[guava-libraries] 01/07: Imported Upstream version 19.0
Emmanuel Bourg
ebourg-guest at moszumanska.debian.org
Fri Dec 18 00:32:46 UTC 2015
This is an automated email from the git hooks/post-receive script.
ebourg-guest pushed a commit to branch master
in repository guava-libraries.
commit 9b06b6f0efee371e43279f679557148446dc77f4
Author: Emmanuel Bourg <ebourg at apache.org>
Date: Fri Dec 18 00:05:28 2015 +0100
Imported Upstream version 19.0
---
.gitattributes | 14 +
.gitignore | 2 +-
.travis.yml | 30 +
AUTHORS | 7 -
CONTRIBUTING.md | 86 +
README | 46 -
README.md | 96 +
guava-gwt/pom.xml | 61 +-
.../super/com/google/common/base/CharMatcher.java | 1573 ++++++++-----
.../super/com/google/common/base/Charsets.java | 2 +-
.../base/super/com/google/common/base/Enums.java | 9 +-
.../super/com/google/common/base/Predicates.java | 142 +-
.../super/com/google/common/base/Splitter.java | 141 +-
.../super/com/google/common/base/Stopwatch.java | 27 +-
.../com/google/common/cache/CacheBuilder.java | 16 +-
.../super/com/google/common/cache/CacheLoader.java | 15 +-
.../super/com/google/common/cache/LocalCache.java | 34 +-
.../com/google/common/collect/AbstractBiMap.java | 123 +-
.../common/collect/AbstractMapBasedMultimap.java | 179 +-
.../common/collect/AbstractMapBasedMultiset.java | 34 +-
.../google/common/collect/ArrayListMultimap.java | 24 +-
.../com/google/common/collect/ArrayTable.java | 102 +-
.../google/common/collect/BinaryTreeTraverser.java | 8 +-
.../com/google/common/collect/ContiguousSet.java | 37 +-
.../google/common/collect/EmptyContiguousSet.java | 55 +-
.../common/collect/EmptyImmutableSortedMap.java | 42 -
.../super/com/google/common/collect/EnumBiMap.java | 31 +-
.../com/google/common/collect/EnumHashBiMap.java | 28 +-
.../com/google/common/collect/EnumMultiset.java | 10 +-
.../com/google/common/collect/FluentIterable.java | 258 ++-
.../com/google/common/collect/GenericMapMaker.java | 2 +-
.../com/google/common/collect/HashMultimap.java | 17 +-
.../com/google/common/collect/HashMultiset.java | 9 +-
.../com/google/common/collect/ImmutableAsList.java | 3 +-
.../com/google/common/collect/ImmutableBiMap.java | 29 +-
.../common/collect/ImmutableListMultimap.java | 118 +-
.../com/google/common/collect/ImmutableMap.java | 221 +-
.../common/collect/ImmutableMapEntrySet.java | 31 +
.../google/common/collect/ImmutableMapKeySet.java | 26 +-
.../google/common/collect/ImmutableMapValues.java | 19 +-
.../google/common/collect/ImmutableMultimap.java | 209 +-
.../google/common/collect/ImmutableMultiset.java | 189 +-
.../com/google/common/collect/ImmutableSet.java | 36 +-
.../common/collect/ImmutableSetMultimap.java | 179 +-
.../common/collect/ImmutableSortedAsList.java | 6 +-
.../google/common/collect/ImmutableSortedMap.java | 58 +-
.../google/common/collect/ImmutableSortedSet.java | 14 +-
.../super/com/google/common/collect/Iterables.java | 139 +-
.../super/com/google/common/collect/Iterators.java | 196 +-
.../google/common/collect/LinkedHashMultimap.java | 56 +-
.../google/common/collect/LinkedHashMultiset.java | 15 +-
.../google/common/collect/LinkedListMultimap.java | 81 +-
.../super/com/google/common/collect/Lists.java | 347 ++-
.../super/com/google/common/collect/MapMaker.java | 2 +-
.../super/com/google/common/collect/Maps.java | 711 +++---
.../super/com/google/common/collect/Multimaps.java | 515 +++--
.../com/google/common/collect/ObjectArrays.java | 9 +-
.../super/com/google/common/collect/Platform.java | 6 +
.../common/collect/RegularContiguousSet.java | 63 +-
.../common/collect/RegularImmutableAsList.java | 5 +-
.../common/collect/RegularImmutableBiMap.java | 9 +
.../google/common/collect/RegularImmutableSet.java | 10 +-
.../super/com/google/common/collect/Sets.java | 369 +--
.../com/google/common/collect/SortedMultisets.java | 30 +-
.../com/google/common/collect/Synchronized.java | 346 +--
.../com/google/common/collect/TreeMultimap.java | 31 +-
.../com/google/common/collect/TreeMultiset.java | 46 +-
.../super/com/google/common/io/BaseEncoding.java | 356 +--
.../super/com/google/common/io/GwtWorkarounds.java | 118 -
.../super/com/google/common/math/DoubleMath.java | 46 +
.../super/com/google/common/math/LongMath.java | 195 +-
.../super/com/google/common/primitives/Chars.java | 51 +-
.../com/google/common/primitives/Doubles.java | 53 +-
.../super/com/google/common/primitives/Floats.java | 58 +-
.../super/com/google/common/primitives/Ints.java | 119 +-
.../super/com/google/common/primitives/Shorts.java | 55 +-
.../google/common/primitives/UnsignedInteger.java | 49 +-
.../common/util/concurrent/AbstractFuture.java | 326 +++
.../util/concurrent/AggregateFutureState.java | 49 +
.../google/common/util/concurrent/Callables.java | 28 +-
.../com/google/common/util/concurrent/Futures.java | 1267 +++++++++++
.../GwtFuturesCatchingSpecialization.java | 73 +
.../common/util/concurrent/InterruptibleTask.java} | 22 +-
.../common/util/concurrent/MoreExecutors.java | 85 +
.../google/common/util/concurrent/Platform.java} | 22 +-
.../common/util/concurrent/Uninterruptibles.java} | 28 +-
guava-gwt/src-super/java/lang/Lang.gwt.xml | 1 +
.../super/java/lang/InterruptedException.java} | 19 +-
.../reflect/UndeclaredThrowableException.java} | 26 +-
.../util/concurrent/CancellationException.java} | 21 +-
.../super/java/util/concurrent/CountDownLatch.java | 55 +
.../util/super/java/util/concurrent/Delayed.java | 18 +
.../util/super/java/util/concurrent/Executor.java} | 18 +-
.../util/super/java/util/concurrent/Executors.java | 50 +
.../util/super/java/util/concurrent/Future.java | 36 +
.../concurrent/RejectedExecutionException.java | 30 +-
.../java/util/concurrent/RunnableFuture.java} | 15 +-
.../java/util/concurrent/ScheduledFuture.java | 19 +
.../util/super/java/util/concurrent/TimeUnit.java | 138 +-
.../java/util/concurrent/TimeoutException.java} | 18 +-
.../java/util/concurrent/atomic/AtomicBoolean.java | 77 +
.../google/common/annotations/Annotations.gwt.xml | 2 +-
guava-gwt/src/com/google/common/base/Base.gwt.xml | 2 +-
.../common/base/GwtSerializationDependencies.java | 34 +-
.../PairwiseEquivalence_CustomFieldSerializer.java | 4 +-
.../AllEqualOrdering_CustomFieldSerializer.java | 6 +-
.../ArrayListMultimap_CustomFieldSerializer.java | 17 +-
.../ByFunctionOrdering_CustomFieldSerializer.java | 18 +-
.../src/com/google/common/collect/Collect.gwt.xml | 6 +-
.../ComparatorOrdering_CustomFieldSerializer.java | 18 +-
.../CompoundOrdering_CustomFieldSerializer.java | 17 +-
.../DenseImmutableTable_CustomFieldSerializer.java | 3 +-
.../EmptyImmutableBiMap_CustomFieldSerializer.java | 38 -
...mmutableListMultimap_CustomFieldSerializer.java | 15 +-
...ImmutableSetMultimap_CustomFieldSerializer.java | 15 +-
.../EmptyImmutableSet_CustomFieldSerializer.java | 41 -
...tyImmutableSortedMap_CustomFieldSerializer.java | 44 -
...tyImmutableSortedSet_CustomFieldSerializer.java | 59 -
.../ExplicitOrdering_CustomFieldSerializer.java | 17 +-
.../collect/GwtSerializationDependencies.java | 22 +-
.../HashBasedTable_CustomFieldSerializer.java | 3 +-
.../HashMultimap_CustomFieldSerializer.java | 16 +-
.../HashMultiset_CustomFieldSerializer.java | 16 +-
.../ImmutableEntry_CustomFieldSerializer.java | 12 +-
.../ImmutableEnumMap_CustomFieldSerializer.java | 10 +-
.../ImmutableEnumSet_CustomFieldSerializer.java | 9 +-
...mmutableListMultimap_CustomFieldSerializer.java | 17 +-
...ImmutableSetMultimap_CustomFieldSerializer.java | 14 +-
.../ImmutableSortedMap_CustomFieldSerializer.java | 19 +-
...icographicalOrdering_CustomFieldSerializer.java | 19 +-
.../LinkedHashMultimap_CustomFieldSerializer.java | 17 +-
.../LinkedHashMultiset_CustomFieldSerializer.java | 16 +-
.../LinkedListMultimap_CustomFieldSerializer.java | 14 +-
.../Multimap_CustomFieldSerializerBase.java | 9 +-
.../Multiset_CustomFieldSerializerBase.java | 7 +-
.../NaturalOrdering_CustomFieldSerializer.java | 13 +-
.../NullsFirstOrdering_CustomFieldSerializer.java | 18 +-
.../NullsLastOrdering_CustomFieldSerializer.java | 17 +-
...gularImmutableAsList_CustomFieldSerializer.java | 13 +-
...egularImmutableBiMap_CustomFieldSerializer.java | 19 +-
...RegularImmutableList_CustomFieldSerializer.java | 13 +-
.../RegularImmutableMap_CustomFieldSerializer.java | 13 +-
...larImmutableMultiset_CustomFieldSerializer.java | 19 +-
.../RegularImmutableSet_CustomFieldSerializer.java | 13 +-
...arImmutableSortedMap_CustomFieldSerializer.java | 44 -
...arImmutableSortedSet_CustomFieldSerializer.java | 19 +-
...verseNaturalOrdering_CustomFieldSerializer.java | 14 +-
.../ReverseOrdering_CustomFieldSerializer.java | 17 +-
...gletonImmutableBiMap_CustomFieldSerializer.java | 12 +-
...ngletonImmutableList_CustomFieldSerializer.java | 15 +-
...ingletonImmutableSet_CustomFieldSerializer.java | 15 +-
...gletonImmutableTable_CustomFieldSerializer.java | 3 +-
...SparseImmutableTable_CustomFieldSerializer.java | 3 +-
.../TreeBasedTable_CustomFieldSerializer.java | 9 +-
.../TreeMultimap_CustomFieldSerializer.java | 12 +-
...singToStringOrdering_CustomFieldSerializer.java | 14 +-
guava-gwt/src/com/google/common/net/Net.gwt.xml | 2 +-
.../UnsignedLong_CustomFieldSerializer.java | 10 +-
.../common/util/concurrent/Concurrent.gwt.xml | 4 +-
.../com/google/common/base/CharMatcherTest.java | 72 +-
.../super/com/google/common/base/EnumsTest.java | 28 +-
.../super/com/google/common/base/JoinerTest.java | 3 +
.../super/com/google/common/base/ObjectsTest.java | 1 +
.../super/com/google/common/base/OptionalTest.java | 16 +-
.../com/google/common/base/PreconditionsTest.java | 39 +-
.../super/com/google/common/base/SplitterTest.java | 147 +-
.../com/google/common/base/StopwatchTest.java | 43 -
.../super/com/google/common/base/StringsTest.java | 4 +
.../super/com/google/common/base/Utf8Test.java | 93 +-
.../com/google/common/cache/CacheBuilderTest.java | 8 +
.../common/collect/AbstractImmutableSetTest.java | 12 +-
.../collect/AbstractSequentialIteratorTest.java | 10 +-
.../common/collect/AbstractTableReadTest.java | 2 +-
.../common/collect/ArrayListMultimapTest.java | 8 +-
.../com/google/common/collect/ArrayTableTest.java | 12 +-
.../google/common/collect/Collections2Test.java | 2 +-
.../google/common/collect/ContiguousSetTest.java | 58 +-
.../com/google/common/collect/EnumBiMapTest.java | 24 +-
.../google/common/collect/EvictingQueueTest.java | 14 +-
.../com/google/common/collect/HashBiMapTest.java | 8 +
.../google/common/collect/ImmutableBiMapTest.java | 52 +-
.../common/collect/ImmutableEnumMapTest.java | 2 +-
.../common/collect/ImmutableListMultimapTest.java | 39 +-
.../google/common/collect/ImmutableMapTest.java | 43 +-
.../common/collect/ImmutableMultimapTest.java | 10 +-
.../common/collect/ImmutableMultisetTest.java | 2 +-
.../common/collect/ImmutableSetMultimapTest.java | 64 +-
.../google/common/collect/ImmutableSetTest.java | 2 +-
.../common/collect/ImmutableSortedMapTest.java | 24 +-
.../common/collect/ImmutableSortedSetTest.java | 104 +-
.../google/common/collect/ImmutableTableTest.java | 48 +-
.../com/google/common/collect/IterablesTest.java | 28 +-
.../com/google/common/collect/IteratorsTest.java | 106 +-
.../common/collect/LinkedHashMultimapTest.java | 30 +-
.../common/collect/LinkedHashMultisetTest.java | 8 +-
.../common/collect/LinkedListMultimapTest.java | 14 +-
.../super/com/google/common/collect/ListsTest.java | 22 +-
.../google/common/collect/MapConstraintsTest.java | 28 +-
.../super/com/google/common/collect/MapsTest.java | 53 +-
.../com/google/common/collect/MultimapsTest.java | 40 +-
.../com/google/common/collect/MultisetsTest.java | 36 +-
.../google/common/collect/ObjectArraysTest.java | 18 +-
.../com/google/common/collect/OrderingTest.java | 34 +-
.../super/com/google/common/collect/SetsTest.java | 33 +-
.../collect/SingletonImmutableTableTest.java | 2 +-
.../google/common/collect/TreeBasedTableTest.java | 8 +-
.../common/collect/TreeMultimapExplicitTest.java | 26 +-
.../common/collect/TreeMultimapNaturalTest.java | 18 +-
.../google/common/collect/TreeMultisetTest.java | 44 +-
.../google/AbstractMultisetSetCountTester.java | 42 +-
.../testing/google/MultisetCountTester.java | 6 +-
.../testing/google/MultisetIteratorTester.java | 27 +-
.../testing/google/MultisetRemoveTester.java | 54 +-
.../google/common/collect/testing/GwtPlatform.java | 5 +-
.../com/google/common/collect/testing/Helpers.java | 96 +
.../testing/testers/CollectionAddAllTester.java | 16 +-
.../testing/testers/CollectionAddTester.java | 12 +-
.../testing/testers/CollectionToArrayTester.java | 8 +-
.../testing/testers/ListAddAtIndexTester.java | 32 +-
.../collect/testing/testers/ListAddTester.java | 6 +-
.../testing/testers/ListListIteratorTester.java | 2 +-
.../collect/testing/testers/ListSetTester.java | 12 +-
.../collect/testing/testers/ListSubListTester.java | 26 +-
.../collect/testing/testers/MapCreationTester.java | 2 +-
.../collect/testing/testers/MapPutAllTester.java | 18 +-
.../collect/testing/testers/MapPutTester.java | 30 +-
.../collect/testing/testers/SetAddTester.java | 2 +-
.../com/google/common/io/BaseEncodingTest.java | 107 +-
.../google/common/net/InternetDomainNameTest.java | 2 +-
.../super/com/google/common/net/MediaTypeTest.java | 9 +-
.../com/google/common/primitives/BooleansTest.java | 2 +
.../com/google/common/primitives/BytesTest.java | 2 +
.../com/google/common/primitives/CharsTest.java | 5 +
.../com/google/common/primitives/DoublesTest.java | 7 +-
.../com/google/common/primitives/FloatsTest.java | 7 +-
.../com/google/common/primitives/IntsTest.java | 54 +
.../com/google/common/primitives/LongsTest.java | 53 +
.../com/google/common/primitives/ShortsTest.java | 6 +
.../google/common/primitives/SignedBytesTest.java | 3 +
.../google/common/primitives/UnsignedIntsTest.java | 28 +-
.../google/common/primitives/UnsignedLongTest.java | 2 +-
.../common/primitives/UnsignedLongsTest.java | 12 +-
.../common/util/concurrent/CallablesTest.java | 30 +-
.../common/util/concurrent/FutureCallbackTest.java | 44 +-
.../google/common/util/concurrent/FuturesTest.java | 1518 +++++++++++++
.../common/util/concurrent/TestPlatform.java | 61 +
.../TrustedListenableFutureTaskTest.java | 79 +
.../com/google/common/base/StopwatchTest_gwt.java | 20 -
.../test/com/google/common/base/Utf8Test_gwt.java | 5 +
.../test/com/google/common/base/testModule.gwt.xml | 2 +-
.../google/common/cache/CacheBuilderTest_gwt.java | 5 +
.../common/collect/ComparisonChainTest_gwt.java | 5 +
.../common/collect/EvictingQueueTest_gwt.java | 65 +
.../google/common/collect/HashBiMapTest_gwt.java | 5 +
.../common/collect/ImmutableBiMapTest_gwt.java | 20 +
.../common/collect/ImmutableMapTest_gwt.java | 15 +
.../common/collect/ImmutableSortedMapTest_gwt.java | 5 +
.../google/common/collect/IteratorsTest_gwt.java | 5 +
.../google/common/collect/OrderingTest_gwt.java | 5 +
.../common/collect/testing/HelpersTest_gwt.java | 30 +
.../google/common/collect/testing/Testing.gwt.xml | 4 +-
.../common/collect/testing/google/Google.gwt.xml | 1 -
.../com/google/common/io/BaseEncodingTest_gwt.java | 20 +
.../test/com/google/common/io/testModule.gwt.xml | 1 +
.../test/com/google/common/math/testModule.gwt.xml | 2 +-
.../test/com/google/common/net/testModule.gwt.xml | 2 +-
.../com/google/common/primitives/IntsTest_gwt.java | 15 +
.../google/common/primitives/LongsTest_gwt.java | 20 +
.../common/primitives/UnsignedIntsTest_gwt.java | 10 +
.../common/primitives/UnsignedLongsTest_gwt.java | 10 +
.../concurrent/CallablesTest_gwt.java} | 12 +-
.../util/concurrent/FutureCallbackTest_gwt.java | 55 +
.../common/util/concurrent/FuturesTest_gwt.java | 2153 ++++++++++++++++++
.../concurrent/TrustedInputFutureTest_gwt.java | 218 ++
.../TrustedListenableFutureTaskTest_gwt.java | 35 +
.../concurrent/UntrustedInputFutureTest_gwt.java | 218 ++
.../common/util/concurrent/testModule.gwt.xml | 4 +-
guava-testlib/pom.xml | 24 +-
.../collect/testing/AbstractContainerTester.java | 22 +-
.../common/collect/testing/AbstractMapTester.java | 42 +-
.../testing/CollectionTestSuiteBuilder.java | 10 +-
.../testing/ConcurrentMapTestSuiteBuilder.java | 52 +
.../ConcurrentNavigableMapTestSuiteBuilder.java | 49 +
.../testing/DerivedCollectionGenerators.java | 24 +-
.../com/google/common/collect/testing/Helpers.java | 96 +
.../collect/testing/ListTestSuiteBuilder.java | 12 +-
.../collect/testing/MapTestSuiteBuilder.java | 2 +-
.../testing/NavigableMapTestSuiteBuilder.java | 69 +-
.../testing/NavigableSetTestSuiteBuilder.java | 10 +-
.../common/collect/testing/OneSizeGenerator.java | 2 +-
.../google/common/collect/testing/Platform.java | 4 +-
.../common/collect/testing/SampleElements.java | 42 +-
.../collect/testing/SetTestSuiteBuilder.java | 10 +-
.../collect/testing/SortedMapTestSuiteBuilder.java | 7 +-
.../collect/testing/TestsForMapsInJavaUtil.java | 9 +-
.../collect/testing/features/FeatureUtil.java | 13 +-
.../testing/google/AbstractListMultimapTester.java | 9 +-
.../testing/google/AbstractMultimapTester.java | 52 +-
.../google/AbstractMultisetSetCountTester.java | 42 +-
.../testing/google/AbstractMultisetTester.java | 2 +-
.../collect/testing/google/BiMapGenerators.java | 7 +
.../collect/testing/google/BiMapPutTester.java | 43 +-
.../collect/testing/google/BiMapRemoveTester.java | 24 +-
.../testing/google/BiMapTestSuiteBuilder.java | 2 +-
.../google/DerivedGoogleCollectionGenerators.java | 14 +-
...etMultimapGetTester.java => GoogleHelpers.java} | 24 +-
.../testing/google/ListMultimapAsMapTester.java | 34 +-
.../testing/google/ListMultimapEqualsTester.java | 12 +-
.../testing/google/ListMultimapPutAllTester.java | 6 +-
.../testing/google/ListMultimapRemoveTester.java | 46 +-
.../google/ListMultimapReplaceValuesTester.java | 6 +-
.../collect/testing/google/MapGenerators.java | 8 +
.../testing/google/MultimapAsMapGetTester.java | 92 +-
.../testing/google/MultimapAsMapTester.java | 57 +-
.../testing/google/MultimapClearTester.java | 37 +-
.../google/MultimapContainsEntryTester.java | 8 +-
.../testing/google/MultimapContainsKeyTester.java | 4 +-
.../google/MultimapContainsValueTester.java | 4 +-
.../testing/google/MultimapEntriesTester.java | 54 +-
.../testing/google/MultimapEqualsTester.java | 2 +-
.../collect/testing/google/MultimapGetTester.java | 106 +-
.../testing/google/MultimapKeySetTester.java | 12 +-
.../collect/testing/google/MultimapKeysTester.java | 60 +-
.../google/MultimapPutAllMultimapTester.java | 46 +-
.../testing/google/MultimapPutIterableTester.java | 82 +-
.../collect/testing/google/MultimapPutTester.java | 91 +-
.../testing/google/MultimapRemoveAllTester.java | 34 +-
.../testing/google/MultimapRemoveEntryTester.java | 26 +-
.../google/MultimapReplaceValuesTester.java | 77 +-
.../collect/testing/google/MultimapSizeTester.java | 9 +-
.../testing/google/MultimapTestSuiteBuilder.java | 24 +-
.../testing/google/MultimapToStringTester.java | 3 +-
.../testing/google/MultimapValuesTester.java | 12 +-
.../collect/testing/google/MultisetAddTester.java | 46 +-
.../testing/google/MultisetContainsTester.java | 4 +-
.../testing/google/MultisetCountTester.java | 6 +-
.../testing/google/MultisetElementSetTester.java | 32 +-
.../testing/google/MultisetEntrySetTester.java | 52 +-
.../testing/google/MultisetIteratorTester.java | 27 +-
.../testing/google/MultisetNavigationTester.java | 12 +-
.../testing/google/MultisetReadsTester.java | 18 +-
.../testing/google/MultisetRemoveTester.java | 56 +-
.../MultisetSetCountConditionallyTester.java | 10 +-
.../testing/google/MultisetTestSuiteBuilder.java | 10 +-
.../testing/google/SetMultimapAsMapTester.java | 34 +-
.../testing/google/SetMultimapEqualsTester.java | 12 +-
.../testing/google/SetMultimapPutAllTester.java | 4 +-
.../testing/google/SetMultimapPutTester.java | 2 +-
.../google/SetMultimapReplaceValuesTester.java | 6 +-
.../testing/google/SortedMapGenerators.java | 7 +
.../google/SortedMultisetTestSuiteBuilder.java | 30 +-
.../testing/google/SortedSetMultimapGetTester.java | 2 +-
.../google/UnmodifiableCollectionTests.java | 7 +-
.../testing/testers/AbstractListIndexOfTester.java | 4 +-
.../testing/testers/CollectionAddAllTester.java | 16 +-
.../testing/testers/CollectionAddTester.java | 12 +-
.../testing/testers/CollectionClearTester.java | 2 +
.../testers/CollectionContainsAllTester.java | 6 +-
.../testing/testers/CollectionContainsTester.java | 6 +-
.../testing/testers/CollectionRemoveAllTester.java | 24 +-
.../testing/testers/CollectionRemoveTester.java | 18 +-
.../testing/testers/CollectionRetainAllTester.java | 20 +-
.../testing/testers/CollectionToArrayTester.java | 8 +-
.../testing/testers/CollectionToStringTester.java | 2 +-
.../testers/ConcurrentMapPutIfAbsentTester.java | 131 ++
.../testing/testers/ConcurrentMapRemoveTester.java | 108 +
.../testers/ConcurrentMapReplaceEntryTester.java | 149 ++
.../testers/ConcurrentMapReplaceTester.java | 105 +
.../testing/testers/ListAddAllAtIndexTester.java | 26 +-
.../collect/testing/testers/ListAddAllTester.java | 10 +-
.../testing/testers/ListAddAtIndexTester.java | 32 +-
.../collect/testing/testers/ListAddTester.java | 6 +-
.../testing/testers/ListCreationTester.java | 2 +-
.../collect/testing/testers/ListEqualsTester.java | 2 +-
.../collect/testing/testers/ListIndexOfTester.java | 4 +-
.../testing/testers/ListLastIndexOfTester.java | 4 +-
.../testing/testers/ListListIteratorTester.java | 2 +-
.../testing/testers/ListRetainAllTester.java | 19 +-
.../collect/testing/testers/ListSetTester.java | 12 +-
.../collect/testing/testers/ListSubListTester.java | 26 +-
.../collect/testing/testers/MapClearTester.java | 2 +
.../testing/testers/MapContainsKeyTester.java | 6 +-
.../testing/testers/MapContainsValueTester.java | 9 +-
.../collect/testing/testers/MapCreationTester.java | 2 +-
.../collect/testing/testers/MapEntrySetTester.java | 24 +-
.../collect/testing/testers/MapEqualsTester.java | 12 +-
.../collect/testing/testers/MapGetTester.java | 6 +-
.../collect/testing/testers/MapHashCodeTester.java | 4 +-
.../collect/testing/testers/MapPutAllTester.java | 18 +-
.../collect/testing/testers/MapPutTester.java | 30 +-
.../collect/testing/testers/MapRemoveTester.java | 20 +-
.../collect/testing/testers/MapToStringTester.java | 2 +-
.../testers/NavigableMapNavigationTester.java | 32 +-
.../testers/NavigableSetNavigationTester.java | 18 +-
.../common/collect/testing/testers/Platform.java | 4 +-
.../testing/testers/QueueElementTester.java | 4 +-
.../collect/testing/testers/QueueOfferTester.java | 4 +-
.../collect/testing/testers/QueuePeekTester.java | 4 +-
.../collect/testing/testers/QueuePollTester.java | 8 +-
.../collect/testing/testers/QueueRemoveTester.java | 8 +-
.../collect/testing/testers/SetAddAllTester.java | 10 +-
.../collect/testing/testers/SetAddTester.java | 2 +-
.../collect/testing/testers/SetCreationTester.java | 4 +-
.../collect/testing/testers/SetEqualsTester.java | 2 +-
.../collect/testing/testers/SetRemoveTester.java | 4 +-
.../testing/testers/SortedMapNavigationTester.java | 30 +-
.../common/testing/AbstractPackageSanityTests.java | 24 +-
.../google/common/testing/ArbitraryInstances.java | 7 +-
.../google/common/testing/ClassSanityTester.java | 24 +-
.../common/testing/ForwardingWrapperTester.java | 10 +-
.../google/common/testing/FreshValueGenerator.java | 510 +++--
.../com/google/common/testing/GcFinalization.java | 18 +-
.../google/common/testing/NullPointerTester.java | 1 -
.../com/google/common/testing/TestLogHandler.java | 21 +-
.../google/common/collect/testing/HelpersTest.java | 129 ++
.../collect/testing/features/FeatureEnumTest.java | 29 +-
.../collect/testing/features/FeatureUtilTest.java | 25 +-
.../testing/AbstractPackageSanityTestsTest.java | 25 +-
.../common/testing/ArbitraryInstancesTest.java | 30 +-
.../common/testing/ClassSanityTesterTest.java | 39 +-
.../google/common/testing/EqualsTesterTest.java | 5 +-
.../common/testing/FreshValueGeneratorTest.java | 343 +--
.../google/common/testing/GcFinalizationTest.java | 6 +-
.../common/testing/NullPointerTesterTest.java | 29 +-
.../google/common/testing/TearDownStackTest.java | 4 +-
.../com/google/common/base/EnumsBenchmark.java | 6 +-
.../common/base/LazyStackTraceBenchmark.java | 93 +
.../com/google/common/base/Utf8Benchmark.java | 172 --
.../common/base/WhitespaceMatcherBenchmark.java | 3 +-
.../common/cache/MapMakerComparisonBenchmark.java | 29 -
.../collect/MultipleSetContainsBenchmark.java | 83 +
.../com/google/common/hash/ChecksumBenchmark.java | 4 +-
.../com/google/common/hash/HashCodeBenchmark.java | 142 ++
.../google/common/hash/HashFunctionBenchmark.java | 10 +-
.../hash/MessageDigestAlgorithmBenchmark.java | 1 +
.../hash/MessageDigestCreationBenchmark.java | 2 +-
.../google/common/io/BaseEncodingBenchmark.java | 108 +
.../AbstractFutureFootprintBenchmark.java | 95 +
.../util/concurrent/ExecutionListBenchmark.java | 116 +-
.../util/concurrent/FuturesCombineBenchmark.java | 147 --
.../concurrent/FuturesGetCheckedBenchmark.java | 188 ++
.../SingleThreadAbstractFutureBenchmark.java | 127 ++
guava-tests/pom.xml | 16 +-
.../com/google/common/base/CharMatcherTest.java | 96 +-
.../test/com/google/common/base/EnumsTest.java | 32 +-
.../common/base/FinalizableReferenceQueueTest.java | 2 +
.../test/com/google/common/base/FunctionsTest.java | 2 +
.../test/com/google/common/base/JoinerTest.java | 3 +
.../test/com/google/common/base/ObjectsTest.java | 1 +
.../test/com/google/common/base/OptionalTest.java | 16 +-
.../com/google/common/base/PreconditionsTest.java | 39 +-
.../com/google/common/base/PredicatesTest.java | 1 +
.../test/com/google/common/base/SplitterTest.java | 189 +-
.../test/com/google/common/base/StopwatchTest.java | 43 -
.../test/com/google/common/base/StringsTest.java | 4 +
.../test/com/google/common/base/SuppliersTest.java | 1 +
.../google/common/base/SuppressUnderAndroid.java | 72 +
.../com/google/common/base/ThrowablesTest.java | 80 +-
.../test/com/google/common/base/Utf8Test.java | 65 +-
.../test/com/google/common/base/VerifyTest.java | 5 +-
.../com/google/common/cache/CacheBuilderTest.java | 22 +-
.../com/google/common/cache/CacheEvictionTest.java | 145 +-
.../google/common/cache/CacheExpirationTest.java | 44 +-
.../com/google/common/cache/CacheLoadingTest.java | 20 +-
.../google/common/cache/CacheReferencesTest.java | 4 +-
.../test/com/google/common/cache/CacheTesting.java | 9 +-
.../com/google/common/cache/LocalCacheTest.java | 113 +-
.../google/common/cache/LocalLoadingCacheTest.java | 12 +-
.../google/common/cache/PopulatedCachesTest.java | 23 +-
.../common/cache/RemovalNotificationTest.java | 8 +-
.../common/collect/AbstractImmutableSetTest.java | 12 +-
.../common/collect/AbstractRangeSetTest.java | 6 +
.../collect/AbstractSequentialIteratorTest.java | 10 +-
.../common/collect/AbstractTableReadTest.java | 2 +-
.../common/collect/ArrayListMultimapTest.java | 8 +-
.../com/google/common/collect/ArrayTableTest.java | 20 +-
.../google/common/collect/Collections2Test.java | 2 +-
.../google/common/collect/ComparisonChainTest.java | 9 +
.../com/google/common/collect/ConstraintsTest.java | 51 +-
.../google/common/collect/ContiguousSetTest.java | 58 +-
.../com/google/common/collect/EnumBiMapTest.java | 24 +-
.../google/common/collect/EvictingQueueTest.java | 4 +
.../com/google/common/collect/FauxveridesTest.java | 19 +-
.../common/collect/FilteredCollectionsTest.java | 10 +-
.../google/common/collect/FluentIterableTest.java | 66 +-
.../google/common/collect/ForwardingListTest.java | 4 +-
.../common/collect/ForwardingMultisetTest.java | 1 +
.../common/collect/ForwardingNavigableMapTest.java | 2 +-
.../com/google/common/collect/HashBiMapTest.java | 101 +
.../google/common/collect/ImmutableBiMapTest.java | 64 +-
.../collect/ImmutableClassToInstanceMapTest.java | 18 +-
.../common/collect/ImmutableEnumMapTest.java | 9 +-
.../common/collect/ImmutableListMultimapTest.java | 59 +-
.../google/common/collect/ImmutableListTest.java | 33 +-
.../google/common/collect/ImmutableMapTest.java | 62 +-
.../common/collect/ImmutableMultimapTest.java | 10 +-
.../common/collect/ImmutableMultisetTest.java | 6 +-
.../common/collect/ImmutableRangeMapTest.java | 30 +
.../common/collect/ImmutableRangeSetTest.java | 17 +-
.../common/collect/ImmutableSetMultimapTest.java | 107 +-
.../google/common/collect/ImmutableSetTest.java | 2 +-
.../common/collect/ImmutableSortedMapTest.java | 36 +-
.../collect/ImmutableSortedMultisetTest.java | 6 +-
.../common/collect/ImmutableSortedSetTest.java | 104 +-
.../google/common/collect/ImmutableTableTest.java | 49 +-
.../com/google/common/collect/IterablesTest.java | 30 +-
.../com/google/common/collect/IteratorsTest.java | 105 +-
.../common/collect/LinkedHashMultimapTest.java | 34 +-
.../common/collect/LinkedHashMultisetTest.java | 8 +-
.../common/collect/LinkedListMultimapTest.java | 14 +-
.../test/com/google/common/collect/ListsTest.java | 24 +-
.../google/common/collect/MapConstraintsTest.java | 28 +-
.../common/collect/MapMakerInternalMapTest.java | 5 +-
.../test/com/google/common/collect/MapsTest.java | 141 +-
.../common/collect/MinMaxPriorityQueueTest.java | 14 +-
.../com/google/common/collect/MultimapsTest.java | 47 +-
.../com/google/common/collect/MultisetsTest.java | 36 +-
.../google/common/collect/NewCustomTableTest.java | 4 +-
.../google/common/collect/ObjectArraysTest.java | 32 +-
.../com/google/common/collect/OrderingTest.java | 34 +-
.../common/collect/RegularImmutableTableTest.java | 2 +-
.../test/com/google/common/collect/SetsTest.java | 45 +-
.../collect/SingletonImmutableTableTest.java | 2 +-
.../common/collect/SuppressUnderAndroid.java | 42 +
.../common/collect/SynchronizedMultimapTest.java | 19 +-
.../google/common/collect/TreeBasedTableTest.java | 8 +-
.../common/collect/TreeMultimapExplicitTest.java | 30 +-
.../common/collect/TreeMultimapNaturalTest.java | 32 +-
.../google/common/collect/TreeMultisetTest.java | 45 +-
.../google/common/collect/TreeRangeMapTest.java | 112 +
.../google/common/collect/TreeRangeSetTest.java | 108 +-
.../com/google/common/escape/EscapersTest.java | 4 +-
.../com/google/common/eventbus/DispatcherTest.java | 177 ++
.../com/google/common/eventbus/EventBusTest.java | 51 +-
.../common/eventbus/EventSubscriberTest.java | 195 --
.../google/common/eventbus/PackageSanityTests.java | 28 +-
.../common/eventbus/SubscriberRegistryTest.java | 203 ++
.../com/google/common/eventbus/SubscriberTest.java | 153 ++
.../outside/AnnotatedSubscriberFinderTests.java | 59 +-
.../com/google/common/hash/BloomFilterTest.java | 17 +-
.../test/com/google/common/hash/HashCodeTest.java | 5 +
.../com/google/common/hash/HashFunctionEnum.java | 1 +
.../test/com/google/common/hash/HashingTest.java | 123 +-
.../common/hash/MessageDigestHashFunctionTest.java | 2 +
.../google/common/hash/SuppressUnderAndroid.java | 42 +
.../com/google/common/io/BaseEncodingTest.java | 124 +-
.../test/com/google/common/io/ByteSinkTester.java | 1 +
.../test/com/google/common/io/ByteSourceTest.java | 79 +-
.../com/google/common/io/ByteSourceTester.java | 36 +-
.../test/com/google/common/io/ByteStreamsTest.java | 68 +-
.../test/com/google/common/io/CharSinkTester.java | 1 +
.../test/com/google/common/io/CharSourceTest.java | 5 +-
.../com/google/common/io/CharSourceTester.java | 13 +
.../test/com/google/common/io/CharStreamsTest.java | 17 -
.../test/com/google/common/io/CloserTest.java | 11 +-
.../google/common/io/CountingInputStreamTest.java | 6 +-
.../test/com/google/common/io/FilesTest.java | 9 +-
.../common/io/LittleEndianDataInputStreamTest.java | 4 +-
.../test/com/google/common/io/ResourcesTest.java | 10 +-
.../com/google/common/io/SourceSinkFactories.java | 6 +-
.../com/google/common/io/SourceSinkTester.java | 1 +
.../com/google/common/io/SuppressUnderAndroid.java | 42 +
.../com/google/common/math/BigIntegerMathTest.java | 12 +-
.../com/google/common/math/DoubleUtilsTest.java | 14 +-
.../test/com/google/common/math/LongMathTest.java | 74 +-
.../google/common/math/SuppressUnderAndroid.java | 42 +
.../com/google/common/net/HostSpecifierTest.java | 4 +-
.../com/google/common/net/InetAddressesTest.java | 10 +-
.../google/common/net/InternetDomainNameTest.java | 2 +-
.../test/com/google/common/net/MediaTypeTest.java | 18 +-
.../com/google/common/net/PercentEscaperTest.java | 5 +-
.../com/google/common/primitives/BooleansTest.java | 2 +
.../com/google/common/primitives/BytesTest.java | 2 +
.../com/google/common/primitives/CharsTest.java | 17 +-
.../com/google/common/primitives/DoublesTest.java | 25 +-
.../com/google/common/primitives/FloatsTest.java | 7 +-
.../com/google/common/primitives/IntsTest.java | 57 +
.../com/google/common/primitives/LongsTest.java | 53 +
.../com/google/common/primitives/ShortsTest.java | 10 +
.../google/common/primitives/SignedBytesTest.java | 3 +
.../common/primitives/UnsignedBytesTest.java | 6 +
.../google/common/primitives/UnsignedIntsTest.java | 28 +-
.../google/common/primitives/UnsignedLongTest.java | 2 +-
.../common/primitives/UnsignedLongsTest.java | 12 +-
.../com/google/common/reflect/ClassPathTest.java | 268 +--
.../reflect/ImmutableTypeToInstanceMapTest.java | 3 +-
.../com/google/common/reflect/InvokableTest.java | 20 +-
.../reflect/MutableTypeToInstanceMapTest.java | 3 +-
.../common/reflect/SuppressUnderAndroid.java | 42 +
.../google/common/reflect/TypeResolverTest.java | 54 +-
.../common/reflect/TypeTokenResolutionTest.java | 4 +-
.../com/google/common/reflect/TypeTokenTest.java | 529 +++--
.../test/com/google/common/reflect/TypesTest.java | 38 +-
.../concurrent/AbstractAbstractFutureTest.java | 490 ++++
.../AbstractExecutionThreadServiceTest.java | 46 +-
.../util/concurrent/AbstractFutureBenchmarks.java | 423 ++++
.../AbstractFutureCancellationCauseTest.java | 91 +
.../AbstractFutureFallbackAtomicHelperTest.java | 145 ++
.../common/util/concurrent/AbstractFutureTest.java | 526 ++++-
.../util/concurrent/AbstractIdleServiceTest.java | 14 +-
.../AbstractListeningExecutorServiceTest.java | 14 +-
.../concurrent/AbstractScheduledServiceTest.java | 143 +-
.../util/concurrent/AbstractServiceTest.java | 7 +-
.../util/concurrent/AsyncSettableFutureTest.java | 193 --
.../common/util/concurrent/CallablesTest.java | 7 +
.../util/concurrent/ForwardingObjectTester.java | 15 +-
.../concurrent/ForwardingObjectTesterTest.java | 3 +
.../common/util/concurrent/FutureCallbackTest.java | 10 +-
.../util/concurrent/FuturesGetCheckedInputs.java | 142 ++
.../util/concurrent/FuturesGetCheckedTest.java | 367 +++
.../util/concurrent/FuturesGetUncheckedTest.java | 107 +
.../google/common/util/concurrent/FuturesTest.java | 2401 ++++++++++++--------
.../util/concurrent/FuturesTransformAsyncTest.java | 187 ++
.../util/concurrent/GeneratedMonitorTest.java | 787 +++++++
.../util/concurrent/ListenableFutureTester.java | 3 +-
.../common/util/concurrent/MoreExecutorsTest.java | 59 +-
.../common/util/concurrent/PackageSanityTests.java | 3 +
.../common/util/concurrent/RateLimiterTest.java | 143 +-
.../util/concurrent/SerializingExecutorTest.java | 112 +-
.../common/util/concurrent/ServiceManagerTest.java | 24 +-
.../google/common/util/concurrent/ServiceTest.java | 4 +-
.../common/util/concurrent/SettableFutureTest.java | 151 ++
.../util/concurrent/SupplementalMonitorTest.java | 145 ++
.../util/concurrent/SuppressUnderAndroid.java | 42 +
.../common/util/concurrent/TestPlatform.java | 69 +
.../util/concurrent/ThreadFactoryBuilderTest.java | 11 +-
.../util/concurrent/TrustedInputFutureTest.java | 18 +-
.../TrustedListenableFutureTaskTest.java | 172 ++
.../util/concurrent/UntrustedInputFutureTest.java | 18 +-
.../concurrent/WrappingExecutorServiceTest.java | 9 +-
.../WrappingScheduledExecutorServiceTest.java | 23 +-
.../com/google/common/xml/XmlEscapersTest.java | 2 +-
guava/pom.xml | 71 +-
guava/src/com/google/common/base/Absent.java | 40 +-
.../com/google/common/base/AbstractIterator.java | 12 +-
guava/src/com/google/common/base/Ascii.java | 8 +-
guava/src/com/google/common/base/CaseFormat.java | 61 +-
guava/src/com/google/common/base/CharMatcher.java | 1783 +++++++++------
guava/src/com/google/common/base/Charsets.java | 2 +-
guava/src/com/google/common/base/Converter.java | 45 +-
guava/src/com/google/common/base/Defaults.java | 4 +-
guava/src/com/google/common/base/Enums.java | 21 +-
guava/src/com/google/common/base/Equivalence.java | 80 +-
.../common/base/FinalizablePhantomReference.java | 2 +-
.../google/common/base/FinalizableReference.java | 2 +-
.../common/base/FinalizableReferenceQueue.java | 31 +-
.../common/base/FinalizableSoftReference.java | 2 +-
.../common/base/FinalizableWeakReference.java | 2 +-
guava/src/com/google/common/base/Function.java | 7 +-
.../google/common/base/FunctionalEquivalence.java | 24 +-
guava/src/com/google/common/base/Functions.java | 101 +-
guava/src/com/google/common/base/Joiner.java | 46 +-
guava/src/com/google/common/base/MoreObjects.java | 97 +-
guava/src/com/google/common/base/Objects.java | 22 +-
guava/src/com/google/common/base/Optional.java | 102 +-
.../google/common/base/PairwiseEquivalence.java | 3 +-
.../src/com/google/common/base/Preconditions.java | 20 +-
guava/src/com/google/common/base/Predicate.java | 4 +-
guava/src/com/google/common/base/Predicates.java | 194 +-
guava/src/com/google/common/base/Present.java | 41 +-
.../com/google/common/base/SmallCharMatcher.java | 24 +-
guava/src/com/google/common/base/Splitter.java | 180 +-
.../google/common/base/StandardSystemProperty.java | 5 +-
guava/src/com/google/common/base/Stopwatch.java | 32 +-
guava/src/com/google/common/base/Strings.java | 17 +-
guava/src/com/google/common/base/Supplier.java | 2 +-
guava/src/com/google/common/base/Suppliers.java | 83 +-
guava/src/com/google/common/base/Throwables.java | 252 +-
guava/src/com/google/common/base/Ticker.java | 18 +-
guava/src/com/google/common/base/Utf8.java | 24 +-
guava/src/com/google/common/base/Verify.java | 6 +-
.../com/google/common/base/VerifyException.java | 22 +-
.../com/google/common/base/internal/Finalizer.java | 43 +-
.../src/com/google/common/cache/AbstractCache.java | 4 -
.../google/common/cache/AbstractLoadingCache.java | 2 -
guava/src/com/google/common/cache/Cache.java | 7 -
.../src/com/google/common/cache/CacheBuilder.java | 19 +-
.../com/google/common/cache/CacheBuilderSpec.java | 15 +-
guava/src/com/google/common/cache/CacheLoader.java | 16 +-
guava/src/com/google/common/cache/CacheStats.java | 3 -
.../com/google/common/cache/ForwardingCache.java | 5 +-
.../common/cache/ForwardingLoadingCache.java | 5 +-
.../src/com/google/common/cache/LoadingCache.java | 11 +-
guava/src/com/google/common/cache/LocalCache.java | 95 +-
.../src/com/google/common/cache/LongAddables.java | 2 +-
.../src/com/google/common/cache/RemovalCause.java | 2 -
.../com/google/common/cache/RemovalListener.java | 5 +-
.../com/google/common/cache/RemovalListeners.java | 3 -
.../google/common/cache/RemovalNotification.java | 16 +-
guava/src/com/google/common/cache/Weigher.java | 2 -
.../src/com/google/common/cache/package-info.java | 2 +-
.../com/google/common/collect/AbstractBiMap.java | 126 +-
.../collect/AbstractIndexedListIterator.java | 3 +-
.../google/common/collect/AbstractIterator.java | 2 +-
.../common/collect/AbstractListMultimap.java | 28 +-
.../common/collect/AbstractMapBasedMultimap.java | 183 +-
.../common/collect/AbstractMapBasedMultiset.java | 35 +-
.../google/common/collect/AbstractMapEntry.java | 9 +-
.../google/common/collect/AbstractMultimap.java | 58 +-
.../google/common/collect/AbstractMultiset.java | 57 +-
.../common/collect/AbstractNavigableMap.java | 34 +-
.../google/common/collect/AbstractRangeSet.java | 2 +-
.../common/collect/AbstractSequentialIterator.java | 5 +-
.../google/common/collect/AbstractSetMultimap.java | 32 +-
.../AbstractSortedKeySortedSetMultimap.java | 7 +-
.../common/collect/AbstractSortedMultiset.java | 14 +-
.../common/collect/AbstractSortedSetMultimap.java | 20 +-
.../com/google/common/collect/AbstractTable.java | 28 +-
.../google/common/collect/ArrayListMultimap.java | 32 +-
.../src/com/google/common/collect/ArrayTable.java | 105 +-
guava/src/com/google/common/collect/BiMap.java | 8 +-
.../google/common/collect/BinaryTreeTraverser.java | 4 +-
.../google/common/collect/ByFunctionOrdering.java | 21 +-
.../com/google/common/collect/CartesianList.java | 10 +-
.../google/common/collect/ClassToInstanceMap.java | 6 +-
.../common/collect/CollectPreconditions.java | 6 +
.../com/google/common/collect/Collections2.java | 135 +-
.../google/common/collect/ComparatorOrdering.java | 12 +-
.../com/google/common/collect/ComparisonChain.java | 150 +-
.../google/common/collect/CompoundOrdering.java | 18 +-
.../common/collect/ComputationException.java | 3 +-
.../common/collect/ComputingConcurrentHashMap.java | 64 +-
.../common/collect/ConcurrentHashMultiset.java | 92 +-
.../src/com/google/common/collect/Constraints.java | 122 +-
.../common/collect/ConsumingQueueIterator.java | 46 +
.../com/google/common/collect/ContiguousSet.java | 48 +-
guava/src/com/google/common/collect/Cut.java | 219 +-
.../google/common/collect/DenseImmutableTable.java | 92 +-
.../collect/DescendingImmutableSortedMultiset.java | 6 +-
.../collect/DescendingImmutableSortedSet.java | 5 +
.../google/common/collect/DescendingMultiset.java | 89 +-
.../com/google/common/collect/DiscreteDomain.java | 68 +-
.../google/common/collect/EmptyContiguousSet.java | 69 +-
.../google/common/collect/EmptyImmutableBiMap.java | 82 -
.../common/collect/EmptyImmutableListMultimap.java | 3 +-
.../google/common/collect/EmptyImmutableSet.java | 97 -
.../common/collect/EmptyImmutableSetMultimap.java | 3 +-
.../common/collect/EmptyImmutableSortedMap.java | 112 -
.../collect/EmptyImmutableSortedMultiset.java | 114 -
.../common/collect/EmptyImmutableSortedSet.java | 130 --
guava/src/com/google/common/collect/EnumBiMap.java | 34 +-
.../com/google/common/collect/EnumHashBiMap.java | 34 +-
.../com/google/common/collect/EnumMultiset.java | 10 +-
.../com/google/common/collect/EvictingQueue.java | 29 +-
.../google/common/collect/ExplicitOrdering.java | 24 +-
.../common/collect/FilteredEntryMultimap.java | 101 +-
.../common/collect/FilteredEntrySetMultimap.java | 6 +-
.../common/collect/FilteredKeyListMultimap.java | 4 +-
.../google/common/collect/FilteredKeyMultimap.java | 4 +-
.../common/collect/FilteredKeySetMultimap.java | 6 +-
.../google/common/collect/FilteredMultimap.java | 4 +-
.../common/collect/FilteredMultimapValues.java | 18 +-
.../google/common/collect/FilteredSetMultimap.java | 2 +-
.../com/google/common/collect/FluentIterable.java | 274 ++-
.../common/collect/ForwardingBlockingDeque.java | 7 +-
.../common/collect/ForwardingCollection.java | 10 +-
.../common/collect/ForwardingConcurrentMap.java | 6 +-
.../com/google/common/collect/ForwardingDeque.java | 6 +-
.../google/common/collect/ForwardingIterator.java | 8 +-
.../com/google/common/collect/ForwardingList.java | 31 +-
.../common/collect/ForwardingListIterator.java | 5 +-
.../common/collect/ForwardingListMultimap.java | 16 +-
.../com/google/common/collect/ForwardingMap.java | 22 +-
.../google/common/collect/ForwardingMapEntry.java | 19 +-
.../google/common/collect/ForwardingMultimap.java | 14 +-
.../google/common/collect/ForwardingMultiset.java | 60 +-
.../common/collect/ForwardingNavigableMap.java | 4 +-
.../common/collect/ForwardingNavigableSet.java | 14 +-
.../google/common/collect/ForwardingObject.java | 5 +-
.../com/google/common/collect/ForwardingQueue.java | 14 +-
.../com/google/common/collect/ForwardingSet.java | 16 +-
.../common/collect/ForwardingSetMultimap.java | 19 +-
.../google/common/collect/ForwardingSortedMap.java | 14 +-
.../common/collect/ForwardingSortedMultiset.java | 12 +-
.../google/common/collect/ForwardingSortedSet.java | 19 +-
.../collect/ForwardingSortedSetMultimap.java | 20 +-
.../com/google/common/collect/ForwardingTable.java | 12 +-
.../com/google/common/collect/GeneralRange.java | 80 +-
.../com/google/common/collect/GenericMapMaker.java | 7 +-
.../com/google/common/collect/GwtTransient.java | 3 +-
.../com/google/common/collect/HashBasedTable.java | 42 +-
guava/src/com/google/common/collect/HashBiMap.java | 279 ++-
.../com/google/common/collect/HashMultimap.java | 25 +-
.../com/google/common/collect/HashMultiset.java | 15 +-
guava/src/com/google/common/collect/Hashing.java | 8 +-
.../com/google/common/collect/ImmutableAsList.java | 12 +-
.../com/google/common/collect/ImmutableBiMap.java | 167 +-
.../collect/ImmutableClassToInstanceMap.java | 62 +-
.../google/common/collect/ImmutableCollection.java | 154 +-
.../com/google/common/collect/ImmutableEntry.java | 14 +-
.../google/common/collect/ImmutableEnumMap.java | 82 +-
.../google/common/collect/ImmutableEnumSet.java | 54 +-
.../com/google/common/collect/ImmutableList.java | 132 +-
.../common/collect/ImmutableListMultimap.java | 133 +-
.../com/google/common/collect/ImmutableMap.java | 328 ++-
.../google/common/collect/ImmutableMapEntry.java | 65 +-
.../common/collect/ImmutableMapEntrySet.java | 40 +
.../google/common/collect/ImmutableMapKeySet.java | 31 +-
.../google/common/collect/ImmutableMapValues.java | 25 +-
.../google/common/collect/ImmutableMultimap.java | 228 +-
.../google/common/collect/ImmutableMultiset.java | 188 +-
.../google/common/collect/ImmutableRangeMap.java | 159 +-
.../google/common/collect/ImmutableRangeSet.java | 77 +-
.../com/google/common/collect/ImmutableSet.java | 296 ++-
.../common/collect/ImmutableSetMultimap.java | 205 +-
.../common/collect/ImmutableSortedAsList.java | 17 +-
.../google/common/collect/ImmutableSortedMap.java | 444 ++--
.../collect/ImmutableSortedMapFauxverideShim.java | 24 +-
.../common/collect/ImmutableSortedMultiset.java | 92 +-
.../ImmutableSortedMultisetFauxverideShim.java | 10 +-
.../google/common/collect/ImmutableSortedSet.java | 133 +-
.../collect/ImmutableSortedSetFauxverideShim.java | 31 +-
.../com/google/common/collect/ImmutableTable.java | 106 +-
guava/src/com/google/common/collect/Interners.java | 30 +-
guava/src/com/google/common/collect/Iterables.java | 143 +-
guava/src/com/google/common/collect/Iterators.java | 203 +-
.../common/collect/LexicographicalOrdering.java | 21 +-
.../google/common/collect/LinkedHashMultimap.java | 65 +-
.../google/common/collect/LinkedHashMultiset.java | 21 +-
.../google/common/collect/LinkedListMultimap.java | 84 +-
.../com/google/common/collect/ListMultimap.java | 6 +-
guava/src/com/google/common/collect/Lists.java | 354 ++-
.../com/google/common/collect/MapConstraint.java | 6 +
.../com/google/common/collect/MapConstraints.java | 418 ++--
.../com/google/common/collect/MapDifference.java | 11 +-
guava/src/com/google/common/collect/MapMaker.java | 48 +-
.../google/common/collect/MapMakerInternalMap.java | 468 ++--
guava/src/com/google/common/collect/Maps.java | 871 ++++---
.../google/common/collect/MinMaxPriorityQueue.java | 139 +-
guava/src/com/google/common/collect/Multimap.java | 32 +-
.../com/google/common/collect/MultimapBuilder.java | 22 +-
guava/src/com/google/common/collect/Multimaps.java | 527 +++--
guava/src/com/google/common/collect/Multiset.java | 22 +-
guava/src/com/google/common/collect/Multisets.java | 279 ++-
.../common/collect/MutableClassToInstanceMap.java | 29 +-
.../com/google/common/collect/NaturalOrdering.java | 12 +-
.../google/common/collect/NullsFirstOrdering.java | 21 +-
.../google/common/collect/NullsLastOrdering.java | 21 +-
.../com/google/common/collect/ObjectArrays.java | 9 +-
guava/src/com/google/common/collect/Ordering.java | 124 +-
.../com/google/common/collect/PeekingIterator.java | 6 +-
guava/src/com/google/common/collect/Platform.java | 24 +-
guava/src/com/google/common/collect/Queues.java | 31 +-
guava/src/com/google/common/collect/Range.java | 103 +-
guava/src/com/google/common/collect/RangeMap.java | 30 +-
guava/src/com/google/common/collect/RangeSet.java | 28 +-
.../common/collect/RegularContiguousSet.java | 72 +-
.../common/collect/RegularImmutableAsList.java | 5 +-
.../common/collect/RegularImmutableBiMap.java | 248 +-
.../common/collect/RegularImmutableList.java | 44 +-
.../google/common/collect/RegularImmutableMap.java | 160 +-
.../common/collect/RegularImmutableMultiset.java | 150 +-
.../google/common/collect/RegularImmutableSet.java | 32 +-
.../common/collect/RegularImmutableSortedMap.java | 130 --
.../collect/RegularImmutableSortedMultiset.java | 41 +-
.../common/collect/RegularImmutableSortedSet.java | 74 +-
.../common/collect/RegularImmutableTable.java | 109 +-
.../common/collect/ReverseNaturalOrdering.java | 36 +-
.../com/google/common/collect/ReverseOrdering.java | 39 +-
.../com/google/common/collect/RowSortedTable.java | 6 +-
.../com/google/common/collect/Serialization.java | 27 +-
.../src/com/google/common/collect/SetMultimap.java | 12 +-
guava/src/com/google/common/collect/Sets.java | 425 ++--
.../common/collect/SingletonImmutableBiMap.java | 22 +-
.../common/collect/SingletonImmutableList.java | 59 +-
.../common/collect/SingletonImmutableSet.java | 37 +-
.../common/collect/SingletonImmutableTable.java | 24 +-
.../src/com/google/common/collect/SortedLists.java | 34 +-
.../com/google/common/collect/SortedMultiset.java | 39 +-
.../common/collect/SortedMultisetBridge.java | 2 +-
.../com/google/common/collect/SortedMultisets.java | 37 +-
.../google/common/collect/SortedSetMultimap.java | 9 +-
.../common/collect/SparseImmutableTable.java | 35 +-
.../common/collect/StandardRowSortedTable.java | 24 +-
.../com/google/common/collect/StandardTable.java | 417 ++--
.../com/google/common/collect/Synchronized.java | 535 +++--
guava/src/com/google/common/collect/Table.java | 9 +-
guava/src/com/google/common/collect/Tables.java | 113 +-
.../com/google/common/collect/TreeBasedTable.java | 101 +-
.../com/google/common/collect/TreeMultimap.java | 46 +-
.../com/google/common/collect/TreeMultiset.java | 59 +-
.../com/google/common/collect/TreeRangeMap.java | 206 +-
.../com/google/common/collect/TreeRangeSet.java | 182 +-
.../com/google/common/collect/TreeTraverser.java | 2 +-
.../common/collect/UnmodifiableIterator.java | 6 +-
.../common/collect/UnmodifiableListIterator.java | 12 +-
.../common/collect/UnmodifiableSortedMultiset.java | 24 +-
.../common/collect/UsingToStringOrdering.java | 9 +-
.../com/google/common/collect/WellBehavedMap.java | 8 +-
.../src/com/google/common/escape/CharEscaper.java | 6 +-
guava/src/com/google/common/escape/Escaper.java | 8 +-
.../com/google/common/escape/UnicodeEscaper.java | 7 +-
.../common/eventbus/AnnotatedSubscriberFinder.java | 169 --
.../com/google/common/eventbus/AsyncEventBus.java | 55 +-
.../src/com/google/common/eventbus/DeadEvent.java | 8 +
.../src/com/google/common/eventbus/Dispatcher.java | 207 ++
guava/src/com/google/common/eventbus/EventBus.java | 318 +--
.../google/common/eventbus/EventSubscriber.java | 115 -
.../src/com/google/common/eventbus/Subscriber.java | 158 ++
.../common/eventbus/SubscriberFindingStrategy.java | 42 -
.../google/common/eventbus/SubscriberRegistry.java | 259 +++
.../eventbus/SynchronizedEventSubscriber.java | 50 -
.../com/google/common/eventbus/package-info.java | 2 +-
.../com/google/common/hash/AbstractByteHasher.java | 1 -
.../common/hash/AbstractCompositeHashFunction.java | 42 +-
.../src/com/google/common/hash/AbstractHasher.java | 15 +-
.../hash/AbstractNonStreamingHashFunction.java | 22 +-
.../common/hash/AbstractStreamingHashFunction.java | 39 +-
guava/src/com/google/common/hash/BloomFilter.java | 137 +-
.../google/common/hash/BloomFilterStrategies.java | 31 +-
.../google/common/hash/ChecksumHashFunction.java | 2 -
.../com/google/common/hash/Crc32cHashFunction.java | 1 -
guava/src/com/google/common/hash/Funnels.java | 69 +-
guava/src/com/google/common/hash/HashCode.java | 85 +-
guava/src/com/google/common/hash/Hasher.java | 55 +-
guava/src/com/google/common/hash/Hashing.java | 162 +-
.../com/google/common/hash/HashingInputStream.java | 4 +
.../google/common/hash/HashingOutputStream.java | 12 +-
.../common/hash/MessageDigestHashFunction.java | 14 +-
.../common/hash/Murmur3_128HashFunction.java | 27 +-
.../google/common/hash/Murmur3_32HashFunction.java | 26 +-
.../com/google/common/hash/SipHashFunction.java | 28 +-
guava/src/com/google/common/hash/package-info.java | 2 +-
guava/src/com/google/common/html/HtmlEscapers.java | 3 +
guava/src/com/google/common/io/BaseEncoding.java | 336 ++-
.../com/google/common/io/ByteArrayDataInput.java | 2 +-
guava/src/com/google/common/io/ByteSource.java | 188 +-
guava/src/com/google/common/io/ByteStreams.java | 117 +-
.../com/google/common/io/CharSequenceReader.java | 2 +-
guava/src/com/google/common/io/CharSource.java | 113 +-
guava/src/com/google/common/io/CharStreams.java | 11 +-
.../com/google/common/io/CountingInputStream.java | 8 +-
.../com/google/common/io/CountingOutputStream.java | 8 +-
guava/src/com/google/common/io/Files.java | 10 +
guava/src/com/google/common/io/GwtWorkarounds.java | 231 --
guava/src/com/google/common/io/package-info.java | 2 +-
guava/src/com/google/common/math/DoubleMath.java | 143 +-
guava/src/com/google/common/math/LongMath.java | 186 +-
guava/src/com/google/common/math/package-info.java | 2 +-
guava/src/com/google/common/net/HttpHeaders.java | 14 +
guava/src/com/google/common/net/InetAddresses.java | 17 +-
guava/src/com/google/common/net/MediaType.java | 48 +-
.../src/com/google/common/primitives/Booleans.java | 60 +-
guava/src/com/google/common/primitives/Bytes.java | 51 +-
guava/src/com/google/common/primitives/Chars.java | 58 +-
.../src/com/google/common/primitives/Doubles.java | 59 +-
guava/src/com/google/common/primitives/Floats.java | 64 +-
guava/src/com/google/common/primitives/Ints.java | 130 +-
guava/src/com/google/common/primitives/Longs.java | 132 +-
.../com/google/common/primitives/ParseRequest.java | 3 +
.../com/google/common/primitives/Primitives.java | 12 +-
guava/src/com/google/common/primitives/Shorts.java | 63 +-
.../com/google/common/primitives/SignedBytes.java | 11 +-
.../google/common/primitives/UnsignedBytes.java | 83 +-
.../google/common/primitives/UnsignedInteger.java | 22 +-
.../com/google/common/primitives/UnsignedInts.java | 22 +-
.../com/google/common/primitives/UnsignedLong.java | 21 +-
.../google/common/primitives/UnsignedLongs.java | 24 +-
.../com/google/common/primitives/package-info.java | 2 +-
guava/src/com/google/common/reflect/ClassPath.java | 270 ++-
guava/src/com/google/common/reflect/Invokable.java | 2 +-
.../com/google/common/reflect/TypeResolver.java | 5 +
guava/src/com/google/common/reflect/TypeToken.java | 411 ++--
guava/src/com/google/common/reflect/Types.java | 96 +-
.../concurrent/AbstractExecutionThreadService.java | 14 +-
.../common/util/concurrent/AbstractFuture.java | 1104 +++++++--
.../util/concurrent/AbstractIdleService.java | 22 +-
.../AbstractListeningExecutorService.java | 17 +-
.../util/concurrent/AbstractScheduledService.java | 98 +-
.../common/util/concurrent/AbstractService.java | 131 +-
.../common/util/concurrent/AggregateFuture.java | 300 +++
.../util/concurrent/AggregateFutureState.java | 99 +
.../common/util/concurrent/AsyncFunction.java | 10 +-
.../util/concurrent/AsyncSettableFuture.java | 100 -
.../common/util/concurrent/AtomicLongMap.java | 9 +-
.../google/common/util/concurrent/Callables.java | 6 +
.../common/util/concurrent/CheckedFuture.java | 16 +-
.../common/util/concurrent/CollectionFuture.java | 90 +
.../util/concurrent/CycleDetectingLockFactory.java | 15 +-
.../common/util/concurrent/ExecutionList.java | 101 +-
.../common/util/concurrent/FutureCallback.java | 3 +
.../common/util/concurrent/FutureFallback.java | 26 +-
.../com/google/common/util/concurrent/Futures.java | 1573 ++++++++-----
.../common/util/concurrent/FuturesGetChecked.java | 309 +++
.../GwtFuturesCatchingSpecialization.java | 33 +
.../common/util/concurrent/InterruptibleTask.java | 71 +
.../common/util/concurrent/JdkFutureAdapters.java | 7 +-
.../common/util/concurrent/ListenableFuture.java | 49 +-
.../com/google/common/util/concurrent/Monitor.java | 191 +-
.../common/util/concurrent/MoreExecutors.java | 142 +-
.../concurrent/Platform.java} | 22 +-
.../google/common/util/concurrent/RateLimiter.java | 15 +-
.../util/concurrent/SerializingExecutor.java | 208 +-
.../common/util/concurrent/ServiceManager.java | 51 +-
.../common/util/concurrent/SettableFuture.java | 41 +-
.../common/util/concurrent/SmoothRateLimiter.java | 161 +-
.../com/google/common/util/concurrent/Striped.java | 10 +-
.../util/concurrent/ThreadFactoryBuilder.java | 10 +-
.../concurrent/TrustedListenableFutureTask.java | 119 +
.../util/concurrent/UncaughtExceptionHandlers.java | 4 +-
.../common/util/concurrent/Uninterruptibles.java | 23 +-
.../util/concurrent/WrappingExecutorService.java | 2 +-
.../publicsuffix/PublicSuffixPatterns.java | 6 +-
mvn-deploy.sh | 40 -
pom.xml | 99 +-
util/deploy_snapshot.sh | 16 +
util/settings.xml | 11 +
util/update_snapshot_docs.sh | 25 +
1008 files changed, 45114 insertions(+), 21927 deletions(-)
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1e3b765
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,14 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+# Known text files
+*.java text
+*.xml text
+*.yml text
+*.md text
+*.sh text
+*.css text
+*.txt text
+
+# Known binary files
+*.jar binary
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 4265c9b..ea9f52f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,4 +14,4 @@ out/
.classpath
.project
.settings/
-.metadata/
+.metadata/
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..43de008
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,30 @@
+sudo: false
+
+language: java
+
+jdk:
+ - oraclejdk8
+ - oraclejdk7
+ - openjdk7
+
+install: mvn install -U -DskipTests=true
+
+script: mvn verify -U -Dmaven.javadoc.skip=true
+
+after_success:
+ - util/deploy_snapshot.sh
+ - util/update_snapshot_docs.sh
+
+cache:
+ directories:
+ - $HOME/.m2
+
+env:
+ global:
+ - secure: "IPvqFwnLx/GXyImJuwM2MIvzDlBLqEXaQXFGJgAP1nbuenaLAloOOlqQ+iy2FDLBD/j+zjSbR3WWF9DIT4YxAS03Z6iMwxh7GCfk+tyhVtLQnwt7w1rquyhbrrGFsY5U0hr5q80Ww6J+zfp2yZ8aP9FHSy5ahNjqys4FtubOWLk="
+ - secure: "G77Wt2h2fceQ867i1uwOjUygrNeBpLRS8sxgfUZsO66dvlrx1wYFpZLLRIiPcy01peUTE2SvXIXLHKe9v3AlMonPibsQtvvfQSVfx+jgKwLZx9cuf/M5VQlD3etRUh4K/rBezlxWRroeeKcM2DQqiEVLsTDSyNZV9kVAjwfLTvM="
+ - secure: "wieIClPLTXS3QjDzqyp0TqIrVP/Q6iWNPOtcUQYfdDZJGwufE61laTFtzVKXZRb7uJ4GXDObcVU3AcpAwkTX/5sEksBxgv3TZ5Qi0mVx2GRmbE06ULLxi7sPnTCZ/VFtselDWcWArWGAcdCjW9gcCrgj5K/+sYpVKz9a8V+SDM4="
+
+branches:
+ except:
+ - gh-pages
diff --git a/AUTHORS b/AUTHORS
deleted file mode 100644
index 324fd82..0000000
--- a/AUTHORS
+++ /dev/null
@@ -1,7 +0,0 @@
-Google Inc.
-Colin Decker
-Emily Soldal
-Louis Wasserman
-Maginatics
-Roman Leventov
-David E. Wheeler
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..f1d6529
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,86 @@
+How to contribute
+=================
+
+Thank you so much for wanting to contribute to Guava! Here are a few important
+things you should know about contributing:
+
+ 1. API changes require discussion, use cases, etc. Code comes later.
+ 2. Pull requests are great for small fixes for bugs, documentation, etc.
+ 3. Pull requests are not merged directly into the master branch.
+ 3. Code contributions require signing a Google CLA.
+
+API changes
+-----------
+
+We make changes to Guava's public [APIs][], including adding new APIs, very
+carefully. Because of this, if you're interested in seeing a new feature in
+Guava, the best approach is to create an [issue][] (or comment on an existing
+issue if there is one) requesting the feature and describing specific use cases
+for it.
+
+If the feature has merit, it will go through a thorough process of API design
+and review. Any code should come after this.
+
+[APIs]: http://en.wikipedia.org/wiki/Application_programming_interface
+[issue]: https://github.com/google/guava/issues
+
+Pull requests
+-------------
+
+Unless the change is a trivial fix such as for a typo, it's generally best to
+start by opening a new issue describing the bug or feature you're intending to
+fix. Even if you think it's relatively minor, it's helpful to know what people
+are working on. And as mentioned above, API changes should be discussed
+thoroughly before moving to code.
+
+Some examples of types of pull requests that are immediately helpful:
+
+ - Fixing a bug without changing a public API.
+ - Fixing or improving documentation.
+ - Improvements to Maven configuration.
+
+Guidelines for any code contributions:
+
+ 1. Any significant changes should be accompanied by tests. The project already
+ has good test coverage, so look at some of the existing tests if you're
+ unsure how to go about it.
+ 2. All contributions must be licensed Apache 2.0 and all files must have a
+ copy of the boilerplate licence comment (can be copied from an existing
+ file).
+ 3. Files should be formatted according to Google's [Java style guide][].
+ 4. Please squash all commits for a change into a single commit (this can be
+ done using `git rebase -i`). Do your best to have a
+ [well-formed commit message][] for the change.
+
+[Java style guide]: http://google-styleguide.googlecode.com/svn/trunk/javaguide.html
+[well-formed commit message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
+
+#### Merging pull requests ####
+
+Due to Guava's nature as a subset of Google's internal codebase which is
+automatically synced to the public GitHub repository, we are unable to merge
+pull requests directly into the master branch. Instead, once a pull request is
+ready for merging, we'll make the appropriate changes in the internal codebase
+and, when the change is synced out, give the pull request author credit for the
+commit.
+
+Contributor License Agreement
+-----------------------------
+
+Contributions to any Google project must be accompanied by a Contributor
+License Agreement. This is not a copyright _assignment_; it simply gives
+Google permission to use and redistribute your contributions as part of the
+project.
+
+ - If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual
+ CLA][]. Please include your GitHub username.
+ - If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA][].
+
+You generally only need to submit a CLA once, so if you've already submitted
+one (even if it was for a different project), you probably don't need to do it
+again.
+
+[individual CLA]: https://cla.developers.google.com/about/google-individual
+[corporate CLA]: https://developers.google.com/open-source/cla/corporate
diff --git a/README b/README
deleted file mode 100644
index f6b5992..0000000
--- a/README
+++ /dev/null
@@ -1,46 +0,0 @@
-Guava: Google Core Libraries for Java
-=====================================
-
-Requires JDK 1.6 or higher (as of 12.0).
-
-Project page:
- http://guava-libraries.googlecode.com
-
-Report a defect or feature request here:
- http://code.google.com/p/guava-libraries/issues/entry
-
-Ask "how-to" and "why-didn't-it-work" questions at:
- http://www.stackoverflow.com/questions/ask (use the "guava" tag)
-
-For open-ended questions and discussion:
- http://groups.google.com/group/guava-discuss
-
-Subscribe to project updates in your feed reader:
- http://code.google.com/feeds/p/guava-libraries/updates/basic
-
-IMPORTANT WARNINGS
-------------------
-
-1. APIs marked with the @Beta annotation at the class or method level
-are subject to change. They can be modified in any way, or even
-removed, at any time. If your code is a library itself (i.e. it is
-used on the CLASSPATH of users outside your own control), you should
-not use beta APIs, unless you repackage them (e.g. using ProGuard).
-
-2. Deprecated non-beta APIs will be removed two years after the
-release in which they are first deprecated. You must fix your
-references before this time. If you don't, any manner of breakage
-could result (you are not guaranteed a compilation error).
-
-3. Serialized forms of ALL objects are subject to change unless noted
-otherwise. Do not persist these and assume they can be read by a
-future version of the library.
-
-4. Our classes are not designed to protect against a malicious caller.
-You should not use them for communication between trusted and
-untrusted code.
-
-5. We unit-test and benchmark the libraries using only OpenJDK 1.7 on
-Linux. Some features, especially in com.google.common.io, may not work
-correctly in other environments.
-
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fb57053
--- /dev/null
+++ b/README.md
@@ -0,0 +1,96 @@
+Guava: Google Core Libraries for Java
+=====================================
+
+[![Build Status](https://travis-ci.org/google/guava.svg?branch=master)](https://travis-ci.org/google/guava)
+[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.google.guava/guava/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.google.guava/guava)
+
+The Guava project contains several of Google's core libraries that we rely on
+in our Java-based projects: collections, caching, primitives support,
+concurrency libraries, common annotations, string processing, I/O, and so forth.
+
+Requires JDK 1.6 or higher (as of 12.0).
+
+Latest release
+--------------
+
+The most recent release is [Guava 18.0][], released August 25, 2014.
+
+- [18.0 API Docs][Release API Docs]
+- [18.0 API Diffs from 17.0][Release API Diffs]
+
+To add a dependency on Guava using Maven, use the following:
+
+```xml
+<dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>18.0</version>
+</dependency>
+```
+
+Upcoming release
+----------------
+
+[Guava 19.0][] is the next release. A release candidate is currently available
+on Maven Central as version `19.0-rc1`, release July 23, 2015.
+
+Snapshots
+---------
+
+Snapshots of Guava built from the `master` branch are available through Maven
+using version `19.0-SNAPSHOT`. API documentation and diffs from version 18.0
+are available here:
+
+- [Snapshot API Docs][]
+- [Snapshot API Diffs from 18.0][Snapshot API Diffs]
+
+Learn about Guava
+------------------
+
+- Our users' guide, [Guava Explained][]
+- [Presentation slides focusing on base, primitives, and io](http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf)
+- [Presentation slides focusing on cache]( http://guava-libraries.googlecode.com/files/JavaCachingwithGuava.pdf)
+- [Presentation slides focusing on util.concurrent](http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf)
+- [A nice collection](http://www.tfnico.com/presentations/google-guava) of other helpful links
+
+Links
+-----
+
+- [GitHub project](https://github.com/google/guava)
+- [Issue tracker: report a defect or feature request](https://github.com/google/guava/issues/new)
+- [StackOverflow: Ask "how-to" and "why-didn't-it-work" questions](https://stackoverflow.com/questions/ask?tags=guava+java)
+- [guava-discuss: For open-ended questions and discussion](http://groups.google.com/group/guava-discuss)
+
+IMPORTANT WARNINGS
+------------------
+
+1. APIs marked with the `@Beta` annotation at the class or method level
+are subject to change. They can be modified in any way, or even
+removed, at any time. If your code is a library itself (i.e. it is
+used on the CLASSPATH of users outside your own control), you should
+not use beta APIs, unless you repackage them (e.g. using ProGuard).
+
+2. Deprecated non-beta APIs will be removed two years after the
+release in which they are first deprecated. You must fix your
+references before this time. If you don't, any manner of breakage
+could result (you are not guaranteed a compilation error).
+
+3. Serialized forms of ALL objects are subject to change unless noted
+otherwise. Do not persist these and assume they can be read by a
+future version of the library.
+
+4. Our classes are not designed to protect against a malicious caller.
+You should not use them for communication between trusted and
+untrusted code.
+
+5. We unit-test and benchmark the libraries using only OpenJDK 1.7 on
+Linux. Some features, especially in `com.google.common.io`, may not work
+correctly in other environments.
+
+[Guava 18.0]: https://github.com/google/guava/wiki/Release18
+[Guava 19.0]: https://github.com/google/guava/wiki/Release19
+[Release API Docs]: http://google.github.io/guava/releases/18.0/api/docs/
+[Release API Diffs]: http://google.github.io/guava/releases/18.0/api/diffs/
+[Snapshot API Docs]: http://google.github.io/guava/releases/snapshot/api/docs/
+[Snapshot API Diffs]: http://google.github.io/guava/releases/snapshot/api/diffs/
+[Guava Explained]: https://github.com/google/guava/wiki/Home
diff --git a/guava-gwt/pom.xml b/guava-gwt/pom.xml
index f98a731..34c3013 100644
--- a/guava-gwt/pom.xml
+++ b/guava-gwt/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>com.google.guava</groupId>
<artifactId>guava-parent</artifactId>
- <version>18.0</version>
+ <version>19.0</version>
</parent>
<artifactId>guava-gwt</artifactId>
<name>Guava GWT compatible libs</name>
@@ -19,6 +19,7 @@
<properties>
<gwt.test.include>**/GwtTestSuite.java</gwt.test.include>
<gwt.version>2.6.1</gwt.version>
+ <gwt.logLevel>WARN</gwt.logLevel>
</properties>
<dependencies>
<!-- GWT requires a library's transitive dependencies to be present when
@@ -30,6 +31,17 @@
<optional>false</optional>
</dependency>
<dependency>
+ <groupId>com.google.errorprone</groupId>
+ <artifactId>error_prone_annotations</artifactId>
+ <optional>false</optional>
+ </dependency>
+ <dependency>
+ <groupId>com.google.j2objc</groupId>
+ <artifactId>j2objc-annotations</artifactId>
+ <optional>false</optional>
+ </dependency>
+
+ <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${project.version}</version>
@@ -51,7 +63,7 @@
<groupId>com.google.guava</groupId>
<artifactId>guava-tests</artifactId>
<version>${project.version}</version>
- <classifier>tests</classifier>
+ <classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
@@ -105,7 +117,6 @@
<configuration>
<includeArtifactIds>guava</includeArtifactIds>
<classifier>sources</classifier>
- <overWrite>true</overWrite>
<excludeTransitive>true</excludeTransitive>
<excludes>META-INF/MANIFEST.MF</excludes>
<outputDirectory>${project.build.directory}/guava-sources</outputDirectory>
@@ -120,7 +131,6 @@
<configuration>
<includeArtifactIds>guava-testlib</includeArtifactIds>
<classifier>sources</classifier>
- <overWrite>true</overWrite>
<excludeTransitive>true</excludeTransitive>
<excludes>META-INF/MANIFEST.MF</excludes>
<outputDirectory>${project.build.directory}/guava-test-sources</outputDirectory>
@@ -135,7 +145,6 @@
<configuration>
<includeArtifactIds>guava-testlib</includeArtifactIds>
<classifier>test-sources</classifier>
- <overWrite>true</overWrite>
<excludeTransitive>true</excludeTransitive>
<excludes>META-INF/MANIFEST.MF</excludes>
<outputDirectory>${project.build.directory}/guava-test-sources</outputDirectory>
@@ -150,7 +159,6 @@
<configuration>
<includeArtifactIds>guava-tests</includeArtifactIds>
<classifier>test-sources</classifier>
- <overWrite>true</overWrite>
<excludeTransitive>true</excludeTransitive>
<excludes>META-INF/MANIFEST.MF</excludes>
<outputDirectory>${project.build.directory}/guava-test-sources</outputDirectory>
@@ -190,6 +198,7 @@
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
+ <id>copy-gwt-files</id>
<phase>generate-resources</phase>
<goals><goal>run</goal></goals>
<configuration>
@@ -229,10 +238,45 @@
</goals>
<configuration>
<module>com.google.common.ForceGuavaCompilation</module>
- <strict>true</strict>
+ <failOnError>true</failOnError>
+ <logLevel>${gwt.logLevel}</logLevel>
<validateOnly>true</validateOnly>
+ <sourceLevel>1.6</sourceLevel>
</configuration>
</execution>
+ <!--
+ GWT issues some scary warnings while running tests, but I believe they are harmless.
+ Let's take the warnings for one module, c.g.c.base.testModule, as an example:
+
+ [INFO] Validating units:
+ [INFO] Ignored 53 units with compilation errors in first pass.
+ [INFO] Compile with -strict or with -logLevel set to TRACE or DEBUG to see all errors.
+
+ Turning up the log level, we see that GWT is trying to compile classes from other
+ packages, like RangeTest. The reason for this is that GWT doesn't distinguish between
+ .java files in c.g.c.collect.Collect, a module that the c.g.c.base test module inherits,
+ and .java files in c.g.c.collect.testModule, one that it doesn't[*]. Consequently,
+ c.g.c.base.testModule transitively pulls in .java files from both modules while reading
+ the module description of only the prod module. And the prod module doesn't inherit all
+ the modules that the test module classes use, so we get errors.
+
+ The good news is that, despite ignoring errors here, GWT does fail if any errors affect
+ classes that are actually used in the module under test.
+
+ One way to eliminate the warnings is to make base.testModule include the not really
+ necessary <inherits> lines for c.g.c.collect.testModule, etc. However, adding <inherits>
+ lines could make c.g.c.base.testModule transitively inherit from extra modules. If some
+ of those modules are ones that it uses but forgets to list in its own <inherits>, we'd
+ like to get an error. Currently we do, but if we add the extra <inherits> lines, we
+ won't.
+
+ I have one idea for a better approach, but it's painful, and I haven't tested it: We
+ could postprocess Collect.gwt.xml to add <skip> lines for all the files that should be
+ covered by testModule.gwt.xml. Maybe I'll try it someday.
+
+ [*] https://code.google.com/p/google-web-toolkit/wiki/ResourceOracle#When_multiple_PathPrefix_es_have_the_same_path
+ https://code.google.com/p/google-web-toolkit/issues/detail?id=7581
+ -->
<execution>
<id>gwt-test</id>
<goals>
@@ -240,11 +284,12 @@
</goals>
<configuration>
<module>com.google.common.GuavaTests</module>
- <strict>true</strict>
<includes>${gwt.test.include}</includes>
+ <logLevel>${gwt.logLevel}</logLevel>
<mode>htmlunit</mode>
<testTimeOut>600</testTimeOut>
<extraJvmArgs>-Xms3500m -Xmx3500m -Xss1024k</extraJvmArgs>
+ <sourceLevel>1.6</sourceLevel>
</configuration>
</execution>
</executions>
diff --git a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/CharMatcher.java b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/CharMatcher.java
index e3c0b04..7ebbef5 100644
--- a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/CharMatcher.java
+++ b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/CharMatcher.java
@@ -18,9 +18,11 @@ package com.google.common.base;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkPositionIndex;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.VisibleForTesting;
import java.util.Arrays;
@@ -40,11 +42,11 @@ import javax.annotation.CheckReturnValue;
* treats these just as two separate characters.
*
* <p>Example usages: <pre>
- * String trimmed = {@link #WHITESPACE WHITESPACE}.{@link #trimFrom trimFrom}(userInput);
- * if ({@link #ASCII ASCII}.{@link #matchesAllOf matchesAllOf}(s)) { ... }</pre>
+ * String trimmed = {@link #whitespace() whitespace()}.{@link #trimFrom trimFrom}(userInput);
+ * if ({@link #ascii() ascii()}.{@link #matchesAllOf matchesAllOf}(s)) { ... }</pre>
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/StringsExplained#CharMatcher">
+ * "https://github.com/google/guava/wiki/StringsExplained#charmatcher">
* {@code CharMatcher}</a>.
*
* @author Kevin Bourrillion
@@ -54,184 +56,144 @@ import javax.annotation.CheckReturnValue;
@GwtCompatible(emulated = true)
public abstract class CharMatcher implements Predicate<Character> {
- // Constants
+ // Constant matcher factory methods
+
/**
- * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
- * interpreted as a break between words for formatting purposes). See {@link #WHITESPACE} for a
- * discussion of that term.
+ * Matches any character.
*
- * @since 2.0
+ * @since 19.0 (since 1.0 as constant {@code ANY})
*/
- public static final CharMatcher BREAKING_WHITESPACE = new CharMatcher() {
- @Override
- public boolean matches(char c) {
- switch (c) {
- case '\t':
- case '\n':
- case '\013':
- case '\f':
- case '\r':
- case ' ':
- case '\u0085':
- case '\u1680':
- case '\u2028':
- case '\u2029':
- case '\u205f':
- case '\u3000':
- return true;
- case '\u2007':
- return false;
- default:
- return c >= '\u2000' && c <= '\u200a';
- }
- }
-
- @Override
- public String toString() {
- return "CharMatcher.BREAKING_WHITESPACE";
- }
- };
+ public static CharMatcher any() {
+ return Any.INSTANCE;
+ }
/**
- * Determines whether a character is ASCII, meaning that its code point is less than 128.
+ * Matches no characters.
+ *
+ * @since 19.0 (since 1.0 as constant {@code NONE})
*/
- public static final CharMatcher ASCII = inRange('\0', '\u007f', "CharMatcher.ASCII");
-
- private static class RangesMatcher extends CharMatcher {
- private final char[] rangeStarts;
- private final char[] rangeEnds;
-
- RangesMatcher(String description, char[] rangeStarts, char[] rangeEnds) {
- super(description);
- this.rangeStarts = rangeStarts;
- this.rangeEnds = rangeEnds;
- checkArgument(rangeStarts.length == rangeEnds.length);
- for (int i = 0; i < rangeStarts.length; i++) {
- checkArgument(rangeStarts[i] <= rangeEnds[i]);
- if (i + 1 < rangeStarts.length) {
- checkArgument(rangeEnds[i] < rangeStarts[i + 1]);
- }
- }
- }
+ public static CharMatcher none() {
+ return None.INSTANCE;
+ }
- @Override
- public boolean matches(char c) {
- int index = Arrays.binarySearch(rangeStarts, c);
- if (index >= 0) {
- return true;
- } else {
- index = ~index - 1;
- return index >= 0 && c <= rangeEnds[index];
- }
- }
+ /**
+ * Determines whether a character is whitespace according to the latest Unicode standard, as
+ * illustrated <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
+ * This is not the same definition used by other Java APIs. (See a <a
+ * href="http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">comparison of several
+ * definitions of "whitespace"</a>.)
+ *
+ * <p><b>Note:</b> as the Unicode definition evolves, we will modify this matcher to keep it up
+ * to date.
+ *
+ * @since 19.0 (since 1.0 as constant {@code WHITESPACE})
+ */
+ public static CharMatcher whitespace() {
+ return Whitespace.INSTANCE;
}
- // Must be in ascending order.
- private static final String ZEROES = "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66\u0be6"
- + "\u0c66\u0ce6\u0d66\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810\u1946\u19d0\u1b50\u1bb0"
- + "\u1c40\u1c50\ua620\ua8d0\ua900\uaa50\uff10";
+ /**
+ * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
+ * interpreted as a break between words for formatting purposes). See {@link #whitespace()} for a
+ * discussion of that term.
+ *
+ * @since 19.0 (since 2.0 as constant {@code BREAKING_WHITESPACE})
+ */
+ public static CharMatcher breakingWhitespace() {
+ return BreakingWhitespace.INSTANCE;
+ }
- private static final String NINES;
- static {
- StringBuilder builder = new StringBuilder(ZEROES.length());
- for (int i = 0; i < ZEROES.length(); i++) {
- builder.append((char) (ZEROES.charAt(i) + 9));
- }
- NINES = builder.toString();
+ /**
+ * Determines whether a character is ASCII, meaning that its code point is less than 128.
+ *
+ * @since 19.0 (since 1.0 as constant {@code ASCII})
+ */
+ public static CharMatcher ascii() {
+ return Ascii.INSTANCE;
}
/**
* Determines whether a character is a digit according to
* <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D">Unicode</a>.
* If you only care to match ASCII digits, you can use {@code inRange('0', '9')}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code DIGIT})
*/
- public static final CharMatcher DIGIT = new RangesMatcher(
- "CharMatcher.DIGIT", ZEROES.toCharArray(), NINES.toCharArray());
+ public static CharMatcher digit() {
+ return Digit.INSTANCE;
+ }
/**
* Determines whether a character is a digit according to {@linkplain Character#isDigit(char)
- * Java's definition}. If you only care to match ASCII digits, you can use {@code
- * inRange('0', '9')}.
+ * Java's definition}. If you only care to match ASCII digits, you can use {@code inRange('0',
+ * '9')}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code JAVA_DIGIT})
*/
- public static final CharMatcher JAVA_DIGIT = new CharMatcher("CharMatcher.JAVA_DIGIT") {
- @Override public boolean matches(char c) {
- return Character.isDigit(c);
- }
- };
+ public static CharMatcher javaDigit() {
+ return JavaDigit.INSTANCE;
+ }
/**
* Determines whether a character is a letter according to {@linkplain Character#isLetter(char)
* Java's definition}. If you only care to match letters of the Latin alphabet, you can use {@code
* inRange('a', 'z').or(inRange('A', 'Z'))}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code JAVA_LETTER})
*/
- public static final CharMatcher JAVA_LETTER = new CharMatcher("CharMatcher.JAVA_LETTER") {
- @Override public boolean matches(char c) {
- return Character.isLetter(c);
- }
- };
+ public static CharMatcher javaLetter() {
+ return JavaLetter.INSTANCE;
+ }
/**
* Determines whether a character is a letter or digit according to {@linkplain
* Character#isLetterOrDigit(char) Java's definition}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code JAVA_LETTER_OR_DIGIT}).
*/
- public static final CharMatcher JAVA_LETTER_OR_DIGIT =
- new CharMatcher("CharMatcher.JAVA_LETTER_OR_DIGIT") {
- @Override public boolean matches(char c) {
- return Character.isLetterOrDigit(c);
- }
- };
+ public static CharMatcher javaLetterOrDigit() {
+ return JavaLetterOrDigit.INSTANCE;
+ }
/**
* Determines whether a character is upper case according to {@linkplain
* Character#isUpperCase(char) Java's definition}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code JAVA_UPPER_CASE})
*/
- public static final CharMatcher JAVA_UPPER_CASE =
- new CharMatcher("CharMatcher.JAVA_UPPER_CASE") {
- @Override public boolean matches(char c) {
- return Character.isUpperCase(c);
- }
- };
+ public static CharMatcher javaUpperCase() {
+ return JavaUpperCase.INSTANCE;
+ }
/**
* Determines whether a character is lower case according to {@linkplain
* Character#isLowerCase(char) Java's definition}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code JAVA_LOWER_CASE})
*/
- public static final CharMatcher JAVA_LOWER_CASE =
- new CharMatcher("CharMatcher.JAVA_LOWER_CASE") {
- @Override public boolean matches(char c) {
- return Character.isLowerCase(c);
- }
- };
+ public static CharMatcher javaLowerCase() {
+ return JavaLowerCase.INSTANCE;
+ }
/**
* Determines whether a character is an ISO control character as specified by {@link
* Character#isISOControl(char)}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code JAVA_ISO_CONTROL})
*/
- public static final CharMatcher JAVA_ISO_CONTROL =
- inRange('\u0000', '\u001f')
- .or(inRange('\u007f', '\u009f'))
- .withToString("CharMatcher.JAVA_ISO_CONTROL");
+ public static CharMatcher javaIsoControl() {
+ return JavaIsoControl.INSTANCE;
+ }
/**
* Determines whether a character is invisible; that is, if its Unicode category is any of
* SPACE_SEPARATOR, LINE_SEPARATOR, PARAGRAPH_SEPARATOR, CONTROL, FORMAT, SURROGATE, and
* PRIVATE_USE according to ICU4J.
+ *
+ * @since 19.0 (since 1.0 as constant {@code INVISIBLE})
*/
- public static final CharMatcher INVISIBLE = new RangesMatcher("CharMatcher.INVISIBLE", (
- "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u1680\u180e\u2000\u2028\u205f\u2066\u2067\u2068"
- + "\u2069\u206a\u3000\ud800\ufeff\ufff9\ufffa").toCharArray(), (
- "\u0020\u00a0\u00ad\u0604\u061c\u06dd\u070f\u1680\u180e\u200f\u202f\u2064\u2066\u2067\u2068"
- + "\u2069\u206f\u3000\uf8ff\ufeff\ufff9\ufffb").toCharArray());
-
- private static String showCharacter(char c) {
- String hex = "0123456789ABCDEF";
- char[] tmp = {'\\', 'u', '\0', '\0', '\0', '\0'};
- for (int i = 0; i < 4; i++) {
- tmp[5 - i] = hex.charAt(c & 0xF);
- c >>= 4;
- }
- return String.copyValueOf(tmp);
-
+ public static CharMatcher invisible() {
+ return Invisible.INSTANCE;
}
/**
@@ -239,170 +201,111 @@ public abstract class CharMatcher implements Predicate<Character> {
* errs on the side of returning {@code false} (that is, it tends to assume a character is
* double-width).
*
- * <p><b>Note:</b> as the reference file evolves, we will modify this constant to keep it up to
+ * <p><b>Note:</b> as the reference file evolves, we will modify this matcher to keep it up to
* date.
+ *
+ * @since 19.0 (since 1.0 as constant {@code SINGLE_WIDTH})
*/
- public static final CharMatcher SINGLE_WIDTH = new RangesMatcher("CharMatcher.SINGLE_WIDTH",
- "\u0000\u05be\u05d0\u05f3\u0600\u0750\u0e00\u1e00\u2100\ufb50\ufe70\uff61".toCharArray(),
- "\u04f9\u05be\u05ea\u05f4\u06ff\u077f\u0e7f\u20af\u213a\ufdff\ufeff\uffdc".toCharArray());
-
- /** Matches any character. */
- public static final CharMatcher ANY =
- new FastMatcher("CharMatcher.ANY") {
- @Override public boolean matches(char c) {
- return true;
- }
+ public static CharMatcher singleWidth() {
+ return SingleWidth.INSTANCE;
+ }
- @Override public int indexIn(CharSequence sequence) {
- return (sequence.length() == 0) ? -1 : 0;
- }
+ // Legacy constants
+ // TODO(cgdecker): Deprecate these so they can be removed eventually
- @Override public int indexIn(CharSequence sequence, int start) {
- int length = sequence.length();
- Preconditions.checkPositionIndex(start, length);
- return (start == length) ? -1 : start;
- }
+ /**
+ * Determines whether a character is whitespace according to the latest Unicode standard, as
+ * illustrated <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
+ * This is not the same definition used by other Java APIs. (See a <a
+ * href="http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">comparison of several
+ * definitions of "whitespace"</a>.)
+ *
+ * <p><b>Note:</b> as the Unicode definition evolves, we will modify this constant to keep it up
+ * to date.
+ */
+ public static final CharMatcher WHITESPACE = whitespace();
- @Override public int lastIndexIn(CharSequence sequence) {
- return sequence.length() - 1;
- }
+ /**
+ * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
+ * interpreted as a break between words for formatting purposes). See {@link #WHITESPACE} for a
+ * discussion of that term.
+ *
+ * @since 2.0
+ */
+ public static final CharMatcher BREAKING_WHITESPACE = breakingWhitespace();
- @Override public boolean matchesAllOf(CharSequence sequence) {
- checkNotNull(sequence);
- return true;
- }
+ /**
+ * Determines whether a character is ASCII, meaning that its code point is less than 128.
+ */
+ public static final CharMatcher ASCII = ascii();
- @Override public boolean matchesNoneOf(CharSequence sequence) {
- return sequence.length() == 0;
- }
+ /**
+ * Determines whether a character is a digit according to
+ * <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D">Unicode</a>.
+ * If you only care to match ASCII digits, you can use {@code inRange('0', '9')}.
+ */
+ public static final CharMatcher DIGIT = digit();
- @Override public String removeFrom(CharSequence sequence) {
- checkNotNull(sequence);
- return "";
- }
+ /**
+ * Determines whether a character is a digit according to {@linkplain Character#isDigit(char)
+ * Java's definition}. If you only care to match ASCII digits, you can use {@code
+ * inRange('0', '9')}.
+ */
+ public static final CharMatcher JAVA_DIGIT = javaDigit();
- @Override public String replaceFrom(CharSequence sequence, char replacement) {
- char[] array = new char[sequence.length()];
- Arrays.fill(array, replacement);
- return new String(array);
- }
+ /**
+ * Determines whether a character is a letter according to {@linkplain Character#isLetter(char)
+ * Java's definition}. If you only care to match letters of the Latin alphabet, you can use {@code
+ * inRange('a', 'z').or(inRange('A', 'Z'))}.
+ */
+ public static final CharMatcher JAVA_LETTER = javaLetter();
- @Override public String replaceFrom(CharSequence sequence, CharSequence replacement) {
- StringBuilder retval = new StringBuilder(sequence.length() * replacement.length());
- for (int i = 0; i < sequence.length(); i++) {
- retval.append(replacement);
- }
- return retval.toString();
- }
+ /**
+ * Determines whether a character is a letter or digit according to {@linkplain
+ * Character#isLetterOrDigit(char) Java's definition}.
+ */
+ public static final CharMatcher JAVA_LETTER_OR_DIGIT = javaLetterOrDigit();
- @Override public String collapseFrom(CharSequence sequence, char replacement) {
- return (sequence.length() == 0) ? "" : String.valueOf(replacement);
- }
+ /**
+ * Determines whether a character is upper case according to {@linkplain
+ * Character#isUpperCase(char) Java's definition}.
+ */
+ public static final CharMatcher JAVA_UPPER_CASE = javaUpperCase();
- @Override public String trimFrom(CharSequence sequence) {
- checkNotNull(sequence);
- return "";
- }
+ /**
+ * Determines whether a character is lower case according to {@linkplain
+ * Character#isLowerCase(char) Java's definition}.
+ */
+ public static final CharMatcher JAVA_LOWER_CASE = javaLowerCase();
- @Override public int countIn(CharSequence sequence) {
- return sequence.length();
- }
+ /**
+ * Determines whether a character is an ISO control character as specified by {@link
+ * Character#isISOControl(char)}.
+ */
+ public static final CharMatcher JAVA_ISO_CONTROL = javaIsoControl();
- @Override public CharMatcher and(CharMatcher other) {
- return checkNotNull(other);
- }
+ /**
+ * Determines whether a character is invisible; that is, if its Unicode category is any of
+ * SPACE_SEPARATOR, LINE_SEPARATOR, PARAGRAPH_SEPARATOR, CONTROL, FORMAT, SURROGATE, and
+ * PRIVATE_USE according to ICU4J.
+ */
+ public static final CharMatcher INVISIBLE = invisible();
- @Override public CharMatcher or(CharMatcher other) {
- checkNotNull(other);
- return this;
- }
+ /**
+ * Determines whether a character is single-width (not double-width). When in doubt, this matcher
+ * errs on the side of returning {@code false} (that is, it tends to assume a character is
+ * double-width).
+ *
+ * <p><b>Note:</b> as the reference file evolves, we will modify this constant to keep it up to
+ * date.
+ */
+ public static final CharMatcher SINGLE_WIDTH = singleWidth();
- @Override public CharMatcher negate() {
- return NONE;
- }
- };
+ /** Matches any character. */
+ public static final CharMatcher ANY = any();
/** Matches no characters. */
- public static final CharMatcher NONE =
- new FastMatcher("CharMatcher.NONE") {
- @Override public boolean matches(char c) {
- return false;
- }
-
- @Override public int indexIn(CharSequence sequence) {
- checkNotNull(sequence);
- return -1;
- }
-
- @Override public int indexIn(CharSequence sequence, int start) {
- int length = sequence.length();
- Preconditions.checkPositionIndex(start, length);
- return -1;
- }
-
- @Override public int lastIndexIn(CharSequence sequence) {
- checkNotNull(sequence);
- return -1;
- }
-
- @Override public boolean matchesAllOf(CharSequence sequence) {
- return sequence.length() == 0;
- }
-
- @Override public boolean matchesNoneOf(CharSequence sequence) {
- checkNotNull(sequence);
- return true;
- }
-
- @Override public String removeFrom(CharSequence sequence) {
- return sequence.toString();
- }
-
- @Override public String replaceFrom(CharSequence sequence, char replacement) {
- return sequence.toString();
- }
-
- @Override public String replaceFrom(CharSequence sequence, CharSequence replacement) {
- checkNotNull(replacement);
- return sequence.toString();
- }
-
- @Override public String collapseFrom(CharSequence sequence, char replacement) {
- return sequence.toString();
- }
-
- @Override public String trimFrom(CharSequence sequence) {
- return sequence.toString();
- }
-
- @Override
- public String trimLeadingFrom(CharSequence sequence) {
- return sequence.toString();
- }
-
- @Override
- public String trimTrailingFrom(CharSequence sequence) {
- return sequence.toString();
- }
-
- @Override public int countIn(CharSequence sequence) {
- checkNotNull(sequence);
- return 0;
- }
-
- @Override public CharMatcher and(CharMatcher other) {
- checkNotNull(other);
- return this;
- }
-
- @Override public CharMatcher or(CharMatcher other) {
- return checkNotNull(other);
- }
-
- @Override public CharMatcher negate() {
- return ANY;
- }
- };
+ public static final CharMatcher NONE = none();
// Static factories
@@ -410,28 +313,7 @@ public abstract class CharMatcher implements Predicate<Character> {
* Returns a {@code char} matcher that matches only one specified character.
*/
public static CharMatcher is(final char match) {
- String description = "CharMatcher.is('" + showCharacter(match) + "')";
- return new FastMatcher(description) {
- @Override public boolean matches(char c) {
- return c == match;
- }
-
- @Override public String replaceFrom(CharSequence sequence, char replacement) {
- return sequence.toString().replace(match, replacement);
- }
-
- @Override public CharMatcher and(CharMatcher other) {
- return other.matches(match) ? this : NONE;
- }
-
- @Override public CharMatcher or(CharMatcher other) {
- return other.matches(match) ? other : super.or(other);
- }
-
- @Override public CharMatcher negate() {
- return isNot(match);
- }
- };
+ return new Is(match);
}
/**
@@ -440,24 +322,7 @@ public abstract class CharMatcher implements Predicate<Character> {
* <p>To negate another {@code CharMatcher}, use {@link #negate()}.
*/
public static CharMatcher isNot(final char match) {
- String description = "CharMatcher.isNot('" + showCharacter(match) + "')";
- return new FastMatcher(description) {
- @Override public boolean matches(char c) {
- return c != match;
- }
-
- @Override public CharMatcher and(CharMatcher other) {
- return other.matches(match) ? super.and(other) : other;
- }
-
- @Override public CharMatcher or(CharMatcher other) {
- return other.matches(match) ? ANY : this;
- }
-
- @Override public CharMatcher negate() {
- return is(match);
- }
- };
+ return new IsNot(match);
}
/**
@@ -467,39 +332,16 @@ public abstract class CharMatcher implements Predicate<Character> {
public static CharMatcher anyOf(final CharSequence sequence) {
switch (sequence.length()) {
case 0:
- return NONE;
+ return none();
case 1:
return is(sequence.charAt(0));
case 2:
return isEither(sequence.charAt(0), sequence.charAt(1));
default:
- // continue below to handle the general case
- }
- // TODO(user): is it potentially worth just going ahead and building a precomputed matcher?
- final char[] chars = sequence.toString().toCharArray();
- Arrays.sort(chars);
- StringBuilder description = new StringBuilder("CharMatcher.anyOf(\"");
- for (char c : chars) {
- description.append(showCharacter(c));
- }
- description.append("\")");
- return new CharMatcher(description.toString()) {
- @Override public boolean matches(char c) {
- return Arrays.binarySearch(chars, c) >= 0;
- }
- };
- }
-
- private static CharMatcher isEither(
- final char match1,
- final char match2) {
- String description = "CharMatcher.anyOf(\"" +
- showCharacter(match1) + showCharacter(match2) + "\")";
- return new FastMatcher(description) {
- @Override public boolean matches(char c) {
- return c == match1 || c == match2;
- }
- };
+ // TODO(lowasser): is it potentially worth just going ahead and building a precomputed
+ // matcher?
+ return new AnyOf(sequence);
+ }
}
/**
@@ -518,20 +360,7 @@ public abstract class CharMatcher implements Predicate<Character> {
* @throws IllegalArgumentException if {@code endInclusive < startInclusive}
*/
public static CharMatcher inRange(final char startInclusive, final char endInclusive) {
- checkArgument(endInclusive >= startInclusive);
- String description = "CharMatcher.inRange('" +
- showCharacter(startInclusive) + "', '" +
- showCharacter(endInclusive) + "')";
- return inRange(startInclusive, endInclusive, description);
- }
-
- static CharMatcher inRange(final char startInclusive, final char endInclusive,
- String description) {
- return new FastMatcher(description) {
- @Override public boolean matches(char c) {
- return startInclusive <= c && c <= endInclusive;
- }
- };
+ return new InRange(startInclusive, endInclusive);
}
/**
@@ -539,41 +368,16 @@ public abstract class CharMatcher implements Predicate<Character> {
* which operates on primitive {@code char} instances instead.
*/
public static CharMatcher forPredicate(final Predicate<? super Character> predicate) {
- checkNotNull(predicate);
- if (predicate instanceof CharMatcher) {
- return (CharMatcher) predicate;
- }
- String description = "CharMatcher.forPredicate(" + predicate + ")";
- return new CharMatcher(description) {
- @Override public boolean matches(char c) {
- return predicate.apply(c);
- }
-
- @Override public boolean apply(Character character) {
- return predicate.apply(checkNotNull(character));
- }
- };
+ return predicate instanceof CharMatcher ? (CharMatcher) predicate : new ForPredicate(predicate);
}
- // State
- final String description;
-
// Constructors
/**
- * Sets the {@code toString()} from the given description.
- */
- CharMatcher(String description) {
- this.description = description;
- }
-
- /**
* Constructor for use by subclasses. When subclassing, you may want to override
* {@code toString()} to provide a useful description.
*/
- protected CharMatcher() {
- description = super.toString();
- }
+ protected CharMatcher() {}
// Abstract methods
@@ -586,109 +390,21 @@ public abstract class CharMatcher implements Predicate<Character> {
* Returns a matcher that matches any character not matched by this matcher.
*/
public CharMatcher negate() {
- return new NegatedMatcher(this);
- }
-
- private static class NegatedMatcher extends CharMatcher {
- final CharMatcher original;
-
- NegatedMatcher(String toString, CharMatcher original) {
- super(toString);
- this.original = original;
- }
-
- NegatedMatcher(CharMatcher original) {
- this(original + ".negate()", original);
- }
-
- @Override public boolean matches(char c) {
- return !original.matches(c);
- }
-
- @Override public boolean matchesAllOf(CharSequence sequence) {
- return original.matchesNoneOf(sequence);
- }
-
- @Override public boolean matchesNoneOf(CharSequence sequence) {
- return original.matchesAllOf(sequence);
- }
-
- @Override public int countIn(CharSequence sequence) {
- return sequence.length() - original.countIn(sequence);
- }
-
- @Override public CharMatcher negate() {
- return original;
- }
-
- @Override
- CharMatcher withToString(String description) {
- return new NegatedMatcher(description, original);
- }
+ return new Negated(this);
}
/**
* Returns a matcher that matches any character matched by both this matcher and {@code other}.
*/
public CharMatcher and(CharMatcher other) {
- return new And(this, checkNotNull(other));
- }
-
- private static class And extends CharMatcher {
- final CharMatcher first;
- final CharMatcher second;
-
- And(CharMatcher a, CharMatcher b) {
- this(a, b, "CharMatcher.and(" + a + ", " + b + ")");
- }
-
- And(CharMatcher a, CharMatcher b, String description) {
- super(description);
- first = checkNotNull(a);
- second = checkNotNull(b);
- }
-
- @Override
- public boolean matches(char c) {
- return first.matches(c) && second.matches(c);
- }
-
- @Override
- CharMatcher withToString(String description) {
- return new And(first, second, description);
- }
+ return new And(this, other);
}
/**
* Returns a matcher that matches any character matched by either this matcher or {@code other}.
*/
public CharMatcher or(CharMatcher other) {
- return new Or(this, checkNotNull(other));
- }
-
- private static class Or extends CharMatcher {
- final CharMatcher first;
- final CharMatcher second;
-
- Or(CharMatcher a, CharMatcher b, String description) {
- super(description);
- first = checkNotNull(a);
- second = checkNotNull(b);
- }
-
- Or(CharMatcher a, CharMatcher b) {
- this(a, b, "CharMatcher.or(" + a + ", " + b + ")");
- }
-
- @Override
- public boolean matches(char c) {
- return first.matches(c) || second.matches(c);
- }
-
- @Override
- CharMatcher withToString(String description) {
- return new Or(first, second, description);
- }
+ return new Or(this, other);
}
/**
@@ -704,61 +420,8 @@ public abstract class CharMatcher implements Predicate<Character> {
return Platform.precomputeCharMatcher(this);
}
- /**
- * Subclasses should provide a new CharMatcher with the same characteristics as {@code this},
- * but with their {@code toString} method overridden with the new description.
- *
- * <p>This is unsupported by default.
- */
- CharMatcher withToString(String description) {
- throw new UnsupportedOperationException();
- }
-
private static final int DISTINCT_CHARS = Character.MAX_VALUE - Character.MIN_VALUE + 1;
- /**
- * A matcher for which precomputation will not yield any significant benefit.
- */
- abstract static class FastMatcher extends CharMatcher {
- FastMatcher() {
- super();
- }
-
- FastMatcher(String description) {
- super(description);
- }
-
- @Override
- public final CharMatcher precomputed() {
- return this;
- }
-
- @Override
- public CharMatcher negate() {
- return new NegatedFastMatcher(this);
- }
- }
-
- static final class NegatedFastMatcher extends NegatedMatcher {
- NegatedFastMatcher(CharMatcher original) {
- super(original);
- }
-
- NegatedFastMatcher(String toString, CharMatcher original) {
- super(toString, original);
- }
-
- @Override
- public final CharMatcher precomputed() {
- return this;
- }
-
- @Override
- CharMatcher withToString(String description) {
- return new NegatedFastMatcher(description, original);
- }
- }
-
// Text processing routines
/**
@@ -821,13 +484,7 @@ public abstract class CharMatcher implements Predicate<Character> {
* @return an index, or {@code -1} if no character matches
*/
public int indexIn(CharSequence sequence) {
- int length = sequence.length();
- for (int i = 0; i < length; i++) {
- if (matches(sequence.charAt(i))) {
- return i;
- }
- }
- return -1;
+ return indexIn(sequence, 0);
}
/**
@@ -847,7 +504,7 @@ public abstract class CharMatcher implements Predicate<Character> {
*/
public int indexIn(CharSequence sequence, int start) {
int length = sequence.length();
- Preconditions.checkPositionIndex(start, length);
+ checkPositionIndex(start, length);
for (int i = start; i < length; i++) {
if (matches(sequence.charAt(i))) {
return i;
@@ -908,7 +565,8 @@ public abstract class CharMatcher implements Predicate<Character> {
int spread = 1;
// This unusual loop comes from extensive benchmarking
- OUT: while (true) {
+ OUT:
+ while (true) {
pos++;
while (true) {
if (pos == chars.length) {
@@ -1116,14 +774,12 @@ public abstract class CharMatcher implements Predicate<Character> {
for (int i = 0; i < len; i++) {
char c = sequence.charAt(i);
if (matches(c)) {
- if (c == replacement
- && (i == len - 1 || !matches(sequence.charAt(i + 1)))) {
+ if (c == replacement && (i == len - 1 || !matches(sequence.charAt(i + 1)))) {
// a no-op replacement
i++;
} else {
- StringBuilder builder = new StringBuilder(len)
- .append(sequence.subSequence(0, i))
- .append(replacement);
+ StringBuilder builder =
+ new StringBuilder(len).append(sequence.subSequence(0, i)).append(replacement);
return finishCollapseFrom(sequence, i + 1, len, replacement, builder, true);
}
}
@@ -1141,23 +797,30 @@ public abstract class CharMatcher implements Predicate<Character> {
public String trimAndCollapseFrom(CharSequence sequence, char replacement) {
// This implementation avoids unnecessary allocation.
int len = sequence.length();
- int first;
- int last;
+ int first = 0;
+ int last = len - 1;
+
+ while (first < len && matches(sequence.charAt(first))) {
+ first++;
+ }
- for (first = 0; first < len && matches(sequence.charAt(first)); first++) {}
- for (last = len - 1; last > first && matches(sequence.charAt(last)); last--) {}
+ while (last > first && matches(sequence.charAt(last))) {
+ last--;
+ }
return (first == 0 && last == len - 1)
? collapseFrom(sequence, replacement)
: finishCollapseFrom(
- sequence, first, last + 1, replacement,
- new StringBuilder(last + 1 - first),
- false);
+ sequence, first, last + 1, replacement, new StringBuilder(last + 1 - first), false);
}
private String finishCollapseFrom(
- CharSequence sequence, int start, int end, char replacement,
- StringBuilder builder, boolean inMatchingGroup) {
+ CharSequence sequence,
+ int start,
+ int end,
+ char replacement,
+ StringBuilder builder,
+ boolean inMatchingGroup) {
for (int i = start; i < end; i++) {
char c = sequence.charAt(i);
if (matches(c)) {
@@ -1189,32 +852,800 @@ public abstract class CharMatcher implements Predicate<Character> {
*/
@Override
public String toString() {
- return description;
+ return super.toString();
}
- static final String WHITESPACE_TABLE = ""
- + "\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000"
- + "\u2029\u000B\u3000\u2008\u2003\u205F\u3000\u1680"
- + "\u0009\u0020\u2006\u2001\u202F\u00A0\u000C\u2009"
- + "\u3000\u2004\u3000\u3000\u2028\n\u2007\u3000";
- static final int WHITESPACE_MULTIPLIER = 1682554634;
- static final int WHITESPACE_SHIFT = Integer.numberOfLeadingZeros(WHITESPACE_TABLE.length() - 1);
-
/**
- * Determines whether a character is whitespace according to the latest Unicode standard, as
- * illustrated
- * <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
- * This is not the same definition used by other Java APIs. (See a
- * <a href="http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">comparison of several
- * definitions of "whitespace"</a>.)
- *
- * <p><b>Note:</b> as the Unicode definition evolves, we will modify this constant to keep it up
- * to date.
+ * Returns the Java Unicode escape sequence for the given character, in the form "\u12AB" where
+ * "12AB" is the four hexadecimal digits representing the 16 bits of the UTF-16 character.
*/
- public static final CharMatcher WHITESPACE = new FastMatcher("WHITESPACE") {
+ private static String showCharacter(char c) {
+ String hex = "0123456789ABCDEF";
+ char[] tmp = {'\\', 'u', '\0', '\0', '\0', '\0'};
+ for (int i = 0; i < 4; i++) {
+ tmp[5 - i] = hex.charAt(c & 0xF);
+ c = (char) (c >> 4);
+ }
+ return String.copyValueOf(tmp);
+ }
+
+ // Fast matchers
+
+ /** A matcher for which precomputation will not yield any significant benefit. */
+ abstract static class FastMatcher extends CharMatcher {
+
+ @Override
+ public final CharMatcher precomputed() {
+ return this;
+ }
+
+ @Override
+ public CharMatcher negate() {
+ return new NegatedFastMatcher(this);
+ }
+ }
+
+ /** {@link FastMatcher} which overrides {@code toString()} with a custom name. */
+ abstract static class NamedFastMatcher extends FastMatcher {
+
+ private final String description;
+
+ NamedFastMatcher(String description) {
+ this.description = checkNotNull(description);
+ }
+
+ @Override
+ public final String toString() {
+ return description;
+ }
+ }
+
+ /** Negation of a {@link FastMatcher}. */
+ static class NegatedFastMatcher extends Negated {
+
+ NegatedFastMatcher(CharMatcher original) {
+ super(original);
+ }
+
+ @Override
+ public final CharMatcher precomputed() {
+ return this;
+ }
+ }
+
+ // Static constant implementation classes
+
+ /** Implementation of {@link #any()}. */
+ private static final class Any extends NamedFastMatcher {
+
+ static final Any INSTANCE = new Any();
+
+ private Any() {
+ super("CharMatcher.any()");
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return true;
+ }
+
+ @Override
+ public int indexIn(CharSequence sequence) {
+ return (sequence.length() == 0) ? -1 : 0;
+ }
+
+ @Override
+ public int indexIn(CharSequence sequence, int start) {
+ int length = sequence.length();
+ checkPositionIndex(start, length);
+ return (start == length) ? -1 : start;
+ }
+
+ @Override
+ public int lastIndexIn(CharSequence sequence) {
+ return sequence.length() - 1;
+ }
+
+ @Override
+ public boolean matchesAllOf(CharSequence sequence) {
+ checkNotNull(sequence);
+ return true;
+ }
+
+ @Override
+ public boolean matchesNoneOf(CharSequence sequence) {
+ return sequence.length() == 0;
+ }
+
+ @Override
+ public String removeFrom(CharSequence sequence) {
+ checkNotNull(sequence);
+ return "";
+ }
+
+ @Override
+ public String replaceFrom(CharSequence sequence, char replacement) {
+ char[] array = new char[sequence.length()];
+ Arrays.fill(array, replacement);
+ return new String(array);
+ }
+
+ @Override
+ public String replaceFrom(CharSequence sequence, CharSequence replacement) {
+ StringBuilder result = new StringBuilder(sequence.length() * replacement.length());
+ for (int i = 0; i < sequence.length(); i++) {
+ result.append(replacement);
+ }
+ return result.toString();
+ }
+
+ @Override
+ public String collapseFrom(CharSequence sequence, char replacement) {
+ return (sequence.length() == 0) ? "" : String.valueOf(replacement);
+ }
+
+ @Override
+ public String trimFrom(CharSequence sequence) {
+ checkNotNull(sequence);
+ return "";
+ }
+
+ @Override
+ public int countIn(CharSequence sequence) {
+ return sequence.length();
+ }
+
+ @Override
+ public CharMatcher and(CharMatcher other) {
+ return checkNotNull(other);
+ }
+
+ @Override
+ public CharMatcher or(CharMatcher other) {
+ checkNotNull(other);
+ return this;
+ }
+
+ @Override
+ public CharMatcher negate() {
+ return none();
+ }
+ }
+
+ /** Implementation of {@link #none()}. */
+ private static final class None extends NamedFastMatcher {
+
+ static final None INSTANCE = new None();
+
+ private None() {
+ super("CharMatcher.none()");
+ }
+
@Override
public boolean matches(char c) {
- return WHITESPACE_TABLE.charAt((WHITESPACE_MULTIPLIER * c) >>> WHITESPACE_SHIFT) == c;
+ return false;
+ }
+
+ @Override
+ public int indexIn(CharSequence sequence) {
+ checkNotNull(sequence);
+ return -1;
+ }
+
+ @Override
+ public int indexIn(CharSequence sequence, int start) {
+ int length = sequence.length();
+ checkPositionIndex(start, length);
+ return -1;
+ }
+
+ @Override
+ public int lastIndexIn(CharSequence sequence) {
+ checkNotNull(sequence);
+ return -1;
+ }
+
+ @Override
+ public boolean matchesAllOf(CharSequence sequence) {
+ return sequence.length() == 0;
}
- };
+
+ @Override
+ public boolean matchesNoneOf(CharSequence sequence) {
+ checkNotNull(sequence);
+ return true;
+ }
+
+ @Override
+ public String removeFrom(CharSequence sequence) {
+ return sequence.toString();
+ }
+
+ @Override
+ public String replaceFrom(CharSequence sequence, char replacement) {
+ return sequence.toString();
+ }
+
+ @Override
+ public String replaceFrom(CharSequence sequence, CharSequence replacement) {
+ checkNotNull(replacement);
+ return sequence.toString();
+ }
+
+ @Override
+ public String collapseFrom(CharSequence sequence, char replacement) {
+ return sequence.toString();
+ }
+
+ @Override
+ public String trimFrom(CharSequence sequence) {
+ return sequence.toString();
+ }
+
+ @Override
+ public String trimLeadingFrom(CharSequence sequence) {
+ return sequence.toString();
+ }
+
+ @Override
+ public String trimTrailingFrom(CharSequence sequence) {
+ return sequence.toString();
+ }
+
+ @Override
+ public int countIn(CharSequence sequence) {
+ checkNotNull(sequence);
+ return 0;
+ }
+
+ @Override
+ public CharMatcher and(CharMatcher other) {
+ checkNotNull(other);
+ return this;
+ }
+
+ @Override
+ public CharMatcher or(CharMatcher other) {
+ return checkNotNull(other);
+ }
+
+ @Override
+ public CharMatcher negate() {
+ return any();
+ }
+ }
+
+ /** Implementation of {@link #whitespace()}. */
+ @VisibleForTesting
+ static final class Whitespace extends NamedFastMatcher {
+
+ static final String TABLE =
+ "\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000"
+ + "\u2029\u000B\u3000\u2008\u2003\u205F\u3000\u1680"
+ + "\u0009\u0020\u2006\u2001\u202F\u00A0\u000C\u2009"
+ + "\u3000\u2004\u3000\u3000\u2028\n\u2007\u3000";
+ static final int MULTIPLIER = 1682554634;
+ static final int SHIFT = Integer.numberOfLeadingZeros(TABLE.length() - 1);
+
+ static final Whitespace INSTANCE = new Whitespace();
+
+ Whitespace() {
+ super("CharMatcher.whitespace()");
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return TABLE.charAt((MULTIPLIER * c) >>> SHIFT) == c;
+ }
+ }
+
+ /** Implementation of {@link #breakingWhitespace()}. */
+ private static final class BreakingWhitespace extends CharMatcher {
+
+ static final CharMatcher INSTANCE = new BreakingWhitespace();
+
+ @Override
+ public boolean matches(char c) {
+ switch (c) {
+ case '\t':
+ case '\n':
+ case '\013':
+ case '\f':
+ case '\r':
+ case ' ':
+ case '\u0085':
+ case '\u1680':
+ case '\u2028':
+ case '\u2029':
+ case '\u205f':
+ case '\u3000':
+ return true;
+ case '\u2007':
+ return false;
+ default:
+ return c >= '\u2000' && c <= '\u200a';
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.breakingWhitespace()";
+ }
+ }
+
+ /** Implementation of {@link #ascii()}. */
+ private static final class Ascii extends NamedFastMatcher {
+
+ static final Ascii INSTANCE = new Ascii();
+
+ Ascii() {
+ super("CharMatcher.ascii()");
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return c <= '\u007f';
+ }
+ }
+
+ /** Implementation that matches characters that fall within multiple ranges. */
+ private static class RangesMatcher extends CharMatcher {
+
+ private final String description;
+ private final char[] rangeStarts;
+ private final char[] rangeEnds;
+
+ RangesMatcher(String description, char[] rangeStarts, char[] rangeEnds) {
+ this.description = description;
+ this.rangeStarts = rangeStarts;
+ this.rangeEnds = rangeEnds;
+ checkArgument(rangeStarts.length == rangeEnds.length);
+ for (int i = 0; i < rangeStarts.length; i++) {
+ checkArgument(rangeStarts[i] <= rangeEnds[i]);
+ if (i + 1 < rangeStarts.length) {
+ checkArgument(rangeEnds[i] < rangeStarts[i + 1]);
+ }
+ }
+ }
+
+ @Override
+ public boolean matches(char c) {
+ int index = Arrays.binarySearch(rangeStarts, c);
+ if (index >= 0) {
+ return true;
+ } else {
+ index = ~index - 1;
+ return index >= 0 && c <= rangeEnds[index];
+ }
+ }
+
+ @Override
+ public String toString() {
+ return description;
+ }
+ }
+
+ /** Implementation of {@link #digit()}. */
+ private static final class Digit extends RangesMatcher {
+
+ // Must be in ascending order.
+ private static final String ZEROES =
+ "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66"
+ + "\u0be6\u0c66\u0ce6\u0d66\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810"
+ + "\u1946\u19d0\u1b50\u1bb0\u1c40\u1c50\ua620\ua8d0\ua900\uaa50\uff10";
+
+ private static char[] zeroes() {
+ return ZEROES.toCharArray();
+ }
+
+ private static char[] nines() {
+ char[] nines = new char[ZEROES.length()];
+ for (int i = 0; i < ZEROES.length(); i++) {
+ nines[i] = (char) (ZEROES.charAt(i) + 9);
+ }
+ return nines;
+ }
+
+ static final Digit INSTANCE = new Digit();
+
+ private Digit() {
+ super("CharMatcher.digit()", zeroes(), nines());
+ }
+ }
+
+ /** Implementation of {@link #javaDigit()}. */
+ private static final class JavaDigit extends CharMatcher {
+
+ static final JavaDigit INSTANCE = new JavaDigit();
+
+ @Override
+ public boolean matches(char c) {
+ return Character.isDigit(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.javaDigit()";
+ }
+ }
+
+ /** Implementation of {@link #javaLetter()}. */
+ private static final class JavaLetter extends CharMatcher {
+
+ static final JavaLetter INSTANCE = new JavaLetter();
+
+ @Override
+ public boolean matches(char c) {
+ return Character.isLetter(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.javaLetter()";
+ }
+ }
+
+ /** Implementation of {@link #javaLetterOrDigit()}. */
+ private static final class JavaLetterOrDigit extends CharMatcher {
+
+ static final JavaLetterOrDigit INSTANCE = new JavaLetterOrDigit();
+
+ @Override
+ public boolean matches(char c) {
+ return Character.isLetterOrDigit(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.javaLetterOrDigit()";
+ }
+ }
+
+ /** Implementation of {@link #javaUpperCase()}. */
+ private static final class JavaUpperCase extends CharMatcher {
+
+ static final JavaUpperCase INSTANCE = new JavaUpperCase();
+
+ @Override
+ public boolean matches(char c) {
+ return Character.isUpperCase(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.javaUpperCase()";
+ }
+ }
+
+ /** Implementation of {@link #javaLowerCase()}. */
+ private static final class JavaLowerCase extends CharMatcher {
+
+ static final JavaLowerCase INSTANCE = new JavaLowerCase();
+
+ @Override
+ public boolean matches(char c) {
+ return Character.isLowerCase(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.javaLowerCase()";
+ }
+ }
+
+ /** Implementation of {@link #javaIsoControl()}. */
+ private static final class JavaIsoControl extends NamedFastMatcher {
+
+ static final JavaIsoControl INSTANCE = new JavaIsoControl();
+
+ private JavaIsoControl() {
+ super("CharMatcher.javaIsoControl()");
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return c <= '\u001f' || (c >= '\u007f' && c <= '\u009f');
+ }
+ }
+
+ /** Implementation of {@link #invisible()}. */
+ private static final class Invisible extends RangesMatcher {
+
+ private static final String RANGE_STARTS =
+ "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u1680\u180e\u2000\u2028\u205f\u2066\u2067"
+ + "\u2068\u2069\u206a\u3000\ud800\ufeff\ufff9\ufffa";
+ private static final String RANGE_ENDS =
+ "\u0020\u00a0\u00ad\u0604\u061c\u06dd\u070f\u1680\u180e\u200f\u202f\u2064\u2066\u2067"
+ + "\u2068\u2069\u206f\u3000\uf8ff\ufeff\ufff9\ufffb";
+
+ static final Invisible INSTANCE = new Invisible();
+
+ private Invisible() {
+ super(
+ "CharMatcher.invisible()",
+ RANGE_STARTS.toCharArray(),
+ RANGE_ENDS.toCharArray());
+ }
+ }
+
+ /** Implementation of {@link #singleWidth()}. */
+ private static final class SingleWidth extends RangesMatcher {
+
+ static final SingleWidth INSTANCE = new SingleWidth();
+
+ private SingleWidth() {
+ super(
+ "CharMatcher.singleWidth()",
+ "\u0000\u05be\u05d0\u05f3\u0600\u0750\u0e00\u1e00\u2100\ufb50\ufe70\uff61".toCharArray(),
+ "\u04f9\u05be\u05ea\u05f4\u06ff\u077f\u0e7f\u20af\u213a\ufdff\ufeff\uffdc".toCharArray());
+ }
+ }
+
+ // Non-static factory implementation classes
+
+ /** Implementation of {@link #negate()}. */
+ private static class Negated extends CharMatcher {
+
+ final CharMatcher original;
+
+ Negated(CharMatcher original) {
+ this.original = checkNotNull(original);
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return !original.matches(c);
+ }
+
+ @Override
+ public boolean matchesAllOf(CharSequence sequence) {
+ return original.matchesNoneOf(sequence);
+ }
+
+ @Override
+ public boolean matchesNoneOf(CharSequence sequence) {
+ return original.matchesAllOf(sequence);
+ }
+
+ @Override
+ public int countIn(CharSequence sequence) {
+ return sequence.length() - original.countIn(sequence);
+ }
+
+ @Override
+ public CharMatcher negate() {
+ return original;
+ }
+
+ @Override
+ public String toString() {
+ return original + ".negate()";
+ }
+ }
+
+ /** Implementation of {@link #and(CharMatcher)}. */
+ private static final class And extends CharMatcher {
+
+ final CharMatcher first;
+ final CharMatcher second;
+
+ And(CharMatcher a, CharMatcher b) {
+ first = checkNotNull(a);
+ second = checkNotNull(b);
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return first.matches(c) && second.matches(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.and(" + first + ", " + second + ")";
+ }
+ }
+
+ /** Implementation of {@link #or(CharMatcher)}. */
+ private static final class Or extends CharMatcher {
+
+ final CharMatcher first;
+ final CharMatcher second;
+
+ Or(CharMatcher a, CharMatcher b) {
+ first = checkNotNull(a);
+ second = checkNotNull(b);
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return first.matches(c) || second.matches(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.or(" + first + ", " + second + ")";
+ }
+ }
+
+ // Static factory implementations
+
+ /** Implementation of {@link #is(char)}. */
+ private static final class Is extends FastMatcher {
+
+ private final char match;
+
+ Is(char match) {
+ this.match = match;
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return c == match;
+ }
+
+ @Override
+ public String replaceFrom(CharSequence sequence, char replacement) {
+ return sequence.toString().replace(match, replacement);
+ }
+
+ @Override
+ public CharMatcher and(CharMatcher other) {
+ return other.matches(match) ? this : none();
+ }
+
+ @Override
+ public CharMatcher or(CharMatcher other) {
+ return other.matches(match) ? other : super.or(other);
+ }
+
+ @Override
+ public CharMatcher negate() {
+ return isNot(match);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.is('" + showCharacter(match) + "')";
+ }
+ }
+
+ /** Implementation of {@link #isNot(char)}. */
+ private static final class IsNot extends FastMatcher {
+
+ private final char match;
+
+ IsNot(char match) {
+ this.match = match;
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return c != match;
+ }
+
+ @Override
+ public CharMatcher and(CharMatcher other) {
+ return other.matches(match) ? super.and(other) : other;
+ }
+
+ @Override
+ public CharMatcher or(CharMatcher other) {
+ return other.matches(match) ? any() : this;
+ }
+
+ @Override
+ public CharMatcher negate() {
+ return is(match);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.isNot('" + showCharacter(match) + "')";
+ }
+ }
+
+ private static CharMatcher.IsEither isEither(char c1, char c2) {
+ return new CharMatcher.IsEither(c1, c2);
+ }
+
+ /** Implementation of {@link #anyOf(CharSequence)} for exactly two characters. */
+ private static final class IsEither extends FastMatcher {
+
+ private final char match1;
+ private final char match2;
+
+ IsEither(char match1, char match2) {
+ this.match1 = match1;
+ this.match2 = match2;
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return c == match1 || c == match2;
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.anyOf(\"" + showCharacter(match1) + showCharacter(match2) + "\")";
+ }
+ }
+
+ /** Implementation of {@link #anyOf(CharSequence)} for three or more characters. */
+ private static final class AnyOf extends CharMatcher {
+
+ private final char[] chars;
+
+ public AnyOf(CharSequence chars) {
+ this.chars = chars.toString().toCharArray();
+ Arrays.sort(this.chars);
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return Arrays.binarySearch(chars, c) >= 0;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder description = new StringBuilder("CharMatcher.anyOf(\"");
+ for (char c : chars) {
+ description.append(showCharacter(c));
+ }
+ description.append("\")");
+ return description.toString();
+ }
+ }
+
+ /** Implementation of {@link #inRange(char, char)}. */
+ private static final class InRange extends FastMatcher {
+
+ private final char startInclusive;
+ private final char endInclusive;
+
+ InRange(char startInclusive, char endInclusive) {
+ checkArgument(endInclusive >= startInclusive);
+ this.startInclusive = startInclusive;
+ this.endInclusive = endInclusive;
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return startInclusive <= c && c <= endInclusive;
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.inRange('"
+ + showCharacter(startInclusive)
+ + "', '"
+ + showCharacter(endInclusive)
+ + "')";
+ }
+ }
+
+ /** Implementation of {@link #forPredicate(Predicate)}. */
+ private static final class ForPredicate extends CharMatcher {
+
+ private final Predicate<? super Character> predicate;
+
+ ForPredicate(Predicate<? super Character> predicate) {
+ this.predicate = checkNotNull(predicate);
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return predicate.apply(c);
+ }
+
+ @SuppressWarnings("deprecation") // intentional; deprecation is for callers primarily
+ @Override
+ public boolean apply(Character character) {
+ return predicate.apply(checkNotNull(character));
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.forPredicate(" + predicate + ")";
+ }
+ }
}
diff --git a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Charsets.java b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Charsets.java
index 10d83ce..8866e9a 100644
--- a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Charsets.java
+++ b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Charsets.java
@@ -27,7 +27,7 @@ import java.nio.charset.Charset;
* <p>Assuming you're free to choose, note that <b>{@link #UTF_8} is widely preferred</b>.
*
* <p>See the Guava User Guide article on <a
- * href="http://code.google.com/p/guava-libraries/wiki/StringsExplained#Charsets">
+ * href="https://github.com/google/guava/wiki/StringsExplained#charsets">
* {@code Charsets}</a>.
*
* @author Mike Bostock
diff --git a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Enums.java b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Enums.java
index f4aa4a8..f0f0f5e 100644
--- a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Enums.java
+++ b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Enums.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -32,6 +33,7 @@ import javax.annotation.Nullable;
*
* @since 9.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
@Beta
public final class Enums {
@@ -46,8 +48,7 @@ public final class Enums {
*
* @since 12.0
*/
- public static <T extends Enum<T>> Optional<T> getIfPresent(
- Class<T> enumClass, String value) {
+ public static <T extends Enum<T>> Optional<T> getIfPresent(Class<T> enumClass, String value) {
checkNotNull(enumClass);
checkNotNull(value);
return Platform.getEnumIfPresent(enumClass, value);
@@ -65,8 +66,8 @@ public final class Enums {
return new StringConverter<T>(enumClass);
}
- private static final class StringConverter<T extends Enum<T>>
- extends Converter<String, T> implements Serializable {
+ private static final class StringConverter<T extends Enum<T>> extends Converter<String, T>
+ implements Serializable {
private final Class<T> enumClass;
diff --git a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Predicates.java b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Predicates.java
index e9a4b17..aae8245 100644
--- a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Predicates.java
+++ b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Predicates.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -35,12 +36,13 @@ import javax.annotation.Nullable;
* serializable parameters.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the
+ * "https://github.com/google/guava/wiki/FunctionalExplained">the
* use of {@code Predicate}</a>.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class Predicates {
private Predicates() {}
@@ -99,8 +101,7 @@ public final class Predicates {
* components} is empty, the returned predicate will always evaluate to {@code
* true}.
*/
- public static <T> Predicate<T> and(
- Iterable<? extends Predicate<? super T>> components) {
+ public static <T> Predicate<T> and(Iterable<? extends Predicate<? super T>> components) {
return new AndPredicate<T>(defensiveCopy(components));
}
@@ -123,10 +124,8 @@ public final class Predicates {
* order, and evaluation will be "short-circuited" as soon as a false
* predicate is found.
*/
- public static <T> Predicate<T> and(Predicate<? super T> first,
- Predicate<? super T> second) {
- return new AndPredicate<T>(Predicates.<T>asList(
- checkNotNull(first), checkNotNull(second)));
+ public static <T> Predicate<T> and(Predicate<? super T> first, Predicate<? super T> second) {
+ return new AndPredicate<T>(Predicates.<T>asList(checkNotNull(first), checkNotNull(second)));
}
/**
@@ -138,8 +137,7 @@ public final class Predicates {
* components} is empty, the returned predicate will always evaluate to {@code
* false}.
*/
- public static <T> Predicate<T> or(
- Iterable<? extends Predicate<? super T>> components) {
+ public static <T> Predicate<T> or(Iterable<? extends Predicate<? super T>> components) {
return new OrPredicate<T>(defensiveCopy(components));
}
@@ -162,10 +160,8 @@ public final class Predicates {
* order, and evaluation will be "short-circuited" as soon as a
* true predicate is found.
*/
- public static <T> Predicate<T> or(
- Predicate<? super T> first, Predicate<? super T> second) {
- return new OrPredicate<T>(Predicates.<T>asList(
- checkNotNull(first), checkNotNull(second)));
+ public static <T> Predicate<T> or(Predicate<? super T> first, Predicate<? super T> second) {
+ return new OrPredicate<T>(Predicates.<T>asList(checkNotNull(first), checkNotNull(second)));
}
/**
@@ -173,9 +169,7 @@ public final class Predicates {
* tested {@code equals()} the given target or both are null.
*/
public static <T> Predicate<T> equalTo(@Nullable T target) {
- return (target == null)
- ? Predicates.<T>isNull()
- : new IsEqualToPredicate<T>(target);
+ return (target == null) ? Predicates.<T>isNull() : new IsEqualToPredicate<T>(target);
}
/**
@@ -212,37 +206,49 @@ public final class Predicates {
enum ObjectPredicate implements Predicate<Object> {
/** @see Predicates#alwaysTrue() */
ALWAYS_TRUE {
- @Override public boolean apply(@Nullable Object o) {
+ @Override
+ public boolean apply(@Nullable Object o) {
return true;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.alwaysTrue()";
}
},
/** @see Predicates#alwaysFalse() */
ALWAYS_FALSE {
- @Override public boolean apply(@Nullable Object o) {
+ @Override
+ public boolean apply(@Nullable Object o) {
return false;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.alwaysFalse()";
}
},
/** @see Predicates#isNull() */
IS_NULL {
- @Override public boolean apply(@Nullable Object o) {
+ @Override
+ public boolean apply(@Nullable Object o) {
return o == null;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.isNull()";
}
},
/** @see Predicates#notNull() */
NOT_NULL {
- @Override public boolean apply(@Nullable Object o) {
+ @Override
+ public boolean apply(@Nullable Object o) {
return o != null;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.notNull()";
}
};
@@ -260,23 +266,31 @@ public final class Predicates {
NotPredicate(Predicate<T> predicate) {
this.predicate = checkNotNull(predicate);
}
+
@Override
public boolean apply(@Nullable T t) {
return !predicate.apply(t);
}
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
return ~predicate.hashCode();
}
- @Override public boolean equals(@Nullable Object obj) {
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof NotPredicate) {
NotPredicate<?> that = (NotPredicate<?>) obj;
return predicate.equals(that.predicate);
}
return false;
}
- @Override public String toString() {
- return "Predicates.not(" + predicate.toString() + ")";
+
+ @Override
+ public String toString() {
+ return "Predicates.not(" + predicate + ")";
}
+
private static final long serialVersionUID = 0;
}
@@ -289,6 +303,7 @@ public final class Predicates {
private AndPredicate(List<? extends Predicate<? super T>> components) {
this.components = components;
}
+
@Override
public boolean apply(@Nullable T t) {
// Avoid using the Iterator to avoid generating garbage (issue 820).
@@ -299,20 +314,27 @@ public final class Predicates {
}
return true;
}
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
// add a random number to avoid collisions with OrPredicate
return components.hashCode() + 0x12472c2c;
}
- @Override public boolean equals(@Nullable Object obj) {
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof AndPredicate) {
AndPredicate<?> that = (AndPredicate<?>) obj;
return components.equals(that.components);
}
return false;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.and(" + COMMA_JOINER.join(components) + ")";
}
+
private static final long serialVersionUID = 0;
}
@@ -323,6 +345,7 @@ public final class Predicates {
private OrPredicate(List<? extends Predicate<? super T>> components) {
this.components = components;
}
+
@Override
public boolean apply(@Nullable T t) {
// Avoid using the Iterator to avoid generating garbage (issue 820).
@@ -333,48 +356,62 @@ public final class Predicates {
}
return false;
}
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
// add a random number to avoid collisions with AndPredicate
return components.hashCode() + 0x053c91cf;
}
- @Override public boolean equals(@Nullable Object obj) {
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof OrPredicate) {
OrPredicate<?> that = (OrPredicate<?>) obj;
return components.equals(that.components);
}
return false;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.or(" + COMMA_JOINER.join(components) + ")";
}
+
private static final long serialVersionUID = 0;
}
/** @see Predicates#equalTo(Object) */
- private static class IsEqualToPredicate<T>
- implements Predicate<T>, Serializable {
+ private static class IsEqualToPredicate<T> implements Predicate<T>, Serializable {
private final T target;
private IsEqualToPredicate(T target) {
this.target = target;
}
+
@Override
public boolean apply(T t) {
return target.equals(t);
}
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
return target.hashCode();
}
- @Override public boolean equals(@Nullable Object obj) {
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof IsEqualToPredicate) {
IsEqualToPredicate<?> that = (IsEqualToPredicate<?>) obj;
return target.equals(that.target);
}
return false;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.equalTo(" + target + ")";
}
+
private static final long serialVersionUID = 0;
}
@@ -397,7 +434,8 @@ public final class Predicates {
}
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof InPredicate) {
InPredicate<?> that = (InPredicate<?>) obj;
return target.equals(that.target);
@@ -405,19 +443,21 @@ public final class Predicates {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return target.hashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Predicates.in(" + target + ")";
}
+
private static final long serialVersionUID = 0;
}
/** @see Predicates#compose(Predicate, Function) */
- private static class CompositionPredicate<A, B>
- implements Predicate<A>, Serializable {
+ private static class CompositionPredicate<A, B> implements Predicate<A>, Serializable {
final Predicate<B> p;
final Function<A, ? extends B> f;
@@ -431,7 +471,8 @@ public final class Predicates {
return p.apply(f.apply(a));
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof CompositionPredicate) {
CompositionPredicate<?, ?> that = (CompositionPredicate<?, ?>) obj;
return f.equals(that.f) && p.equals(that.p);
@@ -439,12 +480,15 @@ public final class Predicates {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return f.hashCode() ^ p.hashCode();
}
- @Override public String toString() {
- return p.toString() + "(" + f.toString() + ")";
+ @Override
+ public String toString() {
+ // TODO(cpovirk): maybe make this look like the method call does ("Predicates.compose(...)")
+ return p + "(" + f + ")";
}
private static final long serialVersionUID = 0;
diff --git a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Splitter.java b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Splitter.java
index 56e2902..6e30284 100644
--- a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Splitter.java
+++ b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Splitter.java
@@ -87,7 +87,7 @@ import javax.annotation.CheckReturnValue;
* note that a round-trip between the two should be assumed to be lossy.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/StringsExplained#Splitter">
+ * "https://github.com/google/guava/wiki/StringsExplained#splitter">
* {@code Splitter}</a>.
*
* @author Julien Silland
@@ -107,8 +107,7 @@ public final class Splitter {
this(strategy, false, CharMatcher.NONE, Integer.MAX_VALUE);
}
- private Splitter(Strategy strategy, boolean omitEmptyStrings,
- CharMatcher trimmer, int limit) {
+ private Splitter(Strategy strategy, boolean omitEmptyStrings, CharMatcher trimmer, int limit) {
this.strategy = strategy;
this.omitEmptyStrings = omitEmptyStrings;
this.trimmer = trimmer;
@@ -123,6 +122,7 @@ public final class Splitter {
* @param separator the character to recognize as a separator
* @return a splitter, with default settings, that recognizes that separator
*/
+ @CheckReturnValue
public static Splitter on(char separator) {
return on(CharMatcher.is(separator));
}
@@ -137,23 +137,27 @@ public final class Splitter {
* character is a separator
* @return a splitter, with default settings, that uses this matcher
*/
+ @CheckReturnValue
public static Splitter on(final CharMatcher separatorMatcher) {
checkNotNull(separatorMatcher);
- return new Splitter(new Strategy() {
- @Override public SplittingIterator iterator(
- Splitter splitter, final CharSequence toSplit) {
- return new SplittingIterator(splitter, toSplit) {
- @Override int separatorStart(int start) {
- return separatorMatcher.indexIn(toSplit, start);
- }
+ return new Splitter(
+ new Strategy() {
+ @Override
+ public SplittingIterator iterator(Splitter splitter, final CharSequence toSplit) {
+ return new SplittingIterator(splitter, toSplit) {
+ @Override
+ int separatorStart(int start) {
+ return separatorMatcher.indexIn(toSplit, start);
+ }
- @Override int separatorEnd(int separatorPosition) {
- return separatorPosition + 1;
+ @Override
+ int separatorEnd(int separatorPosition) {
+ return separatorPosition + 1;
+ }
+ };
}
- };
- }
- });
+ });
}
/**
@@ -164,36 +168,40 @@ public final class Splitter {
* @param separator the literal, nonempty string to recognize as a separator
* @return a splitter, with default settings, that recognizes that separator
*/
+ @CheckReturnValue
public static Splitter on(final String separator) {
- checkArgument(separator.length() != 0,
- "The separator may not be the empty string.");
-
- return new Splitter(new Strategy() {
- @Override public SplittingIterator iterator(
- Splitter splitter, CharSequence toSplit) {
- return new SplittingIterator(splitter, toSplit) {
- @Override public int separatorStart(int start) {
- int separatorLength = separator.length();
-
- positions:
- for (int p = start, last = toSplit.length() - separatorLength;
- p <= last; p++) {
- for (int i = 0; i < separatorLength; i++) {
- if (toSplit.charAt(i + p) != separator.charAt(i)) {
- continue positions;
+ checkArgument(separator.length() != 0, "The separator may not be the empty string.");
+ if (separator.length() == 1) {
+ return Splitter.on(separator.charAt(0));
+ }
+ return new Splitter(
+ new Strategy() {
+ @Override
+ public SplittingIterator iterator(Splitter splitter, CharSequence toSplit) {
+ return new SplittingIterator(splitter, toSplit) {
+ @Override
+ public int separatorStart(int start) {
+ int separatorLength = separator.length();
+
+ positions:
+ for (int p = start, last = toSplit.length() - separatorLength; p <= last; p++) {
+ for (int i = 0; i < separatorLength; i++) {
+ if (toSplit.charAt(i + p) != separator.charAt(i)) {
+ continue positions;
+ }
+ }
+ return p;
}
+ return -1;
}
- return p;
- }
- return -1;
- }
- @Override public int separatorEnd(int separatorPosition) {
- return separatorPosition + separator.length();
+ @Override
+ public int separatorEnd(int separatorPosition) {
+ return separatorPosition + separator.length();
+ }
+ };
}
- };
- }
- });
+ });
}
/**
@@ -215,24 +223,28 @@ public final class Splitter {
* pieces
* @throws IllegalArgumentException if {@code length} is zero or negative
*/
+ @CheckReturnValue
public static Splitter fixedLength(final int length) {
checkArgument(length > 0, "The length may not be less than 1");
- return new Splitter(new Strategy() {
- @Override public SplittingIterator iterator(
- final Splitter splitter, CharSequence toSplit) {
- return new SplittingIterator(splitter, toSplit) {
- @Override public int separatorStart(int start) {
- int nextChunkStart = start + length;
- return (nextChunkStart < toSplit.length() ? nextChunkStart : -1);
- }
+ return new Splitter(
+ new Strategy() {
+ @Override
+ public SplittingIterator iterator(final Splitter splitter, CharSequence toSplit) {
+ return new SplittingIterator(splitter, toSplit) {
+ @Override
+ public int separatorStart(int start) {
+ int nextChunkStart = start + length;
+ return (nextChunkStart < toSplit.length() ? nextChunkStart : -1);
+ }
- @Override public int separatorEnd(int separatorPosition) {
- return separatorPosition;
+ @Override
+ public int separatorEnd(int separatorPosition) {
+ return separatorPosition;
+ }
+ };
}
- };
- }
- });
+ });
}
/**
@@ -261,7 +273,8 @@ public final class Splitter {
/**
* Returns a splitter that behaves equivalently to {@code this} splitter but
* stops splitting after it reaches the limit.
- * The limit defines the maximum number of items returned by the iterator.
+ * The limit defines the maximum number of items returned by the iterator, or
+ * the maximum size of the list returned by {@link #splitToList}.
*
* <p>For example,
* {@code Splitter.on(',').limit(3).split("a,b,c,d")} returns an iterable
@@ -271,9 +284,9 @@ public final class Splitter {
* returns an iterable containing {@code ["a", "b", "c,d"}.
* When trim is requested, all entries, including the last are trimmed. Hence
* {@code Splitter.on(',').limit(3).trimResults().split(" a , b , c , d ")}
- * results in @{code ["a", "b", "c , d"]}.
+ * results in {@code ["a", "b", "c , d"]}.
*
- * @param limit the maximum number of items returns
+ * @param limit the maximum number of items returned
* @return a splitter with the desired configuration
* @since 9.0
*/
@@ -324,14 +337,18 @@ public final class Splitter {
* @param sequence the sequence of characters to split
* @return an iteration over the segments split from the parameter.
*/
+ @CheckReturnValue
public Iterable<String> split(final CharSequence sequence) {
checkNotNull(sequence);
return new Iterable<String>() {
- @Override public Iterator<String> iterator() {
+ @Override
+ public Iterator<String> iterator() {
return splittingIterator(sequence);
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return Joiner.on(", ")
.appendTo(new StringBuilder().append('['), this)
.append(']')
@@ -353,6 +370,7 @@ public final class Splitter {
* @return an immutable list of the segments split from the parameter
* @since 15.0
*/
+ @CheckReturnValue
@Beta
public List<String> splitToList(CharSequence sequence) {
checkNotNull(sequence);
@@ -413,8 +431,7 @@ public final class Splitter {
*/
@Beta
public static final class MapSplitter {
- private static final String INVALID_ENTRY_MESSAGE =
- "Chunk [%s] is not a valid entry";
+ private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry";
private final Splitter outerSplitter;
private final Splitter entrySplitter;
@@ -438,6 +455,7 @@ public final class Splitter {
* @throws IllegalArgumentException if the specified sequence does not split
* into valid map entries, or if there are duplicate keys
*/
+ @CheckReturnValue
public Map<String, String> split(CharSequence sequence) {
Map<String, String> map = new LinkedHashMap<String, String>();
for (String entry : outerSplitter.split(sequence)) {
@@ -489,7 +507,8 @@ public final class Splitter {
this.toSplit = toSplit;
}
- @Override protected String computeNext() {
+ @Override
+ protected String computeNext() {
/*
* The returned string will be from the end of the last match to the
* beginning of the next one. nextStart is the start position of the
diff --git a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Stopwatch.java b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Stopwatch.java
index 07f674e..fec69ff 100644
--- a/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Stopwatch.java
+++ b/guava-gwt/src-super/com/google/common/base/super/com/google/common/base/Stopwatch.java
@@ -26,11 +26,12 @@ import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import java.util.concurrent.TimeUnit;
+import javax.annotation.CheckReturnValue;
+
/**
* An object that measures elapsed time in nanoseconds. It is useful to measure
* elapsed time using this class instead of direct calls to {@link
@@ -70,7 +71,6 @@ import java.util.concurrent.TimeUnit;
* @author Kevin Bourrillion
* @since 10.0
*/
- at Beta
@GwtCompatible(emulated = true)
public final class Stopwatch {
private final Ticker ticker;
@@ -84,6 +84,7 @@ public final class Stopwatch {
*
* @since 15.0
*/
+ @CheckReturnValue
public static Stopwatch createUnstarted() {
return new Stopwatch();
}
@@ -94,6 +95,7 @@ public final class Stopwatch {
*
* @since 15.0
*/
+ @CheckReturnValue
public static Stopwatch createUnstarted(Ticker ticker) {
return new Stopwatch(ticker);
}
@@ -104,6 +106,7 @@ public final class Stopwatch {
*
* @since 15.0
*/
+ @CheckReturnValue
public static Stopwatch createStarted() {
return new Stopwatch().start();
}
@@ -114,28 +117,15 @@ public final class Stopwatch {
*
* @since 15.0
*/
+ @CheckReturnValue
public static Stopwatch createStarted(Ticker ticker) {
return new Stopwatch(ticker).start();
}
- /**
- * Creates (but does not start) a new stopwatch using {@link System#nanoTime}
- * as its time source.
- *
- * @deprecated Use {@link Stopwatch#createUnstarted()} instead.
- */
- @Deprecated
Stopwatch() {
- this(Ticker.systemTicker());
+ this.ticker = Ticker.systemTicker();
}
- /**
- * Creates (but does not start) a new stopwatch, using the specified time
- * source.
- *
- * @deprecated Use {@link Stopwatch#createUnstarted(Ticker)} instead.
- */
- @Deprecated
Stopwatch(Ticker ticker) {
this.ticker = checkNotNull(ticker, "ticker");
}
@@ -145,6 +135,7 @@ public final class Stopwatch {
* and {@link #stop()} has not been called since the last call to {@code
* start()}.
*/
+ @CheckReturnValue
public boolean isRunning() {
return isRunning;
}
@@ -203,6 +194,7 @@ public final class Stopwatch {
*
* @since 14.0 (since 10.0 as {@code elapsedTime()})
*/
+ @CheckReturnValue
public long elapsed(TimeUnit desiredUnit) {
return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
}
@@ -250,3 +242,4 @@ public final class Stopwatch {
}
}
}
+
diff --git a/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheBuilder.java b/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheBuilder.java
index 8e50152..cf84576 100644
--- a/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheBuilder.java
+++ b/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheBuilder.java
@@ -52,6 +52,7 @@ import javax.annotation.CheckReturnValue;
* <li>accumulation of cache access statistics
* </ul>
*
+ *
* <p>These features are all optional; caches can be created using all or none of them. By default
* cache instances created by {@code CacheBuilder} will not perform any type of eviction.
*
@@ -133,7 +134,7 @@ import javax.annotation.CheckReturnValue;
* <i>not</i> include cache contents, but only configuration.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CachesExplained">caching</a> for a higher-level
+ * "https://github.com/google/guava/wiki/CachesExplained">caching</a> for a higher-level
* explanation.
*
* @param <K> the base key type for all caches created by this builder
@@ -444,11 +445,11 @@ public final class CacheBuilder<K, V> {
}
/**
- * Specifies a nanosecond-precision time source for use in determining when entries should be
- * expired. By default, {@link System#nanoTime} is used.
+ * Specifies a nanosecond-precision time source for this cache. By default,
+ * {@link System#nanoTime} is used.
*
- * <p>The primary intent of this method is to facilitate testing of caches which have been
- * configured with {@link #expireAfterWrite} or {@link #expireAfterAccess}.
+ * <p>The primary intent of this method is to facilitate testing of caches with a fake or mock
+ * time source.
*
* @throws IllegalStateException if a ticker was already set
*/
@@ -517,7 +518,7 @@ public final class CacheBuilder<K, V> {
statsCounterSupplier = CACHE_STATS_COUNTER;
return this;
}
-
+
boolean isRecordingStats() {
return statsCounterSupplier == CACHE_STATS_COUNTER;
}
@@ -539,7 +540,7 @@ public final class CacheBuilder<K, V> {
* @return a cache having the requested features
*/
public <K1 extends K, V1 extends V> LoadingCache<K1, V1> build(
- CacheLoader<? super K1, V1> loader) {
+ CacheLoader<? super K1, V1> loader) {
checkWeightWithWeigher();
return new LocalCache.LocalLoadingCache<K1, V1>(this, loader);
}
@@ -623,4 +624,3 @@ public final class CacheBuilder<K, V> {
return s.toString();
}
}
-
diff --git a/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheLoader.java b/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheLoader.java
index c345553..44a73da 100644
--- a/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheLoader.java
+++ b/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/CacheLoader.java
@@ -18,7 +18,6 @@ package com.google.common.cache;
import static com.google.common.base.Preconditions.checkNotNull;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
@@ -99,7 +98,6 @@ public abstract class CacheLoader<K, V> {
* @param function the function to be used for loading values; must never return {@code null}
* @return a cache loader that loads values by passing each key to {@code function}
*/
- @Beta
public static <K, V> CacheLoader<K, V> from(Function<K, V> function) {
return new FunctionToCacheLoader<K, V>(function);
}
@@ -129,7 +127,6 @@ public abstract class CacheLoader<K, V> {
* @return a cache loader that loads values by calling {@link Supplier#get}, irrespective of the
* key
*/
- @Beta
public static <V> CacheLoader<Object, V> from(Supplier<V> supplier) {
return new SupplierToCacheLoader<V>(supplier);
}
@@ -151,7 +148,17 @@ public abstract class CacheLoader<K, V> {
private static final long serialVersionUID = 0;
}
- static final class UnsupportedLoadingOperationException extends UnsupportedOperationException {}
+ /**
+ * Exception thrown by {@code loadAll()} to indicate that it is not supported.
+ *
+ * @since 19.0
+ */
+ public static final class UnsupportedLoadingOperationException
+ extends UnsupportedOperationException {
+ // Package-private because this should only be thrown by loadAll() when it is not overridden.
+ // Cache implementors may want to catch it but should not need to be able to throw it.
+ UnsupportedLoadingOperationException() {}
+ }
/**
* Thrown to indicate that an invalid response was returned from a call to {@link CacheLoader}.
diff --git a/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/LocalCache.java b/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/LocalCache.java
index 16aba06..c8dec84 100644
--- a/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/LocalCache.java
+++ b/guava-gwt/src-super/com/google/common/cache/super/com/google/common/cache/LocalCache.java
@@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ExecutionError;
import com.google.common.util.concurrent.UncheckedExecutionException;
+import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.HashMap;
@@ -237,7 +238,7 @@ public class LocalCache<K, V> implements ConcurrentMap<K, V> {
private void alertListenerIfPresent(Object key, Object value, RemovalCause cause) {
if (removalListener != null) {
- removalListener.onRemoval(new RemovalNotification(key, value, cause));
+ removalListener.onRemoval(RemovalNotification.create(key, value, cause));
}
}
@@ -487,7 +488,7 @@ public class LocalCache<K, V> implements ConcurrentMap<K, V> {
protected boolean removeEldestEntry(Map.Entry<K, Timestamped<V>> ignored) {
boolean removal = (maximumSize == UNSET_INT) ? false : (size() > maximumSize);
if ((removalListener != null) && removal) {
- removalListener.onRemoval(new RemovalNotification(
+ removalListener.onRemoval(RemovalNotification.create(
ignored.getKey(),
ignored.getValue().getValue(),
RemovalCause.SIZE));
@@ -742,9 +743,6 @@ public class LocalCache<K, V> implements ConcurrentMap<K, V> {
}
}
- /**
- * Abstraction layer for the KeySet, which redirects to cache methods.
- */
private final class KeySet extends AbstractCacheSet<K> {
KeySet(ConcurrentMap<?, ?> map) {
@@ -767,13 +765,11 @@ public class LocalCache<K, V> implements ConcurrentMap<K, V> {
}
}
- /**
- * Abstraction layer for the Values set, which redirects to cache methods.
- */
- private final class Values extends AbstractCacheSet<V> {
+ private final class Values extends AbstractCollection<V> {
+ final ConcurrentMap<?, ?> map;
Values(ConcurrentMap<?, ?> map) {
- super(map);
+ this.map = map;
}
@Override
@@ -785,11 +781,23 @@ public class LocalCache<K, V> implements ConcurrentMap<K, V> {
public boolean contains(Object o) {
return map.containsValue(o);
}
+
+ @Override
+ public int size() {
+ return map.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ @Override
+ public void clear() {
+ map.clear();
+ }
}
- /**
- * Abstraction layer for the EntrySet, which redirects to cache methods.
- */
private final class EntrySet extends AbstractCacheSet<Entry<K, V>> {
EntrySet(ConcurrentMap<?, ?> map) {
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractBiMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractBiMap.java
index 6f40246..36eefec 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractBiMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractBiMap.java
@@ -22,6 +22,7 @@ import static com.google.common.collect.CollectPreconditions.checkRemove;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.Collection;
@@ -59,7 +60,8 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
inverse = forward;
}
- @Override protected Map<K, V> delegate() {
+ @Override
+ protected Map<K, V> delegate() {
return delegate;
}
@@ -97,13 +99,15 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
// Query Operations (optimizations)
- @Override public boolean containsValue(@Nullable Object value) {
+ @Override
+ public boolean containsValue(@Nullable Object value) {
return inverse.containsKey(value);
}
// Modification Operations
- @Override public V put(@Nullable K key, @Nullable V value) {
+ @Override
+ public V put(@Nullable K key, @Nullable V value) {
return putInBothMaps(key, value, false);
}
@@ -129,15 +133,15 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
return oldValue;
}
- private void updateInverseMap(
- K key, boolean containedKey, V oldValue, V newValue) {
+ private void updateInverseMap(K key, boolean containedKey, V oldValue, V newValue) {
if (containedKey) {
removeFromInverseMap(oldValue);
}
inverse.delegate.put(newValue, key);
}
- @Override public V remove(@Nullable Object key) {
+ @Override
+ public V remove(@Nullable Object key) {
return containsKey(key) ? removeFromBothMaps(key) : null;
}
@@ -153,13 +157,15 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
// Bulk Operations
- @Override public void putAll(Map<? extends K, ? extends V> map) {
+ @Override
+ public void putAll(Map<? extends K, ? extends V> map) {
for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
- @Override public void clear() {
+ @Override
+ public void clear() {
delegate.clear();
inverse.delegate.clear();
}
@@ -173,21 +179,26 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
private transient Set<K> keySet;
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
Set<K> result = keySet;
return (result == null) ? keySet = new KeySet() : result;
}
+ @WeakOuter
private class KeySet extends ForwardingSet<K> {
- @Override protected Set<K> delegate() {
+ @Override
+ protected Set<K> delegate() {
return delegate.keySet();
}
- @Override public void clear() {
+ @Override
+ public void clear() {
AbstractBiMap.this.clear();
}
- @Override public boolean remove(Object key) {
+ @Override
+ public boolean remove(Object key) {
if (!contains(key)) {
return false;
}
@@ -195,22 +206,26 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
return true;
}
- @Override public boolean removeAll(Collection<?> keysToRemove) {
+ @Override
+ public boolean removeAll(Collection<?> keysToRemove) {
return standardRemoveAll(keysToRemove);
}
- @Override public boolean retainAll(Collection<?> keysToRetain) {
+ @Override
+ public boolean retainAll(Collection<?> keysToRetain) {
return standardRetainAll(keysToRetain);
}
- @Override public Iterator<K> iterator() {
+ @Override
+ public Iterator<K> iterator() {
return Maps.keyIterator(entrySet().iterator());
}
}
private transient Set<V> valueSet;
- @Override public Set<V> values() {
+ @Override
+ public Set<V> values() {
/*
* We can almost reuse the inverse's keySet, except we have to fix the
* iteration order so that it is consistent with the forward map.
@@ -219,49 +234,60 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
return (result == null) ? valueSet = new ValueSet() : result;
}
+ @WeakOuter
private class ValueSet extends ForwardingSet<V> {
final Set<V> valuesDelegate = inverse.keySet();
- @Override protected Set<V> delegate() {
+ @Override
+ protected Set<V> delegate() {
return valuesDelegate;
}
- @Override public Iterator<V> iterator() {
+ @Override
+ public Iterator<V> iterator() {
return Maps.valueIterator(entrySet().iterator());
}
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
return standardToArray();
}
- @Override public <T> T[] toArray(T[] array) {
+ @Override
+ public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return standardToString();
}
}
private transient Set<Entry<K, V>> entrySet;
- @Override public Set<Entry<K, V>> entrySet() {
+ @Override
+ public Set<Entry<K, V>> entrySet() {
Set<Entry<K, V>> result = entrySet;
return (result == null) ? entrySet = new EntrySet() : result;
}
+ @WeakOuter
private class EntrySet extends ForwardingSet<Entry<K, V>> {
final Set<Entry<K, V>> esDelegate = delegate.entrySet();
- @Override protected Set<Entry<K, V>> delegate() {
+ @Override
+ protected Set<Entry<K, V>> delegate() {
return esDelegate;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
AbstractBiMap.this.clear();
}
- @Override public boolean remove(Object object) {
+ @Override
+ public boolean remove(Object object) {
if (!esDelegate.contains(object)) {
return false;
}
@@ -278,43 +304,47 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
return true;
}
- @Override public Iterator<Entry<K, V>> iterator() {
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
final Iterator<Entry<K, V>> iterator = esDelegate.iterator();
return new Iterator<Entry<K, V>>() {
Entry<K, V> entry;
- @Override public boolean hasNext() {
+ @Override
+ public boolean hasNext() {
return iterator.hasNext();
}
- @Override public Entry<K, V> next() {
+ @Override
+ public Entry<K, V> next() {
entry = iterator.next();
final Entry<K, V> finalEntry = entry;
return new ForwardingMapEntry<K, V>() {
- @Override protected Entry<K, V> delegate() {
+ @Override
+ protected Entry<K, V> delegate() {
return finalEntry;
}
- @Override public V setValue(V value) {
+ @Override
+ public V setValue(V value) {
// Preconditions keep the map and inverse consistent.
checkState(contains(this), "entry no longer in map");
// similar to putInBothMaps, but set via entry
if (Objects.equal(value, getValue())) {
return value;
}
- checkArgument(!containsValue(value),
- "value already present: %s", value);
+ checkArgument(!containsValue(value), "value already present: %s", value);
V oldValue = finalEntry.setValue(value);
- checkState(Objects.equal(value, get(getKey())),
- "entry no longer in map");
+ checkState(Objects.equal(value, get(getKey())), "entry no longer in map");
updateInverseMap(getKey(), true, oldValue, value);
return oldValue;
}
};
}
- @Override public void remove() {
+ @Override
+ public void remove() {
checkRemove(entry != null);
V value = entry.getValue();
iterator.remove();
@@ -325,22 +355,33 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
// See java.util.Collections.CheckedEntrySet for details on attacks.
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
return standardToArray();
}
- @Override public <T> T[] toArray(T[] array) {
+
+ @Override
+ public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
- @Override public boolean contains(Object o) {
+
+ @Override
+ public boolean contains(Object o) {
return Maps.containsEntryImpl(delegate(), o);
}
- @Override public boolean containsAll(Collection<?> c) {
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
return standardContainsAll(c);
}
- @Override public boolean removeAll(Collection<?> c) {
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
return standardRemoveAll(c);
}
- @Override public boolean retainAll(Collection<?> c) {
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
return standardRetainAll(c);
}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultimap.java
index 652b095..af19393 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultimap.java
@@ -21,7 +21,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.CollectPreconditions.checkRemove;
import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.Maps.ImprovedAbstractMap;
+import com.google.common.collect.Maps.ViewCachingAbstractMap;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.AbstractCollection;
@@ -227,7 +228,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return removeAll(key);
}
- // TODO(user): investigate atomic failure?
+ // TODO(lowasser): investigate atomic failure?
Collection<V> collection = getOrCreateCollection(key);
Collection<V> oldValues = createCollection();
oldValues.addAll(collection);
@@ -324,8 +325,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
}
- private List<V> wrapList(
- @Nullable K key, List<V> list, @Nullable WrappedCollection ancestor) {
+ private List<V> wrapList(@Nullable K key, List<V> list, @Nullable WrappedCollection ancestor) {
return (list instanceof RandomAccess)
? new RandomAccessWrappedList(key, list, ancestor)
: new WrappedList(key, list, ancestor);
@@ -348,19 +348,19 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
* removeIfEmpty}, and {@code addToMap} methods call the corresponding methods
* of the full wrapped collection.
*/
+ @WeakOuter
private class WrappedCollection extends AbstractCollection<V> {
final K key;
Collection<V> delegate;
final WrappedCollection ancestor;
final Collection<V> ancestorDelegate;
- WrappedCollection(@Nullable K key, Collection<V> delegate,
- @Nullable WrappedCollection ancestor) {
+ WrappedCollection(
+ @Nullable K key, Collection<V> delegate, @Nullable WrappedCollection ancestor) {
this.key = key;
this.delegate = delegate;
this.ancestor = ancestor;
- this.ancestorDelegate
- = (ancestor == null) ? null : ancestor.getDelegate();
+ this.ancestorDelegate = (ancestor == null) ? null : ancestor.getDelegate();
}
/**
@@ -415,12 +415,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
}
- @Override public int size() {
+ @Override
+ public int size() {
refreshIfEmpty();
return delegate.size();
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -428,12 +430,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return delegate.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
refreshIfEmpty();
return delegate.hashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
refreshIfEmpty();
return delegate.toString();
}
@@ -442,7 +446,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return delegate;
}
- @Override public Iterator<V> iterator() {
+ @Override
+ public Iterator<V> iterator() {
refreshIfEmpty();
return new WrappedIterator();
}
@@ -496,7 +501,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
}
- @Override public boolean add(V value) {
+ @Override
+ public boolean add(V value) {
refreshIfEmpty();
boolean wasEmpty = delegate.isEmpty();
boolean changed = delegate.add(value);
@@ -515,11 +521,12 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
// The following methods are provided for better performance.
- @Override public boolean addAll(Collection<? extends V> collection) {
+ @Override
+ public boolean addAll(Collection<? extends V> collection) {
if (collection.isEmpty()) {
return false;
}
- int oldSize = size(); // calls refreshIfEmpty
+ int oldSize = size(); // calls refreshIfEmpty
boolean changed = delegate.addAll(collection);
if (changed) {
int newSize = delegate.size();
@@ -531,27 +538,31 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return changed;
}
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
refreshIfEmpty();
return delegate.contains(o);
}
- @Override public boolean containsAll(Collection<?> c) {
+ @Override
+ public boolean containsAll(Collection<?> c) {
refreshIfEmpty();
return delegate.containsAll(c);
}
- @Override public void clear() {
- int oldSize = size(); // calls refreshIfEmpty
+ @Override
+ public void clear() {
+ int oldSize = size(); // calls refreshIfEmpty
if (oldSize == 0) {
return;
}
delegate.clear();
totalSize -= oldSize;
- removeIfEmpty(); // maybe shouldn't be removed if this is a sublist
+ removeIfEmpty(); // maybe shouldn't be removed if this is a sublist
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
refreshIfEmpty();
boolean changed = delegate.remove(o);
if (changed) {
@@ -561,11 +572,12 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return changed;
}
- @Override public boolean removeAll(Collection<?> c) {
+ @Override
+ public boolean removeAll(Collection<?> c) {
if (c.isEmpty()) {
return false;
}
- int oldSize = size(); // calls refreshIfEmpty
+ int oldSize = size(); // calls refreshIfEmpty
boolean changed = delegate.removeAll(c);
if (changed) {
int newSize = delegate.size();
@@ -575,9 +587,10 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return changed;
}
- @Override public boolean retainAll(Collection<?> c) {
+ @Override
+ public boolean retainAll(Collection<?> c) {
checkNotNull(c);
- int oldSize = size(); // calls refreshIfEmpty
+ int oldSize = size(); // calls refreshIfEmpty
boolean changed = delegate.retainAll(c);
if (changed) {
int newSize = delegate.size();
@@ -595,6 +608,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
/** Set decorator that stays in sync with the multimap values for a key. */
+ @WeakOuter
private class WrappedSet extends WrappedCollection implements Set<V> {
WrappedSet(@Nullable K key, Set<V> delegate) {
super(key, delegate, null);
@@ -605,7 +619,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
if (c.isEmpty()) {
return false;
}
- int oldSize = size(); // calls refreshIfEmpty
+ int oldSize = size(); // calls refreshIfEmpty
// Guava issue 1013: AbstractSet and most JDK set implementations are
// susceptible to quadratic removeAll performance on lists;
@@ -623,10 +637,9 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
/**
* SortedSet decorator that stays in sync with the multimap values for a key.
*/
- private class WrappedSortedSet extends WrappedCollection
- implements SortedSet<V> {
- WrappedSortedSet(@Nullable K key, SortedSet<V> delegate,
- @Nullable WrappedCollection ancestor) {
+ @WeakOuter
+ private class WrappedSortedSet extends WrappedCollection implements SortedSet<V> {
+ WrappedSortedSet(@Nullable K key, SortedSet<V> delegate, @Nullable WrappedCollection ancestor) {
super(key, delegate, ancestor);
}
@@ -655,7 +668,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
public SortedSet<V> headSet(V toElement) {
refreshIfEmpty();
return new WrappedSortedSet(
- getKey(), getSortedSetDelegate().headSet(toElement),
+ getKey(),
+ getSortedSetDelegate().headSet(toElement),
(getAncestor() == null) ? this : getAncestor());
}
@@ -663,7 +677,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
public SortedSet<V> subSet(V fromElement, V toElement) {
refreshIfEmpty();
return new WrappedSortedSet(
- getKey(), getSortedSetDelegate().subSet(fromElement, toElement),
+ getKey(),
+ getSortedSetDelegate().subSet(fromElement, toElement),
(getAncestor() == null) ? this : getAncestor());
}
@@ -671,15 +686,16 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
public SortedSet<V> tailSet(V fromElement) {
refreshIfEmpty();
return new WrappedSortedSet(
- getKey(), getSortedSetDelegate().tailSet(fromElement),
+ getKey(),
+ getSortedSetDelegate().tailSet(fromElement),
(getAncestor() == null) ? this : getAncestor());
}
}
/** List decorator that stays in sync with the multimap values for a key. */
+ @WeakOuter
private class WrappedList extends WrappedCollection implements List<V> {
- WrappedList(@Nullable K key, List<V> delegate,
- @Nullable WrappedCollection ancestor) {
+ WrappedList(@Nullable K key, List<V> delegate, @Nullable WrappedCollection ancestor) {
super(key, delegate, ancestor);
}
@@ -692,7 +708,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
if (c.isEmpty()) {
return false;
}
- int oldSize = size(); // calls refreshIfEmpty
+ int oldSize = size(); // calls refreshIfEmpty
boolean changed = getListDelegate().addAll(index, c);
if (changed) {
int newSize = getDelegate().size();
@@ -763,14 +779,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
@Override
public List<V> subList(int fromIndex, int toIndex) {
refreshIfEmpty();
- return wrapList(getKey(),
+ return wrapList(
+ getKey(),
getListDelegate().subList(fromIndex, toIndex),
(getAncestor() == null) ? this : getAncestor());
}
/** ListIterator decorator. */
- private class WrappedListIterator extends WrappedIterator
- implements ListIterator<V> {
+ private class WrappedListIterator extends WrappedIterator implements ListIterator<V> {
WrappedListIterator() {}
public WrappedListIterator(int index) {
@@ -822,10 +838,9 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
* List decorator that stays in sync with the multimap values for a key and
* supports rapid random access.
*/
- private class RandomAccessWrappedList extends WrappedList
- implements RandomAccess {
- RandomAccessWrappedList(@Nullable K key, List<V> delegate,
- @Nullable WrappedCollection ancestor) {
+ private class RandomAccessWrappedList extends WrappedList implements RandomAccess {
+ RandomAccessWrappedList(
+ @Nullable K key, List<V> delegate, @Nullable WrappedCollection ancestor) {
super(key, delegate, ancestor);
}
}
@@ -835,17 +850,19 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
// TreeMultimap uses NavigableKeySet explicitly, but we don't handle that here for GWT
// compatibility reasons
return (map instanceof SortedMap)
- ? new SortedKeySet((SortedMap<K, Collection<V>>) map) : new KeySet(map);
+ ? new SortedKeySet((SortedMap<K, Collection<V>>) map)
+ : new KeySet(map);
}
+ @WeakOuter
private class KeySet extends Maps.KeySet<K, Collection<V>> {
KeySet(final Map<K, Collection<V>> subMap) {
super(subMap);
}
- @Override public Iterator<K> iterator() {
- final Iterator<Map.Entry<K, Collection<V>>> entryIterator
- = map().entrySet().iterator();
+ @Override
+ public Iterator<K> iterator() {
+ final Iterator<Map.Entry<K, Collection<V>>> entryIterator = map().entrySet().iterator();
return new Iterator<K>() {
Map.Entry<K, Collection<V>> entry;
@@ -853,11 +870,13 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
public boolean hasNext() {
return entryIterator.hasNext();
}
+
@Override
public K next() {
entry = entryIterator.next();
return entry.getKey();
}
+
@Override
public void remove() {
checkRemove(entry != null);
@@ -871,7 +890,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
// The following methods are included for better performance.
- @Override public boolean remove(Object key) {
+ @Override
+ public boolean remove(Object key) {
int count = 0;
Collection<V> collection = map().remove(key);
if (collection != null) {
@@ -887,19 +907,23 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
Iterators.clear(iterator());
}
- @Override public boolean containsAll(Collection<?> c) {
+ @Override
+ public boolean containsAll(Collection<?> c) {
return map().keySet().containsAll(c);
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return this == object || this.map().keySet().equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return map().keySet().hashCode();
}
}
+ @WeakOuter
private class SortedKeySet extends KeySet implements SortedSet<K> {
SortedKeySet(SortedMap<K, Collection<V>> subMap) {
@@ -1004,7 +1028,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
* <p>The iterator generated by the returned collection traverses the values
* for one key, followed by the values of a second key, and so on.
*/
- @Override public Collection<V> values() {
+ @Override
+ public Collection<V> values() {
return super.values();
}
@@ -1062,10 +1087,12 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
// TreeMultimap uses NavigableAsMap explicitly, but we don't handle that here for GWT
// compatibility reasons
return (map instanceof SortedMap)
- ? new SortedAsMap((SortedMap<K, Collection<V>>) map) : new AsMap(map);
+ ? new SortedAsMap((SortedMap<K, Collection<V>>) map)
+ : new AsMap(map);
}
- private class AsMap extends ImprovedAbstractMap<K, Collection<V>> {
+ @WeakOuter
+ private class AsMap extends ViewCachingAbstractMap<K, Collection<V>> {
/**
* Usually the same as map, but smaller for the headMap(), tailMap(), or
* subMap() of a SortedAsMap.
@@ -1083,11 +1110,13 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
// The following methods are included for performance.
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return Maps.safeContainsKey(submap, key);
}
- @Override public Collection<V> get(Object key) {
+ @Override
+ public Collection<V> get(Object key) {
Collection<V> collection = Maps.safeGet(submap, key);
if (collection == null) {
return null;
@@ -1097,7 +1126,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return wrapCollection(k, collection);
}
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
return AbstractMapBasedMultimap.this.keySet();
}
@@ -1106,7 +1136,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return submap.size();
}
- @Override public Collection<V> remove(Object key) {
+ @Override
+ public Collection<V> remove(Object key) {
Collection<V> collection = submap.remove(key);
if (collection == null) {
return null;
@@ -1119,15 +1150,18 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return output;
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return this == object || submap.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return submap.hashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return submap.toString();
}
@@ -1145,23 +1179,27 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return Maps.immutableEntry(key, wrapCollection(key, entry.getValue()));
}
+ @WeakOuter
class AsMapEntries extends Maps.EntrySet<K, Collection<V>> {
@Override
Map<K, Collection<V>> map() {
return AsMap.this;
}
- @Override public Iterator<Map.Entry<K, Collection<V>>> iterator() {
+ @Override
+ public Iterator<Map.Entry<K, Collection<V>>> iterator() {
return new AsMapIterator();
}
// The following methods are included for performance.
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
return Collections2.safeContains(submap.entrySet(), o);
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
if (!contains(o)) {
return false;
}
@@ -1173,8 +1211,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
/** Iterator across all keys and value collections. */
class AsMapIterator implements Iterator<Map.Entry<K, Collection<V>>> {
- final Iterator<Map.Entry<K, Collection<V>>> delegateIterator
- = submap.entrySet().iterator();
+ final Iterator<Map.Entry<K, Collection<V>>> delegateIterator = submap.entrySet().iterator();
Collection<V> collection;
@Override
@@ -1198,8 +1235,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
}
- private class SortedAsMap extends AsMap
- implements SortedMap<K, Collection<V>> {
+ @WeakOuter
+ private class SortedAsMap extends AsMap implements SortedMap<K, Collection<V>> {
SortedAsMap(SortedMap<K, Collection<V>> submap) {
super(submap);
}
@@ -1242,7 +1279,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
// returns a SortedSet, even though returning a Set would be sufficient to
// satisfy the SortedMap.keySet() interface
- @Override public SortedSet<K> keySet() {
+ @Override
+ public SortedSet<K> keySet() {
SortedSet<K> result = sortedKeySet;
return (result == null) ? sortedKeySet = createKeySet() : result;
}
@@ -1255,3 +1293,4 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
private static final long serialVersionUID = 2447537837011683357L;
}
+
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultiset.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultiset.java
index e2b9cae..60ec200 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultiset.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/AbstractMapBasedMultiset.java
@@ -42,8 +42,7 @@ import javax.annotation.Nullable;
* @author Kevin Bourrillion
*/
@GwtCompatible(emulated = true)
-abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
- implements Serializable {
+abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E> implements Serializable {
private transient Map<E, Count> backingMap;
@@ -81,8 +80,7 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
@Override
Iterator<Entry<E>> entryIterator() {
- final Iterator<Map.Entry<E, Count>> backingEntries =
- backingMap.entrySet().iterator();
+ final Iterator<Map.Entry<E, Count>> backingEntries = backingMap.entrySet().iterator();
return new Iterator<Multiset.Entry<E>>() {
Map.Entry<E, Count> toRemove;
@@ -100,6 +98,7 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
public E getElement() {
return mapEntry.getKey();
}
+
@Override
public int getCount() {
Count count = mapEntry.getValue();
@@ -140,11 +139,13 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
// Optimizations - Query Operations
- @Override public int size() {
+ @Override
+ public int size() {
return Ints.saturatedCast(size);
}
- @Override public Iterator<E> iterator() {
+ @Override
+ public Iterator<E> iterator() {
return new MapBasedMultisetIterator();
}
@@ -194,7 +195,8 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
}
}
- @Override public int count(@Nullable Object element) {
+ @Override
+ public int count(@Nullable Object element) {
Count frequency = Maps.safeGet(backingMap, element);
return (frequency == null) ? 0 : frequency.get();
}
@@ -208,12 +210,12 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
* {@link Integer#MAX_VALUE} occurrences of {@code element} in this
* multiset.
*/
- @Override public int add(@Nullable E element, int occurrences) {
+ @Override
+ public int add(@Nullable E element, int occurrences) {
if (occurrences == 0) {
return count(element);
}
- checkArgument(
- occurrences > 0, "occurrences cannot be negative: %s", occurrences);
+ checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
Count frequency = backingMap.get(element);
int oldCount;
if (frequency == null) {
@@ -222,20 +224,19 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
} else {
oldCount = frequency.get();
long newCount = (long) oldCount + (long) occurrences;
- checkArgument(newCount <= Integer.MAX_VALUE,
- "too many occurrences: %s", newCount);
+ checkArgument(newCount <= Integer.MAX_VALUE, "too many occurrences: %s", newCount);
frequency.getAndAdd(occurrences);
}
size += occurrences;
return oldCount;
}
- @Override public int remove(@Nullable Object element, int occurrences) {
+ @Override
+ public int remove(@Nullable Object element, int occurrences) {
if (occurrences == 0) {
return count(element);
}
- checkArgument(
- occurrences > 0, "occurrences cannot be negative: %s", occurrences);
+ checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
Count frequency = backingMap.get(element);
if (frequency == null) {
return 0;
@@ -257,7 +258,8 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
}
// Roughly a 33% performance improvement over AbstractMultiset.setCount().
- @Override public int setCount(@Nullable E element, int count) {
+ @Override
+ public int setCount(@Nullable E element, int count) {
checkNonnegative(count, "count");
Count existingCounter;
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimap.java
index 5c12596..3f3f93d 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimap.java
@@ -50,13 +50,13 @@ import java.util.List;
* multimap. Concurrent read operations will work correctly. To allow concurrent
* update operations, wrap your multimap with a call to {@link
* Multimaps#synchronizedListMultimap}.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
* {@code Multimap}</a>.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
@@ -82,8 +82,7 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
* @throws IllegalArgumentException if {@code expectedKeys} or {@code
* expectedValuesPerKey} is negative
*/
- public static <K, V> ArrayListMultimap<K, V> create(
- int expectedKeys, int expectedValuesPerKey) {
+ public static <K, V> ArrayListMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
return new ArrayListMultimap<K, V>(expectedKeys, expectedValuesPerKey);
}
@@ -93,8 +92,7 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
*
* @param multimap the multimap whose contents are copied to this multimap
*/
- public static <K, V> ArrayListMultimap<K, V> create(
- Multimap<? extends K, ? extends V> multimap) {
+ public static <K, V> ArrayListMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
return new ArrayListMultimap<K, V>(multimap);
}
@@ -110,10 +108,11 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
}
private ArrayListMultimap(Multimap<? extends K, ? extends V> multimap) {
- this(multimap.keySet().size(),
- (multimap instanceof ArrayListMultimap) ?
- ((ArrayListMultimap<?, ?>) multimap).expectedValuesPerKey :
- DEFAULT_VALUES_PER_KEY);
+ this(
+ multimap.keySet().size(),
+ (multimap instanceof ArrayListMultimap)
+ ? ((ArrayListMultimap<?, ?>) multimap).expectedValuesPerKey
+ : DEFAULT_VALUES_PER_KEY);
putAll(multimap);
}
@@ -121,7 +120,8 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
* Creates a new, empty {@code ArrayList} to hold the collection of values for
* an arbitrary key.
*/
- @Override List<V> createCollection() {
+ @Override
+ List<V> createCollection() {
return new ArrayList<V>(expectedValuesPerKey);
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayTable.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayTable.java
index 9ac68a1..b798a3e 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayTable.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ArrayTable.java
@@ -23,13 +23,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
+import com.google.common.collect.Maps.IteratorBasedAbstractMap;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
@@ -73,7 +75,7 @@ import javax.annotation.Nullable;
* to one cell and a thread that reads from another.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#table">
* {@code Table}</a>.
*
* @author Jared Levy
@@ -127,8 +129,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
*/
public static <R, C, V> ArrayTable<R, C, V> create(Table<R, C, V> table) {
return (table instanceof ArrayTable<?, ?, ?>)
- ? new ArrayTable<R, C, V>((ArrayTable<R, C, V>) table)
- : new ArrayTable<R, C, V>(table);
+ ? new ArrayTable<R, C, V>((ArrayTable<R, C, V>) table)
+ : new ArrayTable<R, C, V>(table);
}
private final ImmutableList<R> rowList;
@@ -139,8 +141,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
private final ImmutableMap<C, Integer> columnKeyToIndex;
private final V[][] array;
- private ArrayTable(Iterable<? extends R> rowKeys,
- Iterable<? extends C> columnKeys) {
+ private ArrayTable(Iterable<? extends R> rowKeys, Iterable<? extends C> columnKeys) {
this.rowList = ImmutableList.copyOf(rowKeys);
this.columnList = ImmutableList.copyOf(columnKeys);
checkArgument(!rowList.isEmpty());
@@ -151,25 +152,16 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
* columnKeys is empty but rowKeys isn't, the table is empty but
* containsRow() can return true and rowKeySet() isn't empty.
*/
- rowKeyToIndex = index(rowList);
- columnKeyToIndex = index(columnList);
+ rowKeyToIndex = Maps.indexMap(rowList);
+ columnKeyToIndex = Maps.indexMap(columnList);
@SuppressWarnings("unchecked")
- V[][] tmpArray
- = (V[][]) new Object[rowList.size()][columnList.size()];
+ V[][] tmpArray = (V[][]) new Object[rowList.size()][columnList.size()];
array = tmpArray;
// Necessary because in GWT the arrays are initialized with "undefined" instead of null.
eraseAll();
}
- private static <E> ImmutableMap<E, Integer> index(List<E> list) {
- ImmutableMap.Builder<E, Integer> columnBuilder = ImmutableMap.builder();
- for (int i = 0; i < list.size(); i++) {
- columnBuilder.put(list.get(i), i);
- }
- return columnBuilder.build();
- }
-
private ArrayTable(Table<R, C, V> table) {
this(table.rowKeySet(), table.columnKeySet());
putAll(table);
@@ -190,7 +182,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
}
}
- private abstract static class ArrayMap<K, V> extends Maps.ImprovedAbstractMap<K, V> {
+ private abstract static class ArrayMap<K, V> extends IteratorBasedAbstractMap<K, V> {
private final ImmutableMap<K, Integer> keyIndex;
private ArrayMap(ImmutableMap<K, Integer> keyIndex) {
@@ -208,9 +200,11 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
abstract String getKeyRole();
- @Nullable abstract V getValue(int index);
+ @Nullable
+ abstract V getValue(int index);
- @Nullable abstract V setValue(int index, V newValue);
+ @Nullable
+ abstract V setValue(int index, V newValue);
@Override
public int size() {
@@ -223,41 +217,31 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
}
@Override
- protected Set<Entry<K, V>> createEntrySet() {
- return new Maps.EntrySet<K, V>() {
+ Iterator<Entry<K, V>> entryIterator() {
+ return new AbstractIndexedListIterator<Entry<K, V>>(size()) {
@Override
- Map<K, V> map() {
- return ArrayMap.this;
- }
+ protected Entry<K, V> get(final int index) {
+ return new AbstractMapEntry<K, V>() {
+ @Override
+ public K getKey() {
+ return ArrayMap.this.getKey(index);
+ }
- @Override
- public Iterator<Entry<K, V>> iterator() {
- return new AbstractIndexedListIterator<Entry<K, V>>(size()) {
@Override
- protected Entry<K, V> get(final int index) {
- return new AbstractMapEntry<K, V>() {
- @Override
- public K getKey() {
- return ArrayMap.this.getKey(index);
- }
-
- @Override
- public V getValue() {
- return ArrayMap.this.getValue(index);
- }
-
- @Override
- public V setValue(V value) {
- return ArrayMap.this.setValue(index, value);
- }
- };
+ public V getValue() {
+ return ArrayMap.this.getValue(index);
+ }
+
+ @Override
+ public V setValue(V value) {
+ return ArrayMap.this.setValue(index, value);
}
};
}
};
}
- // TODO(user): consider an optimized values() implementation
+ // TODO(lowasser): consider an optimized values() implementation
@Override
public boolean containsKey(@Nullable Object key) {
@@ -363,7 +347,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
* @deprecated Use {@link #eraseAll}
*/
@Override
- @Deprecated public void clear() {
+ @Deprecated
+ public void clear() {
throw new UnsupportedOperationException();
}
@@ -420,8 +405,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
Integer rowIndex = rowKeyToIndex.get(rowKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
- return (rowIndex == null || columnIndex == null)
- ? null : at(rowIndex, columnIndex);
+ return (rowIndex == null || columnIndex == null) ? null : at(rowIndex, columnIndex);
}
/**
@@ -445,8 +429,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
Integer rowIndex = rowKeyToIndex.get(rowKey);
checkArgument(rowIndex != null, "Row %s not in %s", rowKey, rowList);
Integer columnIndex = columnKeyToIndex.get(columnKey);
- checkArgument(columnIndex != null,
- "Column %s not in %s", columnKey, columnList);
+ checkArgument(columnIndex != null, "Column %s not in %s", columnKey, columnList);
return set(rowIndex, columnIndex, value);
}
@@ -478,7 +461,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
* @deprecated Use {@link #erase}
*/
@Override
- @Deprecated public V remove(Object rowKey, Object columnKey) {
+ @Deprecated
+ public V remove(Object rowKey, Object columnKey) {
throw new UnsupportedOperationException();
}
@@ -532,18 +516,22 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
@Override
Iterator<Cell<R, C, V>> cellIterator() {
return new AbstractIndexedListIterator<Cell<R, C, V>>(size()) {
- @Override protected Cell<R, C, V> get(final int index) {
+ @Override
+ protected Cell<R, C, V> get(final int index) {
return new Tables.AbstractCell<R, C, V>() {
final int rowIndex = index / columnList.size();
final int columnIndex = index % columnList.size();
+
@Override
public R getRowKey() {
return rowList.get(rowIndex);
}
+
@Override
public C getColumnKey() {
return columnList.get(columnIndex);
}
+
@Override
public V getValue() {
return at(rowIndex, columnIndex);
@@ -569,8 +557,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
public Map<R, V> column(C columnKey) {
checkNotNull(columnKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
- return (columnIndex == null)
- ? ImmutableMap.<R, V>of() : new Column(columnIndex);
+ return (columnIndex == null) ? ImmutableMap.<R, V>of() : new Column(columnIndex);
}
private class Column extends ArrayMap<R, V> {
@@ -616,6 +603,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
return (map == null) ? columnMap = new ColumnMap() : map;
}
+ @WeakOuter
private class ColumnMap extends ArrayMap<C, Map<R, V>> {
private ColumnMap() {
super(columnKeyToIndex);
@@ -705,6 +693,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
return (map == null) ? rowMap = new RowMap() : map;
}
+ @WeakOuter
private class RowMap extends ArrayMap<R, Map<C, V>> {
private RowMap() {
super(rowKeyToIndex);
@@ -747,3 +736,4 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
private static final long serialVersionUID = 0;
}
+
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/BinaryTreeTraverser.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/BinaryTreeTraverser.java
index 6c87148..ae40605 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/BinaryTreeTraverser.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/BinaryTreeTraverser.java
@@ -30,7 +30,7 @@ import java.util.Iterator;
* @author Louis Wasserman
*/
public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> {
- // TODO(user): make this GWT-compatible when we've checked in ArrayDeque and BitSet emulation
+ // TODO(lowasser): make this GWT-compatible when we've checked in ArrayDeque and BitSet emulation
/**
* Returns the left child of the specified node, or {@link Optional#absent()} if the specified
@@ -80,7 +80,7 @@ public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> {
};
}
- // TODO(user): see if any significant optimizations are possible for breadthFirstIterator
+ // TODO(lowasser): see if any significant optimizations are possible for breadthFirstIterator
public final FluentIterable<T> inOrderTraversal(final T root) {
checkNotNull(root);
@@ -91,11 +91,11 @@ public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> {
}
};
}
-
+
private static final class InOrderNode<T> {
final T node;
boolean hasExpandedLeft;
-
+
InOrderNode(T node) {
this.node = checkNotNull(node);
this.hasExpandedLeft = false;
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ContiguousSet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ContiguousSet.java
index 0c8393a..015a81e 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ContiguousSet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ContiguousSet.java
@@ -63,10 +63,12 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
}
// Per class spec, we are allowed to throw CCE if necessary
- boolean empty = effectiveRange.isEmpty()
- || Range.compareOrThrow(
- range.lowerBound.leastValueAbove(domain),
- range.upperBound.greatestValueBelow(domain)) > 0;
+ boolean empty =
+ effectiveRange.isEmpty()
+ || Range.compareOrThrow(
+ range.lowerBound.leastValueAbove(domain),
+ range.upperBound.greatestValueBelow(domain))
+ > 0;
return empty
? new EmptyContiguousSet<C>(domain)
@@ -80,30 +82,37 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
this.domain = domain;
}
- @Override public ContiguousSet<C> headSet(C toElement) {
+ @Override
+ public ContiguousSet<C> headSet(C toElement) {
return headSetImpl(checkNotNull(toElement), false);
}
- @Override public ContiguousSet<C> subSet(C fromElement, C toElement) {
+ @Override
+ public ContiguousSet<C> subSet(C fromElement, C toElement) {
checkNotNull(fromElement);
checkNotNull(toElement);
checkArgument(comparator().compare(fromElement, toElement) <= 0);
return subSetImpl(fromElement, true, toElement, false);
}
- @Override public ContiguousSet<C> tailSet(C fromElement) {
+ @Override
+ public ContiguousSet<C> tailSet(C fromElement) {
return tailSetImpl(checkNotNull(fromElement), true);
}
/*
* These methods perform most headSet, subSet, and tailSet logic, besides parameter validation.
*/
- /*@Override*/ abstract ContiguousSet<C> headSetImpl(C toElement, boolean inclusive);
+ // TODO(kevinb): we can probably make these real @Overrides now
+ /*@Override*/
+ abstract ContiguousSet<C> headSetImpl(C toElement, boolean inclusive);
- /*@Override*/ abstract ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive,
- C toElement, boolean toInclusive);
+ /*@Override*/
+ abstract ContiguousSet<C> subSetImpl(
+ C fromElement, boolean fromInclusive, C toElement, boolean toInclusive);
- /*@Override*/ abstract ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive);
+ /*@Override*/
+ abstract ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive);
/**
* Returns the set of values that are contained in both this set and the other.
@@ -135,7 +144,8 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
public abstract Range<C> range(BoundType lowerBoundType, BoundType upperBoundType);
/** Returns a short-hand representation of the contents such as {@code "[1..100]"}. */
- @Override public String toString() {
+ @Override
+ public String toString() {
return range().toString();
}
@@ -147,7 +157,8 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
* @throws UnsupportedOperationException always
* @deprecated Use {@link #create}.
*/
- @Deprecated public static <E> ImmutableSortedSet.Builder<E> builder() {
+ @Deprecated
+ public static <E> ImmutableSortedSet.Builder<E> builder() {
throw new UnsupportedOperationException();
}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyContiguousSet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyContiguousSet.java
index 368e856..927e889 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyContiguousSet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyContiguousSet.java
@@ -10,7 +10,7 @@
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
-*/
+ */
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
@@ -32,64 +32,84 @@ final class EmptyContiguousSet<C extends Comparable> extends ContiguousSet<C> {
super(domain);
}
- @Override public C first() {
+ @Override
+ public C first() {
throw new NoSuchElementException();
}
- @Override public C last() {
+ @Override
+ public C last() {
throw new NoSuchElementException();
}
- @Override public int size() {
+ @Override
+ public int size() {
return 0;
}
- @Override public ContiguousSet<C> intersection(ContiguousSet<C> other) {
+ @Override
+ public ContiguousSet<C> intersection(ContiguousSet<C> other) {
return this;
}
- @Override public Range<C> range() {
+ @Override
+ public Range<C> range() {
throw new NoSuchElementException();
}
- @Override public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
+ @Override
+ public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
throw new NoSuchElementException();
}
- @Override ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
+ @Override
+ ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
return this;
}
- @Override ContiguousSet<C> subSetImpl(
+ @Override
+ ContiguousSet<C> subSetImpl(
C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
return this;
}
- @Override ContiguousSet<C> tailSetImpl(C fromElement, boolean fromInclusive) {
+ @Override
+ ContiguousSet<C> tailSetImpl(C fromElement, boolean fromInclusive) {
return this;
}
- @Override public UnmodifiableIterator<C> iterator() {
+ @Override
+ public boolean contains(Object object) {
+ return false;
+ }
+
+ @Override
+ public UnmodifiableIterator<C> iterator() {
return Iterators.emptyIterator();
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return false;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return true;
}
- @Override public ImmutableList<C> asList() {
+ @Override
+ public ImmutableList<C> asList() {
return ImmutableList.of();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "[]";
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object instanceof Set) {
Set<?> that = (Set<?>) object;
return that.isEmpty();
@@ -97,7 +117,8 @@ final class EmptyContiguousSet<C extends Comparable> extends ContiguousSet<C> {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return 0;
}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedMap.java
deleted file mode 100644
index 4159cd4..0000000
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedMap.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2012 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.collect;
-
-import java.util.Comparator;
-import java.util.TreeMap;
-
-/**
- * GWT emulated version of {@link EmptyImmutableSortedMap}.
- *
- * @author Chris Povirk
- */
-final class EmptyImmutableSortedMap<K, V> extends ImmutableSortedMap<K, V> {
- private EmptyImmutableSortedMap(Comparator<? super K> comparator) {
- super(new TreeMap<K, V>(comparator), comparator);
- }
-
- @SuppressWarnings("unchecked")
- private static final ImmutableSortedMap<Object, Object> NATURAL_EMPTY_MAP =
- new EmptyImmutableSortedMap<Object, Object>(NATURAL_ORDER);
-
- static <K, V> ImmutableSortedMap<K, V> forComparator(Comparator<? super K> comparator) {
- if (comparator == NATURAL_ORDER) {
- return (ImmutableSortedMap) NATURAL_EMPTY_MAP;
- }
- return new EmptyImmutableSortedMap<K, V>(comparator);
- }
-}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumBiMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumBiMap.java
index 46fa641..a3f4757 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumBiMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumBiMap.java
@@ -28,17 +28,16 @@ import java.util.Map;
* A {@code BiMap} backed by two {@code EnumMap} instances. Null keys and values
* are not permitted. An {@code EnumBiMap} and its inverse are both
* serializable.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap">
* {@code BiMap}</a>.
*
* @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
-public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
- extends AbstractBiMap<K, V> {
+public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>> extends AbstractBiMap<K, V> {
private transient Class<K> keyType;
private transient Class<V> valueType;
@@ -49,8 +48,8 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
* @param keyType the key type
* @param valueType the value type
*/
- public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V>
- create(Class<K> keyType, Class<V> valueType) {
+ public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V> create(
+ Class<K> keyType, Class<V> valueType) {
return new EnumBiMap<K, V>(keyType, valueType);
}
@@ -64,15 +63,15 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
* @throws IllegalArgumentException if map is not an {@code EnumBiMap}
* instance and contains no mappings
*/
- public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V>
- create(Map<K, V> map) {
+ public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V> create(Map<K, V> map) {
EnumBiMap<K, V> bimap = create(inferKeyType(map), inferValueType(map));
bimap.putAll(map);
return bimap;
}
private EnumBiMap(Class<K> keyType, Class<V> valueType) {
- super(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
+ super(
+ WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
WellBehavedMap.wrap(new EnumMap<V, K>(valueType)));
this.keyType = keyType;
this.valueType = valueType;
@@ -86,7 +85,11 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
return ((EnumHashBiMap<K, ?>) map).keyType();
}
checkArgument(!map.isEmpty());
- return map.keySet().iterator().next().getDeclaringClass();
+ return map
+ .keySet()
+ .iterator()
+ .next()
+ .getDeclaringClass();
}
private static <V extends Enum<V>> Class<V> inferValueType(Map<?, V> map) {
@@ -94,7 +97,11 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
return ((EnumBiMap<?, V>) map).valueType;
}
checkArgument(!map.isEmpty());
- return map.values().iterator().next().getDeclaringClass();
+ return map
+ .values()
+ .iterator()
+ .next()
+ .getDeclaringClass();
}
/** Returns the associated key type. */
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumHashBiMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumHashBiMap.java
index 3d9503f..3ff3ce5 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumHashBiMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumHashBiMap.java
@@ -30,17 +30,16 @@ import javax.annotation.Nullable;
* a {@code HashMap} instance for values-to-keys. Null keys are not permitted,
* but null values are. An {@code EnumHashBiMap} and its inverse are both
* serializable.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap">
* {@code BiMap}</a>.
*
* @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
-public final class EnumHashBiMap<K extends Enum<K>, V>
- extends AbstractBiMap<K, V> {
+public final class EnumHashBiMap<K extends Enum<K>, V> extends AbstractBiMap<K, V> {
private transient Class<K> keyType;
/**
@@ -48,8 +47,7 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
*
* @param keyType the key type
*/
- public static <K extends Enum<K>, V> EnumHashBiMap<K, V>
- create(Class<K> keyType) {
+ public static <K extends Enum<K>, V> EnumHashBiMap<K, V> create(Class<K> keyType) {
return new EnumHashBiMap<K, V>(keyType);
}
@@ -63,18 +61,16 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
* @throws IllegalArgumentException if map is not an {@code EnumBiMap} or an
* {@code EnumHashBiMap} instance and contains no mappings
*/
- public static <K extends Enum<K>, V> EnumHashBiMap<K, V>
- create(Map<K, ? extends V> map) {
+ public static <K extends Enum<K>, V> EnumHashBiMap<K, V> create(Map<K, ? extends V> map) {
EnumHashBiMap<K, V> bimap = create(EnumBiMap.inferKeyType(map));
bimap.putAll(map);
return bimap;
}
private EnumHashBiMap(Class<K> keyType) {
- super(WellBehavedMap.wrap(
- new EnumMap<K, V>(keyType)),
- Maps.<V, K>newHashMapWithExpectedSize(
- keyType.getEnumConstants().length));
+ super(
+ WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
+ Maps.<V, K>newHashMapWithExpectedSize(keyType.getEnumConstants().length));
this.keyType = keyType;
}
@@ -85,11 +81,13 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
return checkNotNull(key);
}
- @Override public V put(K key, @Nullable V value) {
+ @Override
+ public V put(K key, @Nullable V value) {
return super.put(key, value);
}
- @Override public V forcePut(K key, @Nullable V value) {
+ @Override
+ public V forcePut(K key, @Nullable V value) {
return super.forcePut(key, value);
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumMultiset.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumMultiset.java
index 4e769fb..e463409 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumMultiset.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EnumMultiset.java
@@ -23,13 +23,13 @@ import java.util.Iterator;
/**
* Multiset implementation backed by an {@link EnumMap}.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
* {@code Multiset}</a>.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class EnumMultiset<E extends Enum<E>> extends AbstractMapBasedMultiset<E> {
@@ -54,12 +54,12 @@ public final class EnumMultiset<E extends Enum<E>> extends AbstractMapBasedMulti
Iterables.addAll(multiset, elements);
return multiset;
}
-
+
/**
* Returns a new {@code EnumMultiset} instance containing the given elements. Unlike
* {@link EnumMultiset#create(Iterable)}, this method does not produce an exception on an empty
* iterable.
- *
+ *
* @since 14.0
*/
public static <E extends Enum<E>> EnumMultiset<E> create(Iterable<E> elements, Class<E> type) {
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/FluentIterable.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/FluentIterable.java
index 641b052..c98fc2f 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/FluentIterable.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/FluentIterable.java
@@ -36,34 +36,72 @@ import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
- * {@code FluentIterable} provides a rich interface for manipulating {@code Iterable} instances in a
- * chained fashion. A {@code FluentIterable} can be created from an {@code Iterable}, or from a set
- * of elements. The following types of methods are provided on {@code FluentIterable}:
+ * An expanded {@code Iterable} API, providing functionality similar to Java 8's powerful <a href=
+ * "https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#package.description"
+ * >streams library</a> in a slightly different way.
+ *
+ * <p>The following types of methods are provided:
+ *
* <ul>
- * <li>chained methods which return a new {@code FluentIterable} based in some way on the contents
- * of the current one (for example {@link #transform})
- * <li>conversion methods which copy the {@code FluentIterable}'s contents into a new collection or
- * array (for example {@link #toList})
+ * <li>chaining methods which return a new {@code FluentIterable} based in some way on the contents
+ * of the current one (for example {@link #transform})
* <li>element extraction methods which facilitate the retrieval of certain elements (for example
- * {@link #last})
+ * {@link #last})
* <li>query methods which answer questions about the {@code FluentIterable}'s contents (for example
- * {@link #anyMatch})
+ * {@link #anyMatch})
+ * <li>conversion methods which copy the {@code FluentIterable}'s contents into a new collection or
+ * array (for example {@link #toList})
+ * </ul>
+ *
+ * <p>Several lesser-used features are currently available only as static methods on the {@link
+ * Iterables} class.
+ *
+ * <a name="streams"></a>
+ * <h3>Comparison to streams</h3>
+ *
+ * <p>Starting with Java 8, the core Java class libraries provide a new "Streams" library (in {@code
+ * java.util.stream}), which is similar to {@code FluentIterable} but generally more powerful. Key
+ * differences include:</b>
+ *
+ * <ul>
+ * <li>A stream is <i>single-use</i>; it becomes invalid as soon as any "terminal operation" such as
+ * {@code findFirst()} or {@code iterator()} is invoked. (Even though {@code Stream} contains
+ * all the right method <i>signatures</i> to implement {@link Iterable}, it does not actually
+ * do so, to avoid implying repeat-iterability.) {@code FluentIterable}, on the other hand, is
+ * multiple-use, and does implement {@link Iterable}.
+ * <li>Streams offer many features not found here, including {@code min/max}, {@code
+ * distinct}, {@code reduce}, {@code sorted}, the very powerful {@code collect}, and built-in
+ * support for parallelizing stream operations.
+ * <li>{@code FluentIterable} contains several features not available on {@code Stream}, which are
+ * noted in the method descriptions below.
+ * <li>Streams include primitive-specialized variants such as {@code IntStream}, the use of which is
+ * strongly recommended.
+ * <li>Streams are standard Java, not requiring a third-party dependency (but do render your code
+ * incompatible with Java 7 and earlier).
* </ul>
*
- * <p>Here is an example that merges the lists returned by two separate database calls, transforms
- * it by invoking {@code toString()} on each element, and returns the first 10 elements as an
- * {@code ImmutableList}: <pre> {@code
+ * <h3>Example</h3>
*
- * FluentIterable
- * .from(database.getClientList())
- * .filter(activeInLastMonth())
- * .transform(Functions.toStringFunction())
- * .limit(10)
- * .toList();}</pre>
+ * <p>Here is an example that accepts a list from a database call, filters it based on a predicate,
+ * transforms it by invoking {@code toString()} on each element, and returns the first 10 elements
+ * as a {@code List}: <pre> {@code
*
- * <p>Anything which can be done using {@code FluentIterable} could be done in a different fashion
- * (often with {@link Iterables}), however the use of {@code FluentIterable} makes many sets of
- * operations significantly more concise.
+ * List<String> results =
+ * FluentIterable.from(database.getClientList())
+ * .filter(activeInLastMonthPredicate)
+ * .transform(Functions.toStringFunction())
+ * .limit(10)
+ * .toList();}</pre>
+ *
+ * The approximate stream equivalent is: <pre> {@code
+ *
+ * List<String> results =
+ * database.getClientList()
+ * .stream()
+ * .filter(activeInLastMonthPredicate)
+ * .map(Functions.toStringFunction())
+ * .limit(10)
+ * .collect(Collectors.toList());}</pre>
*
* @author Marcin Mikosik
* @since 12.0
@@ -86,9 +124,14 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns a fluent iterable that wraps {@code iterable}, or {@code iterable} itself if it
* is already a {@code FluentIterable}.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code iterable.stream()} if {@code iterable} is a
+ * {@link Collection}; {@code StreamSupport.stream(iterable.spliterator(), false)} otherwise.
*/
+ @CheckReturnValue
public static <E> FluentIterable<E> from(final Iterable<E> iterable) {
- return (iterable instanceof FluentIterable) ? (FluentIterable<E>) iterable
+ return (iterable instanceof FluentIterable)
+ ? (FluentIterable<E>) iterable
: new FluentIterable<E>(iterable) {
@Override
public Iterator<E> iterator() {
@@ -106,6 +149,7 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* {@code FluentIterable}
*/
@Deprecated
+ @CheckReturnValue
public static <E> FluentIterable<E> from(FluentIterable<E> iterable) {
return checkNotNull(iterable);
}
@@ -113,9 +157,13 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns a fluent iterable containing {@code elements} in the specified order.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code Stream.of(elements)} or {@code
+ * Arrays.stream(elements)}.
+ *
* @since 18.0
*/
@Beta
+ @CheckReturnValue
public static <E> FluentIterable<E> of(E[] elements) {
return from(Lists.newArrayList(elements));
}
@@ -123,25 +171,35 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns a string representation of this fluent iterable, with the format
* {@code [e1, e2, ..., en]}.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.collect(Collectors.joining(", ", "[", "]"))}
+ * or (less efficiently) {@code collect(Collectors.toList()).toString()}.
*/
@Override
+ @CheckReturnValue
public String toString() {
return Iterables.toString(iterable);
}
/**
* Returns the number of elements in this fluent iterable.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.count()}.
*/
+ @CheckReturnValue
public final int size() {
return Iterables.size(iterable);
}
/**
* Returns {@code true} if this fluent iterable contains any object for which
- * {@code equals(element)} is true.
+ * {@code equals(target)} is true.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.anyMatch(Predicate.isEqual(target))}.
*/
- public final boolean contains(@Nullable Object element) {
- return Iterables.contains(iterable, element);
+ @CheckReturnValue
+ public final boolean contains(@Nullable Object target) {
+ return Iterables.contains(iterable, target);
}
/**
@@ -156,6 +214,11 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* <p><b>Warning:</b> Typical uses of the resulting iterator may produce an infinite loop. You
* should use an explicit {@code break} or be certain that you will eventually remove all the
* elements.
+ *
+ * <p><b>{@code Stream} equivalent:</b> if the source iterable has only a single element {@code
+ * element}, use {@code Stream.generate(() -> element)}. Otherwise, if the source iterable has
+ * a {@code stream} method (for example, if it is a {@link Collection}), use
+ * {@code Stream.generate(iterable::stream).flatMap(s -> s)}.
*/
@CheckReturnValue
public final FluentIterable<E> cycle() {
@@ -169,6 +232,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* <p>The returned iterable's {@code Iterator} supports {@code remove()} when the corresponding
* {@code Iterator} supports it.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code Stream.concat(thisStream, otherStream)}.
+ *
* @since 18.0
*/
@Beta
@@ -181,6 +246,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Returns a fluent iterable whose iterators traverse first the elements of this fluent iterable,
* followed by {@code elements}.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code Stream.concat(thisStream, Stream.of(elements))}.
+ *
* @since 18.0
*/
@Beta
@@ -192,6 +259,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns the elements from this fluent iterable that satisfy a predicate. The
* resulting fluent iterable's iterator does not support {@code remove()}.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.filter(predicate)} (same).
*/
@CheckReturnValue
public final FluentIterable<E> filter(Predicate<? super E> predicate) {
@@ -200,7 +269,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns {@code true} if any element in this fluent iterable satisfies the predicate.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.anyMatch(predicate)} (same).
*/
+ @CheckReturnValue
public final boolean anyMatch(Predicate<? super E> predicate) {
return Iterables.any(iterable, predicate);
}
@@ -208,7 +280,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns {@code true} if every element in this fluent iterable satisfies the predicate.
* If this fluent iterable is empty, {@code true} is returned.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.allMatch(predicate)} (same).
*/
+ @CheckReturnValue
public final boolean allMatch(Predicate<? super E> predicate) {
return Iterables.all(iterable, predicate);
}
@@ -219,7 +294,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
*
* <p><b>Warning:</b> avoid using a {@code predicate} that matches {@code null}. If {@code null}
* is matched in this fluent iterable, a {@link NullPointerException} will be thrown.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.filter(predicate).findFirst()}.
*/
+ @CheckReturnValue
public final Optional<E> firstMatch(Predicate<? super E> predicate) {
return Iterables.tryFind(iterable, predicate);
}
@@ -231,7 +309,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* <p>The returned fluent iterable's iterator supports {@code remove()} if this iterable's
* iterator does. After a successful {@code remove()} call, this fluent iterable no longer
* contains the corresponding element.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.map(function)}.
*/
+ @CheckReturnValue
public final <T> FluentIterable<T> transform(Function<? super E, T> function) {
return from(Iterables.transform(iterable, function));
}
@@ -245,8 +326,12 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* function-returned iterables' iterator does. After a successful {@code remove()} call,
* the returned fluent iterable no longer contains the corresponding element.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.flatMap(function)} (using a function that
+ * produces streams, not iterables).
+ *
* @since 13.0 (required {@code Function<E, Iterable<T>>} until 14.0)
*/
+ @CheckReturnValue
public <T> FluentIterable<T> transformAndConcat(
Function<? super E, ? extends Iterable<? extends T>> function) {
return from(Iterables.concat(transform(function)));
@@ -256,23 +341,29 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Returns an {@link Optional} containing the first element in this fluent iterable.
* If the iterable is empty, {@code Optional.absent()} is returned.
*
+ * <p><b>{@code Stream} equivalent:</b> if the goal is to obtain any element, {@code
+ * stream.findAny()}; if it must specifically be the <i>first</i> element, {@code
+ * stream.findFirst()}.
+ *
* @throws NullPointerException if the first element is null; if this is a possibility, use
* {@code iterator().next()} or {@link Iterables#getFirst} instead.
*/
+ @CheckReturnValue
public final Optional<E> first() {
Iterator<E> iterator = iterable.iterator();
- return iterator.hasNext()
- ? Optional.of(iterator.next())
- : Optional.<E>absent();
+ return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.<E>absent();
}
/**
* Returns an {@link Optional} containing the last element in this fluent iterable.
* If the iterable is empty, {@code Optional.absent()} is returned.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.reduce((a, b) -> b)}.
+ *
* @throws NullPointerException if the last element is null; if this is a possibility, use
* {@link Iterables#getLast} instead.
*/
+ @CheckReturnValue
public final Optional<E> last() {
// Iterables#getLast was inlined here so we don't have to throw/catch a NSEE
@@ -323,6 +414,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* returned fluent iterable's iterator, as the {@code Iterator} contract states that a call
* to {@code * remove()} before a call to {@code next()} will throw an
* {@link IllegalStateException}.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.skip(numberToSkip)} (same).
*/
@CheckReturnValue
public final FluentIterable<E> skip(int numberToSkip) {
@@ -336,17 +429,22 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* The returned fluent iterable's iterator supports {@code remove()} if this
* fluent iterable's iterator does.
*
- * @param size the maximum number of elements in the returned fluent iterable
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.limit(maxSize)} (same).
+ *
+ * @param maxSize the maximum number of elements in the returned fluent iterable
* @throws IllegalArgumentException if {@code size} is negative
*/
@CheckReturnValue
- public final FluentIterable<E> limit(int size) {
- return from(Iterables.limit(iterable, size));
+ public final FluentIterable<E> limit(int maxSize) {
+ return from(Iterables.limit(iterable, maxSize));
}
/**
* Determines whether this fluent iterable is empty.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code !stream.findAny().isPresent()}.
*/
+ @CheckReturnValue
public final boolean isEmpty() {
return !iterable.iterator().hasNext();
}
@@ -355,8 +453,11 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Returns an {@code ImmutableList} containing all of the elements from this fluent iterable in
* proper sequence.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code ImmutableList.copyOf(stream.iterator())}.
+ *
* @since 14.0 (since 12.0 as {@code toImmutableList()}).
*/
+ @CheckReturnValue
public final ImmutableList<E> toList() {
return ImmutableList.copyOf(iterable);
}
@@ -366,10 +467,14 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* FluentIterable} in the order specified by {@code comparator}. To produce an {@code
* ImmutableList} sorted by its natural ordering, use {@code toSortedList(Ordering.natural())}.
*
+ * <p><b>{@code Stream} equivalent:</b>
+ * {@code ImmutableList.copyOf(stream.sorted(comparator).iterator())}.
+ *
* @param comparator the function by which to sort list elements
* @throws NullPointerException if any element is null
* @since 14.0 (since 13.0 as {@code toSortedImmutableList()}).
*/
+ @CheckReturnValue
public final ImmutableList<E> toSortedList(Comparator<? super E> comparator) {
return Ordering.from(comparator).immutableSortedCopy(iterable);
}
@@ -378,8 +483,11 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Returns an {@code ImmutableSet} containing all of the elements from this fluent iterable with
* duplicates removed.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code ImmutableSet.copyOf(stream.iterator())}.
+ *
* @since 14.0 (since 12.0 as {@code toImmutableSet()}).
*/
+ @CheckReturnValue
public final ImmutableSet<E> toSet() {
return ImmutableSet.copyOf(iterable);
}
@@ -390,24 +498,48 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* {@code comparator.compare(x, y) == 0}) removed. To produce an {@code ImmutableSortedSet} sorted
* by its natural ordering, use {@code toSortedSet(Ordering.natural())}.
*
+ * <p><b>{@code Stream} equivalent:</b>
+ * {@code ImmutableSortedSet.copyOf(comparator, stream.iterator())}.
+ *
* @param comparator the function by which to sort set elements
* @throws NullPointerException if any element is null
* @since 14.0 (since 12.0 as {@code toImmutableSortedSet()}).
*/
+ @CheckReturnValue
public final ImmutableSortedSet<E> toSortedSet(Comparator<? super E> comparator) {
return ImmutableSortedSet.copyOf(comparator, iterable);
}
/**
- * Returns an immutable map for which the elements of this {@code FluentIterable} are the keys in
- * the same order, mapped to values by the given function. If this iterable contains duplicate
- * elements, the returned map will contain each distinct element once in the order it first
- * appears.
+ * Returns an {@code ImmutableMultiset} containing all of the elements from this fluent iterable.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code ImmutableMultiset.copyOf(stream.iterator())}.
+ *
+ * @since 19.0
+ */
+ @CheckReturnValue
+ public final ImmutableMultiset<E> toMultiset() {
+ return ImmutableMultiset.copyOf(iterable);
+ }
+
+ /**
+ * Returns an immutable map whose keys are the distinct elements of this {@code FluentIterable}
+ * and whose value for each key was computed by {@code valueFunction}. The map's iteration order
+ * is the order of the first appearance of each key in this iterable.
+ *
+ * <p>When there are multiple instances of a key in this iterable, it is unspecified whether
+ * {@code valueFunction} will be applied to more than one instance of that key and, if it is,
+ * which result will be mapped to that key in the returned map.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code
+ * ImmutableMap.copyOf(stream.collect(Collectors.toMap(k -> k, valueFunction)))} (but note that
+ * this may not preserve the order of entries).
*
* @throws NullPointerException if any element of this iterable is {@code null}, or if {@code
* valueFunction} produces {@code null} for any key
* @since 14.0
*/
+ @CheckReturnValue
public final <V> ImmutableMap<E, V> toMap(Function<? super E, V> valueFunction) {
return Maps.toMap(iterable, valueFunction);
}
@@ -428,24 +560,49 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* <li>An element in this fluent iterable is null
* <li>{@code keyFunction} returns {@code null} for any element of this iterable
* </ul>
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.collect(Collectors.groupingBy(keyFunction))}
+ * behaves similarly, but returns a mutable {@code Map<K, List<E>>} instead, and may not preserve
+ * the order of entries).
+ *
* @since 14.0
*/
+ @CheckReturnValue
public final <K> ImmutableListMultimap<K, E> index(Function<? super E, K> keyFunction) {
return Multimaps.index(iterable, keyFunction);
}
/**
- * Returns an immutable map for which the {@link java.util.Map#values} are the elements of this
- * {@code FluentIterable} in the given order, and each key is the product of invoking a supplied
- * function on its corresponding value.
+ * Returns a map with the contents of this {@code FluentIterable} as its {@code values}, indexed
+ * by keys derived from those values. In other words, each input value produces an entry in the
+ * map whose key is the result of applying {@code keyFunction} to that value. These entries appear
+ * in the same order as they appeared in this fluent iterable. Example usage:
+ * <pre> {@code
+ *
+ * Color red = new Color("red", 255, 0, 0);
+ * ...
+ * FluentIterable<Color> allColors = FluentIterable.from(ImmutableSet.of(red, green, blue));
+ *
+ * Map<String, Color> colorForName = allColors.uniqueIndex(toStringFunction());
+ * assertThat(colorForName).containsEntry("red", red);}</pre>
+ *
+ * <p>If your index may associate multiple values with each key, use {@link #index(Function)
+ * index}.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code
+ * ImmutableMap.copyOf(stream.collect(Collectors.toMap(keyFunction, v -> v)))} (but note that this
+ * may not preserve the order of entries).
*
* @param keyFunction the function used to produce the key for each value
- * @throws IllegalArgumentException if {@code keyFunction} produces the same key for more than one
- * value in this fluent iterable
- * @throws NullPointerException if any element of this fluent iterable is null, or if
- * {@code keyFunction} produces {@code null} for any value
+ * @return a map mapping the result of evaluating the function {@code
+ * keyFunction} on each value in this fluent iterable to that value
+ * @throws IllegalArgumentException if {@code keyFunction} produces the same
+ * key for more than one value in this fluent iterable
+ * @throws NullPointerException if any elements of this fluent iterable is null, or
+ * if {@code keyFunction} produces {@code null} for any value
* @since 14.0
*/
+ @CheckReturnValue
public final <K> ImmutableMap<K, E> uniqueIndex(Function<? super E, K> keyFunction) {
return Maps.uniqueIndex(iterable, keyFunction);
}
@@ -454,6 +611,9 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Copies all the elements from this fluent iterable to {@code collection}. This is equivalent to
* calling {@code Iterables.addAll(collection, this)}.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.forEachOrdered(collection::add)} or
+ * {@code stream.forEach(collection::add)}.
+ *
* @param collection the collection to copy elements to
* @return {@code collection}, for convenience
* @since 14.0
@@ -474,9 +634,14 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Returns a {@link String} containing all of the elements of this fluent iterable joined with
* {@code joiner}.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code joiner.join(stream.iterator())}, or, if you are not
+ * using any optional {@code Joiner} features,
+ * {@code stream.collect(Collectors.joining(delimiter)}.
+ *
* @since 18.0
*/
@Beta
+ @CheckReturnValue
public final String join(Joiner joiner) {
return joiner.join(this);
}
@@ -484,11 +649,17 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns the element at the specified position in this fluent iterable.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.skip(position).findFirst().get()} (but note
+ * that this throws different exception types, and throws an exception if {@code null} would be
+ * returned).
+ *
* @param position position of the element to return
* @return the element at the specified position in this fluent iterable
* @throws IndexOutOfBoundsException if {@code position} is negative or greater than or equal to
* the size of this fluent iterable
*/
+ // TODO(kevinb): add @Nullable?
+ @CheckReturnValue
public final E get(int position) {
return Iterables.get(iterable, position);
}
@@ -496,8 +667,7 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Function that transforms {@code Iterable<E>} into a fluent iterable.
*/
- private static class FromIterableFunction<E>
- implements Function<Iterable<E>, FluentIterable<E>> {
+ private static class FromIterableFunction<E> implements Function<Iterable<E>, FluentIterable<E>> {
@Override
public FluentIterable<E> apply(Iterable<E> fromObject) {
return FluentIterable.from(fromObject);
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/GenericMapMaker.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/GenericMapMaker.java
index 6240625..164b90c 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/GenericMapMaker.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/GenericMapMaker.java
@@ -36,7 +36,7 @@ import java.util.concurrent.TimeUnit;
* com.google.common.cache.CacheBuilder}, which is a properly generified class and thus needs no
* "Generic" equivalent; simple use {@code CacheBuilder} naturally. For general migration
* instructions, see the <a
- * href="http://code.google.com/p/guava-libraries/wiki/MapMakerMigration">MapMaker Migration
+ * href="https://github.com/google/guava/wiki/MapMakerMigration">MapMaker Migration
* Guide</a>.
*/
@Beta
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultimap.java
index 582c2f7..196661f 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultimap.java
@@ -39,14 +39,13 @@ import java.util.Set;
* Multimaps#synchronizedSetMultimap}.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
private static final int DEFAULT_VALUES_PER_KEY = 2;
- @VisibleForTesting
- transient int expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
+ @VisibleForTesting transient int expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
/**
* Creates a new, empty {@code HashMultimap} with the default initial
@@ -65,8 +64,7 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
* @throws IllegalArgumentException if {@code expectedKeys} or {@code
* expectedValuesPerKey} is negative
*/
- public static <K, V> HashMultimap<K, V> create(
- int expectedKeys, int expectedValuesPerKey) {
+ public static <K, V> HashMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
return new HashMultimap<K, V>(expectedKeys, expectedValuesPerKey);
}
@@ -77,8 +75,7 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
*
* @param multimap the multimap whose contents are copied to this multimap
*/
- public static <K, V> HashMultimap<K, V> create(
- Multimap<? extends K, ? extends V> multimap) {
+ public static <K, V> HashMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
return new HashMultimap<K, V>(multimap);
}
@@ -93,8 +90,7 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
}
private HashMultimap(Multimap<? extends K, ? extends V> multimap) {
- super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(
- multimap.keySet().size()));
+ super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(multimap.keySet().size()));
putAll(multimap);
}
@@ -105,7 +101,8 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
*
* @return a new {@code HashSet} containing a collection of values for one key
*/
- @Override Set<V> createCollection() {
+ @Override
+ Set<V> createCollection() {
return Sets.<V>newHashSetWithExpectedSize(expectedValuesPerKey);
}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultiset.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultiset.java
index 1ee2d8d..02fb070 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultiset.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/HashMultiset.java
@@ -25,7 +25,7 @@ import java.util.HashMap;
*
* @author Kevin Bourrillion
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
public final class HashMultiset<E> extends AbstractMapBasedMultiset<E> {
@@ -51,15 +51,14 @@ public final class HashMultiset<E> extends AbstractMapBasedMultiset<E> {
/**
* Creates a new {@code HashMultiset} containing the specified elements.
- *
+ *
* <p>This implementation is highly efficient when {@code elements} is itself
* a {@link Multiset}.
- *
+ *
* @param elements the elements that the multiset should contain
*/
public static <E> HashMultiset<E> create(Iterable<? extends E> elements) {
- HashMultiset<E> multiset =
- create(Multisets.inferDistinctElements(elements));
+ HashMultiset<E> multiset = create(Multisets.inferDistinctElements(elements));
Iterables.addAll(multiset, elements);
return multiset;
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableAsList.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableAsList.java
index 1279bee..8569c3e 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableAsList.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableAsList.java
@@ -30,7 +30,8 @@ import com.google.common.annotations.GwtCompatible;
abstract class ImmutableAsList<E> extends ImmutableList<E> {
abstract ImmutableCollection<E> delegateCollection();
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// The collection's contains() is at least as fast as ImmutableList's
// and is often faster.
return delegateCollection().contains(target);
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMap.java
index 9ddef1c..518f166 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMap.java
@@ -18,7 +18,9 @@ package com.google.common.collect;
import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
+import java.util.Comparator;
import java.util.Map;
+import java.util.Map.Entry;
/**
* GWT emulation of {@link ImmutableBiMap}.
@@ -31,7 +33,7 @@ public abstract class ImmutableBiMap<K, V> extends ForwardingImmutableMap<K, V>
// Casting to any type is safe because the set will never hold any elements.
@SuppressWarnings("unchecked")
public static <K, V> ImmutableBiMap<K, V> of() {
- return (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE;
+ return (ImmutableBiMap<K, V>) RegularImmutableBiMap.EMPTY;
}
public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) {
@@ -69,15 +71,35 @@ public abstract class ImmutableBiMap<K, V> extends ForwardingImmutableMap<K, V>
public Builder() {}
+ Builder(int initCapacity) {
+ super(initCapacity);
+ }
+
@Override public Builder<K, V> put(K key, V value) {
super.put(key, value);
return this;
}
+ @Override public Builder<K, V> put(Map.Entry<? extends K, ? extends V> entry) {
+ super.put(entry);
+ return this;
+ }
+
@Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
super.putAll(map);
return this;
}
+
+ @Override public Builder<K, V> putAll(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ super.putAll(entries);
+ return this;
+ }
+
+ public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
+ super.orderEntriesByValue(valueComparator);
+ return this;
+ }
@Override public ImmutableBiMap<K, V> build() {
ImmutableMap<K, V> map = super.build();
@@ -103,6 +125,11 @@ public abstract class ImmutableBiMap<K, V> extends ForwardingImmutableMap<K, V>
ImmutableMap<K, V> immutableMap = ImmutableMap.copyOf(map);
return new RegularImmutableBiMap<K, V>(immutableMap);
}
+
+ public static <K, V> ImmutableBiMap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ return new Builder<K, V>().putAll(entries).build();
+ }
ImmutableBiMap(Map<K, V> delegate) {
super(delegate);
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimap.java
index b0cac0c..7f96ca0 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimap.java
@@ -16,6 +16,7 @@
package com.google.common.collect;
+import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import java.util.Collection;
@@ -25,31 +26,18 @@ import java.util.Map.Entry;
import javax.annotation.Nullable;
/**
- * An immutable {@link ListMultimap} with reliable user-specified key and value
- * iteration order. Does not permit null keys or values.
- *
- * <p>Unlike {@link Multimaps#unmodifiableListMultimap(ListMultimap)}, which is
- * a <i>view</i> of a separate multimap which can still change, an instance of
- * {@code ImmutableListMultimap} contains its own data and will <i>never</i>
- * change. {@code ImmutableListMultimap} is convenient for
- * {@code public static final} multimaps ("constant multimaps") and also lets
- * you easily make a "defensive copy" of a multimap provided to your class by
- * a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class
- * are guaranteed to be immutable.
+ * A {@link ListMultimap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
-public class ImmutableListMultimap<K, V>
- extends ImmutableMultimap<K, V>
+public class ImmutableListMultimap<K, V> extends ImmutableMultimap<K, V>
implements ListMultimap<K, V> {
/** Returns the empty multimap. */
@@ -63,8 +51,7 @@ public class ImmutableListMultimap<K, V>
* Returns an immutable multimap containing a single entry.
*/
public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1) {
- ImmutableListMultimap.Builder<K, V> builder
- = ImmutableListMultimap.builder();
+ ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
builder.put(k1, v1);
return builder.build();
}
@@ -73,8 +60,7 @@ public class ImmutableListMultimap<K, V>
* Returns an immutable multimap containing the given entries, in order.
*/
public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1, K k2, V v2) {
- ImmutableListMultimap.Builder<K, V> builder
- = ImmutableListMultimap.builder();
+ ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
builder.put(k1, v1);
builder.put(k2, v2);
return builder.build();
@@ -83,10 +69,8 @@ public class ImmutableListMultimap<K, V>
/**
* Returns an immutable multimap containing the given entries, in order.
*/
- public static <K, V> ImmutableListMultimap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3) {
- ImmutableListMultimap.Builder<K, V> builder
- = ImmutableListMultimap.builder();
+ public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
+ ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
builder.put(k1, v1);
builder.put(k2, v2);
builder.put(k3, v3);
@@ -98,8 +82,7 @@ public class ImmutableListMultimap<K, V>
*/
public static <K, V> ImmutableListMultimap<K, V> of(
K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
- ImmutableListMultimap.Builder<K, V> builder
- = ImmutableListMultimap.builder();
+ ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
builder.put(k1, v1);
builder.put(k2, v2);
builder.put(k3, v3);
@@ -112,8 +95,7 @@ public class ImmutableListMultimap<K, V>
*/
public static <K, V> ImmutableListMultimap<K, V> of(
K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
- ImmutableListMultimap.Builder<K, V> builder
- = ImmutableListMultimap.builder();
+ ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
builder.put(k1, v1);
builder.put(k2, v2);
builder.put(k3, v3);
@@ -148,17 +130,17 @@ public class ImmutableListMultimap<K, V>
* times to build multiple multimaps in series. Each multimap contains the
* key-value mappings in the previously created multimaps.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
- public static final class Builder<K, V>
- extends ImmutableMultimap.Builder<K, V> {
+ public static final class Builder<K, V> extends ImmutableMultimap.Builder<K, V> {
/**
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link ImmutableListMultimap#builder}.
*/
public Builder() {}
- @Override public Builder<K, V> put(K key, V value) {
+ @Override
+ public Builder<K, V> put(K key, V value) {
super.put(key, value);
return this;
}
@@ -168,24 +150,38 @@ public class ImmutableListMultimap<K, V>
*
* @since 11.0
*/
- @Override public Builder<K, V> put(
- Entry<? extends K, ? extends V> entry) {
+ @Override
+ public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
super.put(entry);
return this;
}
- @Override public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
+ /**
+ * {@inheritDoc}
+ *
+ * @since 19.0
+ */
+ @Beta
+ @Override
+ public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ super.putAll(entries);
+ return this;
+ }
+
+ @Override
+ public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
super.putAll(key, values);
return this;
}
- @Override public Builder<K, V> putAll(K key, V... values) {
+ @Override
+ public Builder<K, V> putAll(K key, V... values) {
super.putAll(key, values);
return this;
}
- @Override public Builder<K, V> putAll(
- Multimap<? extends K, ? extends V> multimap) {
+ @Override
+ public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
super.putAll(multimap);
return this;
}
@@ -215,7 +211,8 @@ public class ImmutableListMultimap<K, V>
/**
* Returns a newly-created immutable list multimap.
*/
- @Override public ImmutableListMultimap<K, V> build() {
+ @Override
+ public ImmutableListMultimap<K, V> build() {
return (ImmutableListMultimap<K, V>) super.build();
}
}
@@ -238,21 +235,21 @@ public class ImmutableListMultimap<K, V>
return of();
}
- // TODO(user): copy ImmutableSetMultimap by using asList() on the sets
+ // TODO(lowasser): copy ImmutableSetMultimap by using asList() on the sets
if (multimap instanceof ImmutableListMultimap) {
@SuppressWarnings("unchecked") // safe since multimap is not writable
- ImmutableListMultimap<K, V> kvMultimap
- = (ImmutableListMultimap<K, V>) multimap;
+ ImmutableListMultimap<K, V> kvMultimap = (ImmutableListMultimap<K, V>) multimap;
if (!kvMultimap.isPartialView()) {
return kvMultimap;
}
}
- ImmutableMap.Builder<K, ImmutableList<V>> builder = ImmutableMap.builder();
+ ImmutableMap.Builder<K, ImmutableList<V>> builder =
+ new ImmutableMap.Builder<K, ImmutableList<V>>(multimap.asMap().size());
int size = 0;
- for (Entry<? extends K, ? extends Collection<? extends V>> entry
- : multimap.asMap().entrySet()) {
+ for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+ multimap.asMap().entrySet()) {
ImmutableList<V> list = ImmutableList.copyOf(entry.getValue());
if (!list.isEmpty()) {
builder.put(entry.getKey(), list);
@@ -263,6 +260,21 @@ public class ImmutableListMultimap<K, V>
return new ImmutableListMultimap<K, V>(builder.build(), size);
}
+ /**
+ * Returns an immutable multimap containing the specified entries. The
+ * returned multimap iterates over keys in the order they were first
+ * encountered in the input, and the values for each key are iterated in the
+ * order they were encountered.
+ *
+ * @throws NullPointerException if any key, value, or entry is null
+ * @since 19.0
+ */
+ @Beta
+ public static <K, V> ImmutableListMultimap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ return new Builder<K, V>().putAll(entries).build();
+ }
+
ImmutableListMultimap(ImmutableMap<K, ImmutableList<V>> map, int size) {
super(map, size);
}
@@ -275,7 +287,8 @@ public class ImmutableListMultimap<K, V>
* returned. The values are in the same order as the parameters used to build
* this multimap.
*/
- @Override public ImmutableList<V> get(@Nullable K key) {
+ @Override
+ public ImmutableList<V> get(@Nullable K key) {
// This cast is safe as its type is known in constructor.
ImmutableList<V> list = (ImmutableList<V>) map.get(key);
return (list == null) ? ImmutableList.<V>of() : list;
@@ -315,7 +328,9 @@ public class ImmutableListMultimap<K, V>
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public ImmutableList<V> removeAll(Object key) {
+ @Deprecated
+ @Override
+ public ImmutableList<V> removeAll(Object key) {
throw new UnsupportedOperationException();
}
@@ -325,8 +340,9 @@ public class ImmutableListMultimap<K, V>
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public ImmutableList<V> replaceValues(
- K key, Iterable<? extends V> values) {
+ @Deprecated
+ @Override
+ public ImmutableList<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMap.java
index 679e22f..c4f7cc3 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMap.java
@@ -17,15 +17,19 @@
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
import static com.google.common.collect.Iterables.getOnlyElement;
import java.io.Serializable;
+import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.EnumMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import javax.annotation.Nullable;
@@ -41,7 +45,25 @@ import javax.annotation.Nullable;
* @author Hayward Chan
*/
public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
+ abstract static class IteratorBasedImmutableMap<K, V> extends ImmutableMap<K, V> {
+ abstract UnmodifiableIterator<Entry<K, V>> entryIterator();
+
+ @Override
+ ImmutableSet<Entry<K, V>> createEntrySet() {
+ return new ImmutableMapEntrySet<K, V>() {
+ @Override
+ ImmutableMap<K, V> map() {
+ return IteratorBasedImmutableMap.this;
+ }
+ @Override
+ public UnmodifiableIterator<Entry<K, V>> iterator() {
+ return entryIterator();
+ }
+ };
+ }
+ }
+
ImmutableMap() {}
public static <K, V> ImmutableMap<K, V> of() {
@@ -86,9 +108,16 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
}
public static class Builder<K, V> {
- final List<Entry<K, V>> entries = Lists.newArrayList();
+ final List<Entry<K, V>> entries;
+ Comparator<? super V> valueComparator;
- public Builder() {}
+ public Builder() {
+ this.entries = Lists.newArrayList();
+ }
+
+ Builder(int initCapacity) {
+ this.entries = Lists.newArrayListWithCapacity(initCapacity);
+ }
public Builder<K, V> put(K key, V value) {
entries.add(entryOf(key, value));
@@ -109,31 +138,46 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
}
public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
- for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
- put(entry.getKey(), entry.getValue());
+ return putAll(map.entrySet());
+ }
+
+ public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ for (Entry<? extends K, ? extends V> entry : entries) {
+ put(entry);
}
return this;
}
+
+ public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
+ checkState(this.valueComparator == null, "valueComparator was already set");
+ this.valueComparator = checkNotNull(valueComparator, "valueComparator");
+ return this;
+ }
public ImmutableMap<K, V> build() {
+ if (valueComparator != null) {
+ Collections.sort(
+ entries,
+ Ordering.from(valueComparator).onResultOf(Maps.<V>valueFunction()));
+ }
return fromEntryList(entries);
}
+ }
- private static <K, V> ImmutableMap<K, V> fromEntryList(
- List<Entry<K, V>> entries) {
- int size = entries.size();
- switch (size) {
- case 0:
- return of();
- case 1:
- Entry<K, V> entry = getOnlyElement(entries);
- return of(entry.getKey(), entry.getValue());
- default:
- @SuppressWarnings("unchecked")
- Entry<K, V>[] entryArray
- = entries.toArray(new Entry[entries.size()]);
- return new RegularImmutableMap<K, V>(entryArray);
- }
+ static <K, V> ImmutableMap<K, V> fromEntryList(
+ Collection<? extends Entry<? extends K, ? extends V>> entries) {
+ int size = entries.size();
+ switch (size) {
+ case 0:
+ return of();
+ case 1:
+ Entry<? extends K, ? extends V> entry = getOnlyElement(entries);
+ return of((K) entry.getKey(), (V) entry.getValue());
+ default:
+ @SuppressWarnings("unchecked")
+ Entry<K, V>[] entryArray
+ = entries.toArray(new Entry[entries.size()]);
+ return new RegularImmutableMap<K, V>(entryArray);
}
}
@@ -172,6 +216,16 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
return new RegularImmutableMap<K, V>(orderPreservingCopy);
}
}
+
+ public static <K, V> ImmutableMap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ if (entries instanceof Collection) {
+ return fromEntryList(
+ (Collection<? extends Entry<? extends K, ? extends V>>) entries);
+ } else {
+ return fromEntryList(Lists.newArrayList(entries.iterator()));
+ }
+ }
abstract boolean isPartialView();
@@ -229,6 +283,19 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
ImmutableSet<K> createKeySet() {
return new ImmutableMapKeySet<K, V>(this);
}
+
+ UnmodifiableIterator<K> keyIterator() {
+ final UnmodifiableIterator<Entry<K, V>> entryIterator = entrySet().iterator();
+ return new UnmodifiableIterator<K>() {
+ @Override public boolean hasNext() {
+ return entryIterator.hasNext();
+ }
+
+ @Override public K next() {
+ return entryIterator.next().getKey();
+ }
+ };
+ }
private transient ImmutableCollection<V> cachedValues = null;
@@ -239,82 +306,68 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
return cachedValues = createValues();
}
- // esnickell is editing here
-
// cached so that this.multimapView().inverse() only computes inverse once
private transient ImmutableSetMultimap<K, V> multimapView;
public ImmutableSetMultimap<K, V> asMultimap() {
ImmutableSetMultimap<K, V> result = multimapView;
- return (result == null) ? (multimapView = createMultimapView()) : result;
+ return (result == null)
+ ? (multimapView = new ImmutableSetMultimap<K, V>(
+ new MapViewOfValuesAsSingletonSets(), size(), null))
+ : result;
}
+
+ final class MapViewOfValuesAsSingletonSets
+ extends IteratorBasedImmutableMap<K, ImmutableSet<V>> {
- private ImmutableSetMultimap<K, V> createMultimapView() {
- ImmutableMap<K, ImmutableSet<V>> map = viewValuesAsImmutableSet();
- return new ImmutableSetMultimap<K, V>(map, map.size(), null);
- }
+ @Override public int size() {
+ return ImmutableMap.this.size();
+ }
+
+ @Override public ImmutableSet<K> keySet() {
+ return ImmutableMap.this.keySet();
+ }
- private ImmutableMap<K, ImmutableSet<V>> viewValuesAsImmutableSet() {
- final Map<K, V> outer = this;
- return new ImmutableMap<K, ImmutableSet<V>>() {
- @Override
- public int size() {
- return outer.size();
- }
+ @Override public boolean containsKey(@Nullable Object key) {
+ return ImmutableMap.this.containsKey(key);
+ }
- @Override
- public ImmutableSet<V> get(@Nullable Object key) {
- V outerValue = outer.get(key);
- return outerValue == null ? null : ImmutableSet.of(outerValue);
- }
+ @Override public ImmutableSet<V> get(@Nullable Object key) {
+ V outerValue = ImmutableMap.this.get(key);
+ return (outerValue == null) ? null : ImmutableSet.of(outerValue);
+ }
- @Override
- ImmutableSet<Entry<K, ImmutableSet<V>>> createEntrySet() {
- return new ImmutableSet<Entry<K, ImmutableSet<V>>>() {
- @Override
- public UnmodifiableIterator<Entry<K, ImmutableSet<V>>> iterator() {
- final Iterator<Entry<K,V>> outerEntryIterator = outer.entrySet().iterator();
- return new UnmodifiableIterator<Entry<K, ImmutableSet<V>>>() {
- @Override
- public boolean hasNext() {
- return outerEntryIterator.hasNext();
- }
-
- @Override
- public Entry<K, ImmutableSet<V>> next() {
- final Entry<K, V> outerEntry = outerEntryIterator.next();
- return new AbstractMapEntry<K, ImmutableSet<V>>() {
- @Override
- public K getKey() {
- return outerEntry.getKey();
- }
-
- @Override
- public ImmutableSet<V> getValue() {
- return ImmutableSet.of(outerEntry.getValue());
- }
- };
- }
- };
- }
-
- @Override
- boolean isPartialView() {
- return false;
- }
-
- @Override
- public int size() {
- return outer.size();
- }
- };
- }
+ @Override boolean isPartialView() {
+ return ImmutableMap.this.isPartialView();
+ }
- @Override
- boolean isPartialView() {
- return false;
- }
- };
+ @Override public int hashCode() {
+ // ImmutableSet.of(value).hashCode() == value.hashCode(), so the hashes are the same
+ return ImmutableMap.this.hashCode();
+ }
+
+ @Override
+ UnmodifiableIterator<Entry<K, ImmutableSet<V>>> entryIterator() {
+ final Iterator<Entry<K, V>> backingIterator = ImmutableMap.this.entrySet().iterator();
+ return new UnmodifiableIterator<Entry<K, ImmutableSet<V>>>() {
+ @Override public boolean hasNext() {
+ return backingIterator.hasNext();
+ }
+
+ @Override public Entry<K, ImmutableSet<V>> next() {
+ final Entry<K, V> backingEntry = backingIterator.next();
+ return new AbstractMapEntry<K, ImmutableSet<V>>() {
+ @Override public K getKey() {
+ return backingEntry.getKey();
+ }
+
+ @Override public ImmutableSet<V> getValue() {
+ return ImmutableSet.of(backingEntry.getValue());
+ }
+ };
+ }
+ };
+ }
}
ImmutableCollection<V> createValues() {
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapEntrySet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapEntrySet.java
index 7a5e580..4fd69b5 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapEntrySet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapEntrySet.java
@@ -17,6 +17,7 @@
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.Weak;
import java.util.Map.Entry;
@@ -30,6 +31,31 @@ import javax.annotation.Nullable;
*/
@GwtCompatible(emulated = true)
abstract class ImmutableMapEntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
+ static final class RegularEntrySet<K, V> extends ImmutableMapEntrySet<K, V> {
+ @Weak private final transient ImmutableMap<K, V> map;
+ private final transient Entry<K, V>[] entries;
+
+ RegularEntrySet(ImmutableMap<K, V> map, Entry<K, V>[] entries) {
+ this.map = map;
+ this.entries = entries;
+ }
+
+ @Override
+ ImmutableMap<K, V> map() {
+ return map;
+ }
+
+ @Override
+ public UnmodifiableIterator<Entry<K, V>> iterator() {
+ return asList().iterator();
+ }
+
+ @Override
+ ImmutableList<Entry<K, V>> createAsList() {
+ return new RegularImmutableAsList<Entry<K, V>>(this, entries);
+ }
+ }
+
ImmutableMapEntrySet() {}
abstract ImmutableMap<K, V> map();
@@ -53,5 +79,10 @@ abstract class ImmutableMapEntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
boolean isPartialView() {
return map().isPartialView();
}
+
+ @Override
+ public int hashCode() {
+ return map().hashCode();
+ }
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapKeySet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapKeySet.java
index 78508f4..2469a60 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapKeySet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapKeySet.java
@@ -17,8 +17,7 @@
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
-
-import java.util.Map.Entry;
+import com.google.j2objc.annotations.Weak;
import javax.annotation.Nullable;
@@ -29,8 +28,8 @@ import javax.annotation.Nullable;
* @author Kevin Bourrillion
*/
@GwtCompatible(emulated = true)
-final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
- private final ImmutableMap<K, V> map;
+final class ImmutableMapKeySet<K, V> extends ImmutableSet.Indexed<K> {
+ @Weak private final ImmutableMap<K, V> map;
ImmutableMapKeySet(ImmutableMap<K, V> map) {
this.map = map;
@@ -43,7 +42,7 @@ final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
@Override
public UnmodifiableIterator<K> iterator() {
- return asList().iterator();
+ return map.keyIterator();
}
@Override
@@ -52,21 +51,8 @@ final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
}
@Override
- ImmutableList<K> createAsList() {
- final ImmutableList<Entry<K, V>> entryList = map.entrySet().asList();
- return new ImmutableAsList<K>() {
-
- @Override
- public K get(int index) {
- return entryList.get(index).getKey();
- }
-
- @Override
- ImmutableCollection<K> delegateCollection() {
- return ImmutableMapKeySet.this;
- }
-
- };
+ K get(int index) {
+ return map.entrySet().asList().get(index).getKey();
}
@Override
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapValues.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapValues.java
index ec6a40f..4ba2644 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapValues.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapValues.java
@@ -17,6 +17,7 @@
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.Weak;
import java.util.Map.Entry;
@@ -30,8 +31,8 @@ import javax.annotation.Nullable;
*/
@GwtCompatible(emulated = true)
final class ImmutableMapValues<K, V> extends ImmutableCollection<V> {
- private final ImmutableMap<K, V> map;
-
+ @Weak private final ImmutableMap<K, V> map;
+
ImmutableMapValues(ImmutableMap<K, V> map) {
this.map = map;
}
@@ -43,7 +44,19 @@ final class ImmutableMapValues<K, V> extends ImmutableCollection<V> {
@Override
public UnmodifiableIterator<V> iterator() {
- return Maps.valueIterator(map.entrySet().iterator());
+ return new UnmodifiableIterator<V>() {
+ final UnmodifiableIterator<Entry<K, V>> entryItr = map.entrySet().iterator();
+
+ @Override
+ public boolean hasNext() {
+ return entryItr.hasNext();
+ }
+
+ @Override
+ public V next() {
+ return entryItr.next().getValue();
+ }
+ };
}
@Override
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimap.java
index 236c75b..985ffe9 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimap.java
@@ -19,7 +19,10 @@ package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
+import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.Arrays;
@@ -27,7 +30,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -36,29 +38,30 @@ import java.util.Set;
import javax.annotation.Nullable;
/**
- * An immutable {@link Multimap}. Does not permit null keys or values.
+ * A {@link Multimap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
- * <p>Unlike {@link Multimaps#unmodifiableMultimap(Multimap)}, which is
- * a <i>view</i> of a separate multimap which can still change, an instance of
- * {@code ImmutableMultimap} contains its own data and will <i>never</i>
- * change. {@code ImmutableMultimap} is convenient for
- * {@code public static final} multimaps ("constant multimaps") and also lets
- * you easily make a "defensive copy" of a multimap provided to your class by
- * a caller.
+ * <p><b>Warning:</b> avoid <i>direct</i> usage of {@link ImmutableMultimap} as a type (as with
+ * {@link Multimap} itself). Prefer subtypes such as {@link ImmutableSetMultimap} or {@link
+ * ImmutableListMultimap}, which have well-defined {@link #equals} semantics, thus avoiding a common
+ * source of bugs and confusion.
*
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class
- * are guaranteed to be immutable.
+ * <p><b>Note:</b> every {@link ImmutableMultimap} offers an {@link #inverse} view, so there is no
+ * need for a distinct {@code ImmutableBiMultimap} type.
*
- * <p>In addition to methods defined by {@link Multimap}, an {@link #inverse}
- * method is also supported.
+ * <a name="iteration"></a>
+ * <p><b>Key-grouped iteration.</b> All view collections follow the same iteration order. In all
+ * current implementations, the iteration order always keeps multiple entries with the same key
+ * together. Any creation method that would customarily respect insertion order (such as {@link
+ * #copyOf(Multimap)}) instead preserves key-grouped order by inserting entries for an existing key
+ * immediately after the last entry having that key.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
@@ -84,23 +87,27 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
}
/**
- * Returns an immutable multimap containing the given entries, in order.
+ * Returns an immutable multimap containing the given entries, in the
+ * "key-grouped" insertion order described in the
+ * <a href="#iteration">class documentation</a>.
*/
- public static <K, V> ImmutableMultimap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3) {
+ public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3);
}
/**
- * Returns an immutable multimap containing the given entries, in order.
+ * Returns an immutable multimap containing the given entries, in the
+ * "key-grouped" insertion order described in the
+ * <a href="#iteration">class documentation</a>.
*/
- public static <K, V> ImmutableMultimap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+ public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4);
}
/**
- * Returns an immutable multimap containing the given entries, in order.
+ * Returns an immutable multimap containing the given entries, in the
+ * "key-grouped" insertion order described in the
+ * <a href="#iteration">class documentation</a>.
*/
public static <K, V> ImmutableMultimap<K, V> of(
K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
@@ -118,21 +125,6 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
}
/**
- * Multimap for {@link ImmutableMultimap.Builder} that maintains key and
- * value orderings, allows duplicate values, and performs better than
- * {@link LinkedListMultimap}.
- */
- private static class BuilderMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
- BuilderMultimap() {
- super(new LinkedHashMap<K, Collection<V>>());
- }
- @Override Collection<V> createCollection() {
- return Lists.newArrayList();
- }
- private static final long serialVersionUID = 0;
- }
-
- /**
* A builder for creating immutable multimap instances, especially
* {@code public static final} multimaps ("constant multimaps"). Example:
* <pre> {@code
@@ -148,10 +140,10 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
* times to build multiple multimaps in series. Each multimap contains the
* key-value mappings in the previously created multimaps.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public static class Builder<K, V> {
- Multimap<K, V> builderMultimap = new BuilderMultimap<K, V>();
+ Multimap<K, V> builderMultimap;
Comparator<? super K> keyComparator;
Comparator<? super V> valueComparator;
@@ -159,7 +151,13 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link ImmutableMultimap#builder}.
*/
- public Builder() {}
+ public Builder() {
+ this(MultimapBuilder.linkedHashKeys().arrayListValues().<K, V>build());
+ }
+
+ Builder(Multimap<K, V> builderMultimap) {
+ this.builderMultimap = builderMultimap;
+ }
/**
* Adds a key-value mapping to the built multimap.
@@ -180,6 +178,19 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
}
/**
+ * Adds entries to the built multimap.
+ *
+ * @since 19.0
+ */
+ @Beta
+ public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ for (Entry<? extends K, ? extends V> entry : entries) {
+ put(entry);
+ }
+ return this;
+ }
+
+ /**
* Stores a collection of values with the same key in the built multimap.
*
* @throws NullPointerException if {@code key}, {@code values}, or any
@@ -188,8 +199,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
*/
public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
if (key == null) {
- throw new NullPointerException(
- "null key in entry: null=" + Iterables.toString(values));
+ throw new NullPointerException("null key in entry: null=" + Iterables.toString(values));
}
Collection<V> valueList = builderMultimap.get(key);
for (V value : values) {
@@ -219,8 +229,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
* null. The builder is left in an invalid state.
*/
public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
- for (Entry<? extends K, ? extends Collection<? extends V>> entry
- : multimap.asMap().entrySet()) {
+ for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+ multimap.asMap().entrySet()) {
putAll(entry.getKey(), entry.getValue());
}
return this;
@@ -252,17 +262,17 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
public ImmutableMultimap<K, V> build() {
if (valueComparator != null) {
for (Collection<V> values : builderMultimap.asMap().values()) {
- List<V> list = (List <V>) values;
+ List<V> list = (List<V>) values;
Collections.sort(list, valueComparator);
}
}
if (keyComparator != null) {
- Multimap<K, V> sortedCopy = new BuilderMultimap<K, V>();
- List<Map.Entry<K, Collection<V>>> entries = Lists.newArrayList(
- builderMultimap.asMap().entrySet());
- Collections.sort(
- entries,
- Ordering.from(keyComparator).<K>onKeys());
+ Multimap<K, V> sortedCopy =
+ MultimapBuilder.linkedHashKeys().arrayListValues().<K, V>build();
+ List<Map.Entry<K, Collection<V>>> entries =
+ Ordering.from(keyComparator)
+ .<K>onKeys()
+ .immutableSortedCopy(builderMultimap.asMap().entrySet());
for (Map.Entry<K, Collection<V>> entry : entries) {
sortedCopy.putAll(entry.getKey(), entry.getValue());
}
@@ -274,8 +284,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
/**
* Returns an immutable multimap containing the same mappings as {@code
- * multimap}. The generated multimap's key and value orderings correspond to
- * the iteration ordering of the {@code multimap.asMap()} view.
+ * multimap}, in the "key-grouped" iteration order described in the class
+ * documentation.
*
* <p>Despite the method name, this method attempts to avoid actually copying
* the data when it is safe to do so. The exact circumstances under which a
@@ -284,12 +294,10 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
* @throws NullPointerException if any key or value in {@code multimap} is
* null
*/
- public static <K, V> ImmutableMultimap<K, V> copyOf(
- Multimap<? extends K, ? extends V> multimap) {
+ public static <K, V> ImmutableMultimap<K, V> copyOf(Multimap<? extends K, ? extends V> multimap) {
if (multimap instanceof ImmutableMultimap) {
@SuppressWarnings("unchecked") // safe since multimap is not writable
- ImmutableMultimap<K, V> kvMultimap
- = (ImmutableMultimap<K, V>) multimap;
+ ImmutableMultimap<K, V> kvMultimap = (ImmutableMultimap<K, V>) multimap;
if (!kvMultimap.isPartialView()) {
return kvMultimap;
}
@@ -297,6 +305,21 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
return ImmutableListMultimap.copyOf(multimap);
}
+ /**
+ * Returns an immutable multimap containing the specified entries. The
+ * returned multimap iterates over keys in the order they were first
+ * encountered in the input, and the values for each key are iterated in the
+ * order they were encountered.
+ *
+ * @throws NullPointerException if any key, value, or entry is null
+ * @since 19.0
+ */
+ @Beta
+ public static <K, V> ImmutableMultimap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ return ImmutableListMultimap.copyOf(entries);
+ }
+
final transient ImmutableMap<K, ? extends ImmutableCollection<V>> map;
final transient int size;
@@ -304,8 +327,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
// holder class makes sure they are not initialized unless an instance is
// deserialized.
- ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map,
- int size) {
+ ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map, int size) {
this.map = map;
this.size = size;
}
@@ -332,8 +354,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
*/
@Deprecated
@Override
- public ImmutableCollection<V> replaceValues(K key,
- Iterable<? extends V> values) {
+ public ImmutableCollection<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
@@ -414,7 +435,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
}
-
+
/**
* Returns {@code true} if this immutable multimap's implementation contains references to
* user-created objects that aren't accessible via this multimap's methods. This is generally
@@ -436,7 +457,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
public boolean containsValue(@Nullable Object value) {
return value != null && super.containsValue(value);
}
-
+
@Override
public int size() {
return size;
@@ -445,9 +466,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
// views
/**
- * Returns an immutable set of the distinct keys in this multimap. These keys
- * are ordered according to when they first appeared during the construction
- * of this multimap.
+ * Returns an immutable set of the distinct keys in this multimap, in the same
+ * order as they appear in this multimap.
*/
@Override
public ImmutableSet<K> keySet() {
@@ -456,47 +476,47 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
/**
* Returns an immutable map that associates each key with its corresponding
- * values in the multimap.
+ * values in the multimap. Keys and values appear in the same order as in this
+ * multimap.
*/
@Override
@SuppressWarnings("unchecked") // a widening cast
public ImmutableMap<K, Collection<V>> asMap() {
return (ImmutableMap) map;
}
-
+
@Override
Map<K, Collection<V>> createAsMap() {
throw new AssertionError("should never be called");
}
/**
- * Returns an immutable collection of all key-value pairs in the multimap. Its
- * iterator traverses the values for the first key, the values for the second
- * key, and so on.
+ * Returns an immutable collection of all key-value pairs in the multimap.
*/
@Override
public ImmutableCollection<Entry<K, V>> entries() {
return (ImmutableCollection<Entry<K, V>>) super.entries();
}
-
+
@Override
ImmutableCollection<Entry<K, V>> createEntries() {
return new EntryCollection<K, V>(this);
}
- private static class EntryCollection<K, V>
- extends ImmutableCollection<Entry<K, V>> {
- final ImmutableMultimap<K, V> multimap;
+ private static class EntryCollection<K, V> extends ImmutableCollection<Entry<K, V>> {
+ @Weak final ImmutableMultimap<K, V> multimap;
EntryCollection(ImmutableMultimap<K, V> multimap) {
this.multimap = multimap;
}
- @Override public UnmodifiableIterator<Entry<K, V>> iterator() {
+ @Override
+ public UnmodifiableIterator<Entry<K, V>> iterator() {
return multimap.entryIterator();
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return multimap.isPartialView();
}
@@ -505,7 +525,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
return multimap.size();
}
- @Override public boolean contains(Object object) {
+ @Override
+ public boolean contains(Object object) {
if (object instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) object;
return multimap.containsEntry(entry.getKey(), entry.getValue());
@@ -515,12 +536,12 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
private static final long serialVersionUID = 0;
}
-
+
private abstract class Itr<T> extends UnmodifiableIterator<T> {
final Iterator<Entry<K, Collection<V>>> mapIterator = asMap().entrySet().iterator();
K key = null;
Iterator<V> valueIterator = Iterators.emptyIterator();
-
+
abstract T output(K key, V value);
@Override
@@ -538,7 +559,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
return output(key, valueIterator.next());
}
}
-
+
@Override
UnmodifiableIterator<Entry<K, V>> entryIterator() {
return new Itr<Entry<K, V>>() {
@@ -550,10 +571,9 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
}
/**
- * Returns a collection, which may contain duplicates, of all keys. The number
- * of times a key appears in the returned multiset equals the number of
- * mappings the key has in the multimap. Duplicate keys appear consecutively
- * in the multiset's iteration order.
+ * Returns an immutable multiset containing all the keys in this multimap, in
+ * the same order and with the same frequencies as they appear in this
+ * multimap; to get only a single occurrence of each key, use {@link #keySet}.
*/
@Override
public ImmutableMultiset<K> keys() {
@@ -566,6 +586,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
}
@SuppressWarnings("serial") // Uses writeReplace, not default serialization
+ @WeakOuter
class Keys extends ImmutableMultiset<K> {
@Override
public boolean contains(@Nullable Object object) {
@@ -587,7 +608,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
public int size() {
return ImmutableMultimap.this.size();
}
-
+
@Override
Multiset.Entry<K> getEntry(int index) {
Map.Entry<K, ? extends Collection<V>> entry = map.entrySet().asList().get(index);
@@ -609,7 +630,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
public ImmutableCollection<V> values() {
return (ImmutableCollection<V>) super.values();
}
-
+
@Override
ImmutableCollection<V> createValues() {
return new Values<K, V>(this);
@@ -626,8 +647,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
}
private static final class Values<K, V> extends ImmutableCollection<V> {
- private transient final ImmutableMultimap<K, V> multimap;
-
+ @Weak private final transient ImmutableMultimap<K, V> multimap;
+
Values(ImmutableMultimap<K, V> multimap) {
this.multimap = multimap;
}
@@ -636,8 +657,9 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
public boolean contains(@Nullable Object object) {
return multimap.containsValue(object);
}
-
- @Override public UnmodifiableIterator<V> iterator() {
+
+ @Override
+ public UnmodifiableIterator<V> iterator() {
return multimap.valueIterator();
}
@@ -646,7 +668,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
return multimap.size();
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return true;
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultiset.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultiset.java
index ead2ba0..b75259b 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultiset.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultiset.java
@@ -20,46 +20,41 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Multiset.Entry;
-import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
-import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import javax.annotation.Nullable;
/**
- * An immutable hash-based multiset. Does not permit null elements.
+ * A {@link Multiset} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
- * <p>Its iterator orders elements according to the first appearance of the
- * element among the items passed to the factory method or builder. When the
- * multiset contains multiple instances of an element, those instances are
- * consecutive in the iteration order.
+ * <p><b>Grouped iteration.</b> In all current implementations, duplicate elements always appear
+ * consecutively when iterating. Elements iterate in order by the <i>first</i> appearance of
+ * that element when the multiset was created.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Jared Levy
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
-// TODO(user): write an efficient asList() implementation
-public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
- implements Multiset<E> {
-
- private static final ImmutableMultiset<Object> EMPTY =
- new RegularImmutableMultiset<Object>(ImmutableMap.<Object, Integer>of(), 0);
-
+// TODO(lowasser): write an efficient asList() implementation
+public abstract class ImmutableMultiset<E> extends ImmutableCollection<E> implements Multiset<E> {
/**
* Returns the empty immutable multiset.
*/
@SuppressWarnings("unchecked") // all supported methods are covariant
public static <E> ImmutableMultiset<E> of() {
- return (ImmutableMultiset<E>) EMPTY;
+ return (ImmutableMultiset<E>) RegularImmutableMultiset.EMPTY;
}
/**
@@ -70,7 +65,7 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
*/
@SuppressWarnings("unchecked") // generic array created but never written
public static <E> ImmutableMultiset<E> of(E element) {
- return copyOfInternal(element);
+ return copyFromElements(element);
}
/**
@@ -81,51 +76,54 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
*/
@SuppressWarnings("unchecked") //
public static <E> ImmutableMultiset<E> of(E e1, E e2) {
- return copyOfInternal(e1, e2);
+ return copyFromElements(e1, e2);
}
/**
- * Returns an immutable multiset containing the given elements, in order.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any element is null
* @since 6.0 (source-compatible since 2.0)
*/
@SuppressWarnings("unchecked") //
public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3) {
- return copyOfInternal(e1, e2, e3);
+ return copyFromElements(e1, e2, e3);
}
/**
- * Returns an immutable multiset containing the given elements, in order.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any element is null
* @since 6.0 (source-compatible since 2.0)
*/
@SuppressWarnings("unchecked") //
public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4) {
- return copyOfInternal(e1, e2, e3, e4);
+ return copyFromElements(e1, e2, e3, e4);
}
/**
- * Returns an immutable multiset containing the given elements, in order.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any element is null
* @since 6.0 (source-compatible since 2.0)
*/
@SuppressWarnings("unchecked") //
public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4, E e5) {
- return copyOfInternal(e1, e2, e3, e4, e5);
+ return copyFromElements(e1, e2, e3, e4, e5);
}
/**
- * Returns an immutable multiset containing the given elements, in order.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any element is null
* @since 6.0 (source-compatible since 2.0)
*/
@SuppressWarnings("unchecked") //
- public static <E> ImmutableMultiset<E> of(
- E e1, E e2, E e3, E e4, E e5, E e6, E... others) {
+ public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) {
return new Builder<E>()
.add(e1)
.add(e2)
@@ -138,38 +136,23 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
}
/**
- * Returns an immutable multiset containing the given elements.
- *
- * <p>The multiset is ordered by the first occurrence of each element. For
- * example, {@code ImmutableMultiset.copyOf([2, 3, 1, 3])} yields a multiset
- * with elements in the order {@code 2, 3, 3, 1}.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any of {@code elements} is null
* @since 6.0
*/
public static <E> ImmutableMultiset<E> copyOf(E[] elements) {
- return copyOf(Arrays.asList(elements));
+ return copyFromElements(elements);
}
/**
- * Returns an immutable multiset containing the given elements.
- *
- * <p>The multiset is ordered by the first occurrence of each element. For
- * example, {@code ImmutableMultiset.copyOf(Arrays.asList(2, 3, 1, 3))} yields
- * a multiset with elements in the order {@code 2, 3, 3, 1}.
- *
- * <p>Despite the method name, this method attempts to avoid actually copying
- * the data when it is safe to do so. The exact circumstances under which a
- * copy will or will not be performed are undocumented and subject to change.
- *
- * <p><b>Note:</b> Despite what the method name suggests, if {@code elements}
- * is an {@code ImmutableMultiset}, no copy will actually be performed, and
- * the given multiset itself will be returned.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any of {@code elements} is null
*/
- public static <E> ImmutableMultiset<E> copyOf(
- Iterable<? extends E> elements) {
+ public static <E> ImmutableMultiset<E> copyOf(Iterable<? extends E> elements) {
if (elements instanceof ImmutableMultiset) {
@SuppressWarnings("unchecked") // all supported methods are covariant
ImmutableMultiset<E> result = (ImmutableMultiset<E>) elements;
@@ -178,63 +161,45 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
}
}
- Multiset<? extends E> multiset = (elements instanceof Multiset)
- ? Multisets.cast(elements)
- : LinkedHashMultiset.create(elements);
+ Multiset<? extends E> multiset =
+ (elements instanceof Multiset)
+ ? Multisets.cast(elements)
+ : LinkedHashMultiset.create(elements);
- return copyOfInternal(multiset);
- }
-
- private static <E> ImmutableMultiset<E> copyOfInternal(E... elements) {
- return copyOf(Arrays.asList(elements));
+ return copyFromEntries(multiset.entrySet());
}
- private static <E> ImmutableMultiset<E> copyOfInternal(
- Multiset<? extends E> multiset) {
+ private static <E> ImmutableMultiset<E> copyFromElements(E... elements) {
+ Multiset<E> multiset = LinkedHashMultiset.create();
+ Collections.addAll(multiset, elements);
return copyFromEntries(multiset.entrySet());
}
static <E> ImmutableMultiset<E> copyFromEntries(
Collection<? extends Entry<? extends E>> entries) {
- long size = 0;
- ImmutableMap.Builder<E, Integer> builder = ImmutableMap.builder();
- for (Entry<? extends E> entry : entries) {
- int count = entry.getCount();
- if (count > 0) {
- // Since ImmutableMap.Builder throws an NPE if an element is null, no
- // other null checks are needed.
- builder.put(entry.getElement(), count);
- size += count;
- }
- }
-
- if (size == 0) {
+ if (entries.isEmpty()) {
return of();
+ } else {
+ return new RegularImmutableMultiset<E>(entries);
}
- return new RegularImmutableMultiset<E>(
- builder.build(), Ints.saturatedCast(size));
}
/**
- * Returns an immutable multiset containing the given elements.
- *
- * <p>The multiset is ordered by the first occurrence of each element. For
- * example,
- * {@code ImmutableMultiset.copyOf(Arrays.asList(2, 3, 1, 3).iterator())}
- * yields a multiset with elements in the order {@code 2, 3, 3, 1}.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any of {@code elements} is null
*/
- public static <E> ImmutableMultiset<E> copyOf(
- Iterator<? extends E> elements) {
+ public static <E> ImmutableMultiset<E> copyOf(Iterator<? extends E> elements) {
Multiset<E> multiset = LinkedHashMultiset.create();
Iterators.addAll(multiset, elements);
- return copyOfInternal(multiset);
+ return copyFromEntries(multiset.entrySet());
}
ImmutableMultiset() {}
- @Override public UnmodifiableIterator<E> iterator() {
+ @Override
+ public UnmodifiableIterator<E> iterator() {
final Iterator<Entry<E>> entryIterator = entrySet().iterator();
return new UnmodifiableIterator<E>() {
int remaining;
@@ -263,11 +228,6 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
return count(object) > 0;
}
- @Override
- public boolean containsAll(Collection<?> targets) {
- return elementSet().containsAll(targets);
- }
-
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
@@ -316,15 +276,18 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
throw new UnsupportedOperationException();
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return Multisets.equalsImpl(this, object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Sets.hashCodeImpl(entrySet());
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return entrySet().toString();
}
@@ -342,30 +305,16 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
abstract Entry<E> getEntry(int index);
- private final class EntrySet extends ImmutableSet<Entry<E>> {
+ @WeakOuter
+ private final class EntrySet extends ImmutableSet.Indexed<Entry<E>> {
@Override
boolean isPartialView() {
return ImmutableMultiset.this.isPartialView();
}
@Override
- public UnmodifiableIterator<Entry<E>> iterator() {
- return asList().iterator();
- }
-
- @Override
- ImmutableList<Entry<E>> createAsList() {
- return new ImmutableAsList<Entry<E>>() {
- @Override
- public Entry<E> get(int index) {
- return getEntry(index);
- }
-
- @Override
- ImmutableCollection<Entry<E>> delegateCollection() {
- return EntrySet.this;
- }
- };
+ Entry<E> get(int index) {
+ return getEntry(index);
}
@Override
@@ -430,8 +379,7 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
}
Object readResolve() {
- LinkedHashMultiset<Object> multiset =
- LinkedHashMultiset.create(elements.length);
+ LinkedHashMultiset<Object> multiset = LinkedHashMultiset.create(elements.length);
for (int i = 0; i < elements.length; i++) {
multiset.add(elements[i], counts[i]);
}
@@ -471,7 +419,7 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
* <p>Builder instances can be reused; it is safe to call {@link #build} multiple
* times to build multiple multisets in series.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public static class Builder<E> extends ImmutableCollection.Builder<E> {
final Multiset<E> contents;
@@ -495,7 +443,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
* @return this {@code Builder} object
* @throws NullPointerException if {@code element} is null
*/
- @Override public Builder<E> add(E element) {
+ @Override
+ public Builder<E> add(E element) {
contents.add(checkNotNull(element));
return this;
}
@@ -541,7 +490,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
- @Override public Builder<E> add(E... elements) {
+ @Override
+ public Builder<E> add(E... elements) {
super.add(elements);
return this;
}
@@ -555,7 +505,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
- @Override public Builder<E> addAll(Iterable<? extends E> elements) {
+ @Override
+ public Builder<E> addAll(Iterable<? extends E> elements) {
if (elements instanceof Multiset) {
Multiset<? extends E> multiset = Multisets.cast(elements);
for (Entry<? extends E> entry : multiset.entrySet()) {
@@ -575,7 +526,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
- @Override public Builder<E> addAll(Iterator<? extends E> elements) {
+ @Override
+ public Builder<E> addAll(Iterator<? extends E> elements) {
super.addAll(elements);
return this;
}
@@ -584,7 +536,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
* Returns a newly-created {@code ImmutableMultiset} based on the contents
* of the {@code Builder}.
*/
- @Override public ImmutableMultiset<E> build() {
+ @Override
+ public ImmutableMultiset<E> build() {
return copyOf(contents);
}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSet.java
index 7c0bae7..7918a24 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSet.java
@@ -43,7 +43,7 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements
// Casting to any type is safe because the set will never hold any elements.
@SuppressWarnings({"unchecked"})
public static <E> ImmutableSet<E> of() {
- return (ImmutableSet<E>) EmptyImmutableSet.INSTANCE;
+ return (ImmutableSet<E>) RegularImmutableSet.EMPTY;
}
public static <E> ImmutableSet<E> of(E element) {
@@ -162,6 +162,30 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements
@Override public int hashCode() {
return Sets.hashCodeImpl(this);
}
+
+ abstract static class Indexed<E> extends ImmutableSet<E> {
+ abstract E get(int index);
+
+ @Override
+ public UnmodifiableIterator<E> iterator() {
+ return asList().iterator();
+ }
+
+ @Override
+ ImmutableList<E> createAsList() {
+ return new ImmutableAsList<E>() {
+ @Override
+ public E get(int index) {
+ return Indexed.this.get(index);
+ }
+
+ @Override
+ Indexed<E> delegateCollection() {
+ return Indexed.this;
+ }
+ };
+ }
+ }
public static <E> Builder<E> builder() {
return new Builder<E>();
@@ -169,9 +193,15 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements
public static class Builder<E> extends ImmutableCollection.Builder<E> {
// accessed directly by ImmutableSortedSet
- final ArrayList<E> contents = Lists.newArrayList();
+ final ArrayList<E> contents;
- public Builder() {}
+ public Builder() {
+ this.contents = Lists.newArrayList();
+ }
+
+ Builder(int initialCapacity) {
+ this.contents = Lists.newArrayListWithCapacity(initialCapacity);
+ }
@Override public Builder<E> add(E element) {
contents.add(checkNotNull(element));
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimap.java
index 1a4b392..0815e5d 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimap.java
@@ -18,14 +18,14 @@ package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.MoreObjects;
+import com.google.j2objc.annotations.Weak;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.Comparator;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -33,31 +33,18 @@ import java.util.Map.Entry;
import javax.annotation.Nullable;
/**
- * An immutable {@link SetMultimap} with reliable user-specified key and value
- * iteration order. Does not permit null keys or values.
- *
- * <p>Unlike {@link Multimaps#unmodifiableSetMultimap(SetMultimap)}, which is
- * a <i>view</i> of a separate multimap which can still change, an instance of
- * {@code ImmutableSetMultimap} contains its own data and will <i>never</i>
- * change. {@code ImmutableSetMultimap} is convenient for
- * {@code public static final} multimaps ("constant multimaps") and also lets
- * you easily make a "defensive copy" of a multimap provided to your class by
- * a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class
- * are guaranteed to be immutable.
+ * A {@link SetMultimap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Mike Ward
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
-public class ImmutableSetMultimap<K, V>
- extends ImmutableMultimap<K, V>
+public class ImmutableSetMultimap<K, V> extends ImmutableMultimap<K, V>
implements SetMultimap<K, V> {
/** Returns the empty multimap. */
@@ -93,8 +80,7 @@ public class ImmutableSetMultimap<K, V>
* Repeated occurrences of an entry (according to {@link Object#equals}) after
* the first are ignored.
*/
- public static <K, V> ImmutableSetMultimap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3) {
+ public static <K, V> ImmutableSetMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
ImmutableSetMultimap.Builder<K, V> builder = ImmutableSetMultimap.builder();
builder.put(k1, v1);
builder.put(k2, v2);
@@ -143,20 +129,6 @@ public class ImmutableSetMultimap<K, V>
}
/**
- * Multimap for {@link ImmutableSetMultimap.Builder} that maintains key
- * and value orderings and performs better than {@link LinkedHashMultimap}.
- */
- private static class BuilderMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
- BuilderMultimap() {
- super(new LinkedHashMap<K, Collection<V>>());
- }
- @Override Collection<V> createCollection() {
- return Sets.newLinkedHashSet();
- }
- private static final long serialVersionUID = 0;
- }
-
- /**
* A builder for creating immutable {@code SetMultimap} instances, especially
* {@code public static final} multimaps ("constant multimaps"). Example:
* <pre> {@code
@@ -172,23 +144,23 @@ public class ImmutableSetMultimap<K, V>
* times to build multiple multimaps in series. Each multimap contains the
* key-value mappings in the previously created multimaps.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
- public static final class Builder<K, V>
- extends ImmutableMultimap.Builder<K, V> {
+ public static final class Builder<K, V> extends ImmutableMultimap.Builder<K, V> {
/**
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link ImmutableSetMultimap#builder}.
*/
public Builder() {
- builderMultimap = new BuilderMultimap<K, V>();
+ super(MultimapBuilder.linkedHashKeys().linkedHashSetValues().<K, V>build());
}
/**
* Adds a key-value mapping to the built multimap if it is not already
* present.
*/
- @Override public Builder<K, V> put(K key, V value) {
+ @Override
+ public Builder<K, V> put(K key, V value) {
builderMultimap.put(checkNotNull(key), checkNotNull(value));
return this;
}
@@ -198,13 +170,26 @@ public class ImmutableSetMultimap<K, V>
*
* @since 11.0
*/
- @Override public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
- builderMultimap.put(
- checkNotNull(entry.getKey()), checkNotNull(entry.getValue()));
+ @Override
+ public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
+ builderMultimap.put(checkNotNull(entry.getKey()), checkNotNull(entry.getValue()));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 19.0
+ */
+ @Beta
+ @Override
+ public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ super.putAll(entries);
return this;
}
- @Override public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
+ @Override
+ public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
Collection<V> collection = builderMultimap.get(checkNotNull(key));
for (V value : values) {
collection.add(checkNotNull(value));
@@ -212,14 +197,15 @@ public class ImmutableSetMultimap<K, V>
return this;
}
- @Override public Builder<K, V> putAll(K key, V... values) {
+ @Override
+ public Builder<K, V> putAll(K key, V... values) {
return putAll(key, Arrays.asList(values));
}
- @Override public Builder<K, V> putAll(
- Multimap<? extends K, ? extends V> multimap) {
- for (Entry<? extends K, ? extends Collection<? extends V>> entry
- : multimap.asMap().entrySet()) {
+ @Override
+ public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
+ for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+ multimap.asMap().entrySet()) {
putAll(entry.getKey(), entry.getValue());
}
return this;
@@ -257,14 +243,15 @@ public class ImmutableSetMultimap<K, V>
/**
* Returns a newly-created immutable set multimap.
*/
- @Override public ImmutableSetMultimap<K, V> build() {
+ @Override
+ public ImmutableSetMultimap<K, V> build() {
if (keyComparator != null) {
- Multimap<K, V> sortedCopy = new BuilderMultimap<K, V>();
- List<Map.Entry<K, Collection<V>>> entries = Lists.newArrayList(
- builderMultimap.asMap().entrySet());
- Collections.sort(
- entries,
- Ordering.from(keyComparator).<K>onKeys());
+ Multimap<K, V> sortedCopy =
+ MultimapBuilder.linkedHashKeys().linkedHashSetValues().<K, V>build();
+ List<Map.Entry<K, Collection<V>>> entries =
+ Ordering.from(keyComparator)
+ .<K>onKeys()
+ .immutableSortedCopy(builderMultimap.asMap().entrySet());
for (Map.Entry<K, Collection<V>> entry : entries) {
sortedCopy.putAll(entry.getKey(), entry.getValue());
}
@@ -294,8 +281,7 @@ public class ImmutableSetMultimap<K, V>
}
private static <K, V> ImmutableSetMultimap<K, V> copyOf(
- Multimap<? extends K, ? extends V> multimap,
- Comparator<? super V> valueComparator) {
+ Multimap<? extends K, ? extends V> multimap, Comparator<? super V> valueComparator) {
checkNotNull(multimap); // eager for GWT
if (multimap.isEmpty() && valueComparator == null) {
return of();
@@ -303,18 +289,18 @@ public class ImmutableSetMultimap<K, V>
if (multimap instanceof ImmutableSetMultimap) {
@SuppressWarnings("unchecked") // safe since multimap is not writable
- ImmutableSetMultimap<K, V> kvMultimap
- = (ImmutableSetMultimap<K, V>) multimap;
+ ImmutableSetMultimap<K, V> kvMultimap = (ImmutableSetMultimap<K, V>) multimap;
if (!kvMultimap.isPartialView()) {
return kvMultimap;
}
}
- ImmutableMap.Builder<K, ImmutableSet<V>> builder = ImmutableMap.builder();
+ ImmutableMap.Builder<K, ImmutableSet<V>> builder =
+ new ImmutableMap.Builder<K, ImmutableSet<V>>(multimap.asMap().size());
int size = 0;
- for (Entry<? extends K, ? extends Collection<? extends V>> entry
- : multimap.asMap().entrySet()) {
+ for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+ multimap.asMap().entrySet()) {
K key = entry.getKey();
Collection<? extends V> values = entry.getValue();
ImmutableSet<V> set = valueSet(valueComparator, values);
@@ -324,8 +310,23 @@ public class ImmutableSetMultimap<K, V>
}
}
- return new ImmutableSetMultimap<K, V>(
- builder.build(), size, valueComparator);
+ return new ImmutableSetMultimap<K, V>(builder.build(), size, valueComparator);
+ }
+
+ /**
+ * Returns an immutable multimap containing the specified entries. The
+ * returned multimap iterates over keys in the order they were first
+ * encountered in the input, and the values for each key are iterated in the
+ * order they were encountered. If two values for the same key are
+ * {@linkplain Object#equals equal}, the first value encountered is used.
+ *
+ * @throws NullPointerException if any key, value, or entry is null
+ * @since 19.0
+ */
+ @Beta
+ public static <K, V> ImmutableSetMultimap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ return new Builder<K, V>().putAll(entries).build();
}
/**
@@ -334,7 +335,9 @@ public class ImmutableSetMultimap<K, V>
*/
private final transient ImmutableSet<V> emptySet;
- ImmutableSetMultimap(ImmutableMap<K, ImmutableSet<V>> map, int size,
+ ImmutableSetMultimap(
+ ImmutableMap<K, ImmutableSet<V>> map,
+ int size,
@Nullable Comparator<? super V> valueComparator) {
super(map, size);
this.emptySet = emptySet(valueComparator);
@@ -348,7 +351,8 @@ public class ImmutableSetMultimap<K, V>
* The values are in the same order as the parameters used to build this
* multimap.
*/
- @Override public ImmutableSet<V> get(@Nullable K key) {
+ @Override
+ public ImmutableSet<V> get(@Nullable K key) {
// This cast is safe as its type is known in constructor.
ImmutableSet<V> set = (ImmutableSet<V>) map.get(key);
return MoreObjects.firstNonNull(set, emptySet);
@@ -387,7 +391,9 @@ public class ImmutableSetMultimap<K, V>
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public ImmutableSet<V> removeAll(Object key) {
+ @Deprecated
+ @Override
+ public ImmutableSet<V> removeAll(Object key) {
throw new UnsupportedOperationException();
}
@@ -397,8 +403,9 @@ public class ImmutableSetMultimap<K, V>
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public ImmutableSet<V> replaceValues(
- K key, Iterable<? extends V> values) {
+ @Deprecated
+ @Override
+ public ImmutableSet<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
@@ -409,16 +416,17 @@ public class ImmutableSetMultimap<K, V>
* Its iterator traverses the values for the first key, the values for the
* second key, and so on.
*/
- @Override public ImmutableSet<Entry<K, V>> entries() {
+ @Override
+ public ImmutableSet<Entry<K, V>> entries() {
ImmutableSet<Entry<K, V>> result = entries;
- return (result == null)
+ return result == null
? (entries = new EntrySet<K, V>(this))
: result;
}
-
+
private static final class EntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
- private transient final ImmutableSetMultimap<K, V> multimap;
-
+ @Weak private final transient ImmutableSetMultimap<K, V> multimap;
+
EntrySet(ImmutableSetMultimap<K, V> multimap) {
this.multimap = multimap;
}
@@ -445,28 +453,33 @@ public class ImmutableSetMultimap<K, V>
@Override
boolean isPartialView() {
return false;
- }
+ }
}
private static <V> ImmutableSet<V> valueSet(
- @Nullable Comparator<? super V> valueComparator,
- Collection<? extends V> values) {
+ @Nullable Comparator<? super V> valueComparator, Collection<? extends V> values) {
return (valueComparator == null)
? ImmutableSet.copyOf(values)
: ImmutableSortedSet.copyOf(valueComparator, values);
}
- private static <V> ImmutableSet<V> emptySet(
- @Nullable Comparator<? super V> valueComparator) {
+ private static <V> ImmutableSet<V> emptySet(@Nullable Comparator<? super V> valueComparator) {
return (valueComparator == null)
? ImmutableSet.<V>of()
: ImmutableSortedSet.<V>emptySet(valueComparator);
}
- @Nullable Comparator<? super V> valueComparator() {
+ private static <V> ImmutableSet.Builder<V> valuesBuilder(
+ @Nullable Comparator<? super V> valueComparator) {
+ return (valueComparator == null)
+ ? new ImmutableSet.Builder<V>()
+ : new ImmutableSortedSet.Builder<V>(valueComparator);
+ }
+
+ @Nullable
+ Comparator<? super V> valueComparator() {
return emptySet instanceof ImmutableSortedSet
? ((ImmutableSortedSet<V>) emptySet).comparator()
: null;
}
}
-
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedAsList.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedAsList.java
index c94e88e..e1a068a 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedAsList.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedAsList.java
@@ -28,8 +28,7 @@ import java.util.Comparator;
@SuppressWarnings("serial")
final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
implements SortedIterable<E> {
- ImmutableSortedAsList(
- ImmutableSortedSet<E> backingSet, ImmutableList<E> backingList) {
+ ImmutableSortedAsList(ImmutableSortedSet<E> backingSet, ImmutableList<E> backingList) {
super(backingSet, backingList);
}
@@ -38,7 +37,8 @@ final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
return (ImmutableSortedSet<E>) super.delegateCollection();
}
- @Override public Comparator<? super E> comparator() {
+ @Override
+ public Comparator<? super E> comparator() {
return delegateCollection().comparator();
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMap.java
index 238ffe9..f8f151f 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMap.java
@@ -19,9 +19,10 @@ package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Maps.newTreeMap;
+import static java.util.Collections.singletonMap;
import static java.util.Collections.unmodifiableSortedMap;
-import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.ImmutableSortedMap.Builder;
import java.util.Comparator;
import java.util.Iterator;
@@ -34,7 +35,7 @@ import java.util.SortedMap;
*
* @author Hayward Chan
*/
-public abstract class ImmutableSortedMap<K, V>
+public final class ImmutableSortedMap<K, V>
extends ForwardingImmutableMap<K, V> implements SortedMap<K, V> {
@SuppressWarnings("unchecked")
@@ -62,26 +63,15 @@ public abstract class ImmutableSortedMap<K, V>
this.sortedDelegate = delegate;
}
- private static <K, V> ImmutableSortedMap<K, V> create(
- Comparator<? super K> comparator,
- Entry<? extends K, ? extends V>... entries) {
- checkNotNull(comparator);
- SortedMap<K, V> delegate = newModifiableDelegate(comparator);
- for (Entry<? extends K, ? extends V> entry : entries) {
- delegate.put(entry.getKey(), entry.getValue());
- }
- return newView(unmodifiableSortedMap(delegate), comparator);
- }
-
// Casting to any type is safe because the set will never hold any elements.
@SuppressWarnings("unchecked")
public static <K, V> ImmutableSortedMap<K, V> of() {
- return EmptyImmutableSortedMap.forComparator(NATURAL_ORDER);
+ return new Builder<K, V>(NATURAL_ORDER).build();
}
public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
of(K k1, V v1) {
- return create(Ordering.natural(), entryOf(k1, v1));
+ return copyOf(singletonMap(k1, v1));
}
public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
@@ -118,6 +108,17 @@ public abstract class ImmutableSortedMap<K, V>
return copyOfInternal(map, checkNotNull(comparator));
}
+ public static <K, V> ImmutableSortedMap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ return new Builder<K, V>(NATURAL_ORDER).putAll(entries).build();
+ }
+
+ public static <K, V> ImmutableSortedMap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries,
+ Comparator<? super K> comparator) {
+ return new Builder<K, V>(comparator).putAll(entries).build();
+ }
+
public static <K, V> ImmutableSortedMap<K, V> copyOfSorted(
SortedMap<K, ? extends V> map) {
// If map has a null comparator, the keys should have a natural ordering,
@@ -162,9 +163,9 @@ public abstract class ImmutableSortedMap<K, V>
Entry<K, V> previousEntry
= map.tailMap(key).entrySet().iterator().next();
throw new IllegalArgumentException(
- "Duplicate keys in mappings " + previousEntry.getKey() +
- "=" + previousEntry.getValue() + " and " + key +
- "=" + value);
+ "Duplicate keys in mappings " + previousEntry.getKey()
+ + "=" + previousEntry.getValue() + " and " + key
+ + "=" + value);
}
map.put(key, value);
}
@@ -199,11 +200,21 @@ public abstract class ImmutableSortedMap<K, V>
}
@Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
- for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
- put(entry.getKey(), entry.getValue());
+ return putAll(map.entrySet());
+ }
+
+ @Override public Builder<K, V> putAll(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ for (Entry<? extends K, ? extends V> entry : entries) {
+ put(entry);
}
return this;
}
+
+ @Override
+ public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
+ throw new UnsupportedOperationException("Not available on ImmutableSortedMap.Builder");
+ }
@Override public ImmutableSortedMap<K, V> build() {
SortedMap<K, V> delegate = newModifiableDelegate(comparator);
@@ -295,7 +306,7 @@ public abstract class ImmutableSortedMap<K, V>
if (!inclusive) {
fromKey = higher(fromKey);
if (fromKey == null) {
- return EmptyImmutableSortedMap.forComparator(comparator());
+ return new Builder<K, V>(this.comparator).build();
}
}
return tailMap(fromKey);
@@ -307,10 +318,7 @@ public abstract class ImmutableSortedMap<K, V>
private static <K, V> ImmutableSortedMap<K, V> newView(
SortedMap<K, V> delegate, Comparator<? super K> comparator) {
- if (delegate.isEmpty()) {
- return EmptyImmutableSortedMap.forComparator(comparator);
- }
- return new RegularImmutableSortedMap<K, V>(delegate, comparator);
+ return new ImmutableSortedMap<K, V>(delegate, comparator);
}
/*
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSet.java
index 1eff230..e24caae 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSet.java
@@ -55,25 +55,21 @@ public abstract class ImmutableSortedSet<E>
@SuppressWarnings("unchecked")
private static final ImmutableSortedSet<Object> NATURAL_EMPTY_SET =
- new EmptyImmutableSortedSet<Object>(NATURAL_ORDER);
-
- @SuppressWarnings("unchecked")
- private static <E> ImmutableSortedSet<E> emptySet() {
- return (ImmutableSortedSet<E>) NATURAL_EMPTY_SET;
- }
+ new RegularImmutableSortedSet<Object>(new TreeSet<Object>(NATURAL_ORDER), false);
static <E> ImmutableSortedSet<E> emptySet(
Comparator<? super E> comparator) {
checkNotNull(comparator);
if (NATURAL_ORDER.equals(comparator)) {
- return emptySet();
+ return of();
} else {
- return new EmptyImmutableSortedSet<E>(comparator);
+ return new RegularImmutableSortedSet<E>(new TreeSet<E>(comparator), false);
}
}
+ @SuppressWarnings("unchecked")
public static <E> ImmutableSortedSet<E> of() {
- return emptySet();
+ return (ImmutableSortedSet<E>) NATURAL_EMPTY_SET;
}
public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterables.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterables.java
index 0ca88c7..6be8885 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterables.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterables.java
@@ -35,6 +35,7 @@ import java.util.Queue;
import java.util.RandomAccess;
import java.util.Set;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -47,23 +48,21 @@ import javax.annotation.Nullable;
* only advance the backing iteration when absolutely necessary.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Iterables">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#iterables">
* {@code Iterables}</a>.
*
* @author Kevin Bourrillion
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Iterables {
private Iterables() {}
/** Returns an unmodifiable view of {@code iterable}. */
- public static <T> Iterable<T> unmodifiableIterable(
- final Iterable<T> iterable) {
+ public static <T> Iterable<T> unmodifiableIterable(final Iterable<T> iterable) {
checkNotNull(iterable);
- if (iterable instanceof UnmodifiableIterable ||
- iterable instanceof ImmutableCollection) {
+ if (iterable instanceof UnmodifiableIterable || iterable instanceof ImmutableCollection) {
return iterable;
}
return new UnmodifiableIterable<T>(iterable);
@@ -75,8 +74,8 @@ public final class Iterables {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <E> Iterable<E> unmodifiableIterable(
- ImmutableCollection<E> iterable) {
+ @Deprecated
+ public static <E> Iterable<E> unmodifiableIterable(ImmutableCollection<E> iterable) {
return checkNotNull(iterable);
}
@@ -131,8 +130,7 @@ public final class Iterables {
* @param elementsToRemove the elements to remove
* @return {@code true} if any element was removed from {@code iterable}
*/
- public static boolean removeAll(
- Iterable<?> removeFrom, Collection<?> elementsToRemove) {
+ public static boolean removeAll(Iterable<?> removeFrom, Collection<?> elementsToRemove) {
return (removeFrom instanceof Collection)
? ((Collection<?>) removeFrom).removeAll(checkNotNull(elementsToRemove))
: Iterators.removeAll(removeFrom.iterator(), elementsToRemove);
@@ -149,8 +147,7 @@ public final class Iterables {
* @param elementsToRetain the elements to retain
* @return {@code true} if any element was removed from {@code iterable}
*/
- public static boolean retainAll(
- Iterable<?> removeFrom, Collection<?> elementsToRetain) {
+ public static boolean retainAll(Iterable<?> removeFrom, Collection<?> elementsToRetain) {
return (removeFrom instanceof Collection)
? ((Collection<?>) removeFrom).retainAll(checkNotNull(elementsToRetain))
: Iterators.retainAll(removeFrom.iterator(), elementsToRetain);
@@ -169,11 +166,9 @@ public final class Iterables {
* {@code remove()}.
* @since 2.0
*/
- public static <T> boolean removeIf(
- Iterable<T> removeFrom, Predicate<? super T> predicate) {
+ public static <T> boolean removeIf(Iterable<T> removeFrom, Predicate<? super T> predicate) {
if (removeFrom instanceof RandomAccess && removeFrom instanceof List) {
- return removeIfFromRandomAccessList(
- (List<T>) removeFrom, checkNotNull(predicate));
+ return removeIfFromRandomAccessList((List<T>) removeFrom, checkNotNull(predicate));
}
return Iterators.removeIf(removeFrom.iterator(), predicate);
}
@@ -205,8 +200,8 @@ public final class Iterables {
return from != to;
}
- private static <T> void slowRemoveIfForRemainingElements(List<T> list,
- Predicate<? super T> predicate, int to, int from) {
+ private static <T> void slowRemoveIfForRemainingElements(
+ List<T> list, Predicate<? super T> predicate, int to, int from) {
// Here we know that:
// * (to < from) and that both are valid indices.
// * Everything with (index < to) should be kept.
@@ -252,8 +247,8 @@ public final class Iterables {
* of {@code iterable1} is equal to the corresponding element of
* {@code iterable2}.
*/
- public static boolean elementsEqual(
- Iterable<?> iterable1, Iterable<?> iterable2) {
+ @CheckReturnValue
+ public static boolean elementsEqual(Iterable<?> iterable1, Iterable<?> iterable2) {
if (iterable1 instanceof Collection && iterable2 instanceof Collection) {
Collection<?> collection1 = (Collection<?>) iterable1;
Collection<?> collection2 = (Collection<?>) iterable2;
@@ -295,11 +290,15 @@ public final class Iterables {
* elements
*/
@Nullable
- public static <T> T getOnlyElement(
- Iterable<? extends T> iterable, @Nullable T defaultValue) {
+ public static <T> T getOnlyElement(Iterable<? extends T> iterable, @Nullable T defaultValue) {
return Iterators.getOnlyElement(iterable.iterator(), defaultValue);
}
+ static <T> T[] toArray(Iterable<? extends T> iterable, T[] array) {
+ Collection<? extends T> collection = toCollection(iterable);
+ return collection.toArray(array);
+ }
+
/**
* Copies an iterable's elements into an array.
*
@@ -328,8 +327,7 @@ public final class Iterables {
* @return {@code true} if {@code collection} was modified as a result of this
* operation.
*/
- public static <T> boolean addAll(
- Collection<T> addTo, Iterable<? extends T> elementsToAdd) {
+ public static <T> boolean addAll(Collection<T> addTo, Iterable<? extends T> elementsToAdd) {
if (elementsToAdd instanceof Collection) {
Collection<? extends T> c = Collections2.cast(elementsToAdd);
return addTo.addAll(c);
@@ -377,7 +375,9 @@ public final class Iterables {
public Iterator<T> iterator() {
return Iterators.cycle(iterable);
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return iterable.toString() + " (cycled)";
}
};
@@ -413,8 +413,7 @@ public final class Iterables {
* <p>The returned iterable's iterator supports {@code remove()} when the
* corresponding input iterator supports it.
*/
- public static <T> Iterable<T> concat(
- Iterable<? extends T> a, Iterable<? extends T> b) {
+ public static <T> Iterable<T> concat(Iterable<? extends T> a, Iterable<? extends T> b) {
return concat(ImmutableList.of(a, b));
}
@@ -427,8 +426,8 @@ public final class Iterables {
* <p>The returned iterable's iterator supports {@code remove()} when the
* corresponding input iterator supports it.
*/
- public static <T> Iterable<T> concat(Iterable<? extends T> a,
- Iterable<? extends T> b, Iterable<? extends T> c) {
+ public static <T> Iterable<T> concat(
+ Iterable<? extends T> a, Iterable<? extends T> b, Iterable<? extends T> c) {
return concat(ImmutableList.of(a, b, c));
}
@@ -442,8 +441,10 @@ public final class Iterables {
* <p>The returned iterable's iterator supports {@code remove()} when the
* corresponding input iterator supports it.
*/
- public static <T> Iterable<T> concat(Iterable<? extends T> a,
- Iterable<? extends T> b, Iterable<? extends T> c,
+ public static <T> Iterable<T> concat(
+ Iterable<? extends T> a,
+ Iterable<? extends T> b,
+ Iterable<? extends T> c,
Iterable<? extends T> d) {
return concat(ImmutableList.of(a, b, c, d));
}
@@ -472,8 +473,7 @@ public final class Iterables {
* iterable may throw {@code NullPointerException} if any of the input
* iterators is null.
*/
- public static <T> Iterable<T> concat(
- final Iterable<? extends Iterable<? extends T>> inputs) {
+ public static <T> Iterable<T> concat(final Iterable<? extends Iterable<? extends T>> inputs) {
checkNotNull(inputs);
return new FluentIterable<T>() {
@Override
@@ -517,8 +517,7 @@ public final class Iterables {
* iterable} divided into partitions
* @throws IllegalArgumentException if {@code size} is nonpositive
*/
- public static <T> Iterable<List<T>> partition(
- final Iterable<T> iterable, final int size) {
+ public static <T> Iterable<List<T>> partition(final Iterable<T> iterable, final int size) {
checkNotNull(iterable);
checkArgument(size > 0);
return new FluentIterable<List<T>>() {
@@ -546,8 +545,7 @@ public final class Iterables {
* trailing null elements)
* @throws IllegalArgumentException if {@code size} is nonpositive
*/
- public static <T> Iterable<List<T>> paddedPartition(
- final Iterable<T> iterable, final int size) {
+ public static <T> Iterable<List<T>> paddedPartition(final Iterable<T> iterable, final int size) {
checkNotNull(iterable);
checkArgument(size > 0);
return new FluentIterable<List<T>>() {
@@ -562,6 +560,7 @@ public final class Iterables {
* Returns the elements of {@code unfiltered} that satisfy a predicate. The
* resulting iterable's iterator does not support {@code remove()}.
*/
+ @CheckReturnValue
public static <T> Iterable<T> filter(
final Iterable<T> unfiltered, final Predicate<? super T> predicate) {
checkNotNull(unfiltered);
@@ -577,8 +576,7 @@ public final class Iterables {
/**
* Returns {@code true} if any element in {@code iterable} satisfies the predicate.
*/
- public static <T> boolean any(
- Iterable<T> iterable, Predicate<? super T> predicate) {
+ public static <T> boolean any(Iterable<T> iterable, Predicate<? super T> predicate) {
return Iterators.any(iterable.iterator(), predicate);
}
@@ -586,8 +584,7 @@ public final class Iterables {
* Returns {@code true} if every element in {@code iterable} satisfies the
* predicate. If {@code iterable} is empty, {@code true} is returned.
*/
- public static <T> boolean all(
- Iterable<T> iterable, Predicate<? super T> predicate) {
+ public static <T> boolean all(Iterable<T> iterable, Predicate<? super T> predicate) {
return Iterators.all(iterable.iterator(), predicate);
}
@@ -600,8 +597,7 @@ public final class Iterables {
* @throws NoSuchElementException if no element in {@code iterable} matches
* the given predicate
*/
- public static <T> T find(Iterable<T> iterable,
- Predicate<? super T> predicate) {
+ public static <T> T find(Iterable<T> iterable, Predicate<? super T> predicate) {
return Iterators.find(iterable.iterator(), predicate);
}
@@ -614,8 +610,8 @@ public final class Iterables {
* @since 7.0
*/
@Nullable
- public static <T> T find(Iterable<? extends T> iterable,
- Predicate<? super T> predicate, @Nullable T defaultValue) {
+ public static <T> T find(
+ Iterable<? extends T> iterable, Predicate<? super T> predicate, @Nullable T defaultValue) {
return Iterators.find(iterable.iterator(), predicate, defaultValue);
}
@@ -629,8 +625,7 @@ public final class Iterables {
*
* @since 11.0
*/
- public static <T> Optional<T> tryFind(Iterable<T> iterable,
- Predicate<? super T> predicate) {
+ public static <T> Optional<T> tryFind(Iterable<T> iterable, Predicate<? super T> predicate) {
return Iterators.tryFind(iterable.iterator(), predicate);
}
@@ -645,8 +640,7 @@ public final class Iterables {
*
* @since 2.0
*/
- public static <T> int indexOf(
- Iterable<T> iterable, Predicate<? super T> predicate) {
+ public static <T> int indexOf(Iterable<T> iterable, Predicate<? super T> predicate) {
return Iterators.indexOf(iterable.iterator(), predicate);
}
@@ -662,8 +656,9 @@ public final class Iterables {
* {@code Collection}, consider {@link Lists#transform} and {@link
* Collections2#transform}.
*/
- public static <F, T> Iterable<T> transform(final Iterable<F> fromIterable,
- final Function<? super F, ? extends T> function) {
+ @CheckReturnValue
+ public static <F, T> Iterable<T> transform(
+ final Iterable<F> fromIterable, final Function<? super F, ? extends T> function) {
checkNotNull(fromIterable);
checkNotNull(function);
return new FluentIterable<T>() {
@@ -799,8 +794,7 @@ public final class Iterables {
*
* @since 3.0
*/
- public static <T> Iterable<T> skip(final Iterable<T> iterable,
- final int numberToSkip) {
+ public static <T> Iterable<T> skip(final Iterable<T> iterable, final int numberToSkip) {
checkNotNull(iterable);
checkArgument(numberToSkip >= 0, "number to skip cannot be negative");
@@ -865,8 +859,7 @@ public final class Iterables {
* @throws IllegalArgumentException if {@code limitSize} is negative
* @since 3.0
*/
- public static <T> Iterable<T> limit(
- final Iterable<T> iterable, final int limitSize) {
+ public static <T> Iterable<T> limit(final Iterable<T> iterable, final int limitSize) {
checkNotNull(iterable);
checkArgument(limitSize >= 0, "limit is negative");
return new FluentIterable<T>() {
@@ -926,22 +919,6 @@ public final class Iterables {
};
}
- private static class ConsumingQueueIterator<T> extends AbstractIterator<T> {
- private final Queue<T> queue;
-
- private ConsumingQueueIterator(Queue<T> queue) {
- this.queue = queue;
- }
-
- @Override public T computeNext() {
- try {
- return queue.remove();
- } catch (NoSuchElementException e) {
- return endOfData();
- }
- }
- }
-
// Methods only in Iterables, not in Iterators
/**
@@ -978,21 +955,21 @@ public final class Iterables {
final Comparator<? super T> comparator) {
checkNotNull(iterables, "iterables");
checkNotNull(comparator, "comparator");
- Iterable<T> iterable = new FluentIterable<T>() {
- @Override
- public Iterator<T> iterator() {
- return Iterators.mergeSorted(
- Iterables.transform(iterables, Iterables.<T>toIterator()),
- comparator);
- }
- };
+ Iterable<T> iterable =
+ new FluentIterable<T>() {
+ @Override
+ public Iterator<T> iterator() {
+ return Iterators.mergeSorted(
+ Iterables.transform(iterables, Iterables.<T>toIterator()),
+ comparator);
+ }
+ };
return new UnmodifiableIterable<T>(iterable);
}
// TODO(user): Is this the best place for this? Move to fluent functions?
// Useful as a public method?
- private static <T> Function<Iterable<? extends T>, Iterator<? extends T>>
- toIterator() {
+ private static <T> Function<Iterable<? extends T>, Iterator<? extends T>> toIterator() {
return new Function<Iterable<? extends T>, Iterator<? extends T>>() {
@Override
public Iterator<? extends T> apply(Iterable<? extends T> iterable) {
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterators.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterators.java
index e63a460..d1e1fff 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterators.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterators.java
@@ -44,6 +44,7 @@ import java.util.NoSuchElementException;
import java.util.PriorityQueue;
import java.util.Queue;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -56,39 +57,44 @@ import javax.annotation.Nullable;
* the backing iteration when absolutely necessary.
*
* <p>See the Guava User Guide section on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Iterables">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#iterables">
* {@code Iterators}</a>.
*
* @author Kevin Bourrillion
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Iterators {
private Iterators() {}
- static final UnmodifiableListIterator<Object> EMPTY_LIST_ITERATOR
- = new UnmodifiableListIterator<Object>() {
+ static final UnmodifiableListIterator<Object> EMPTY_LIST_ITERATOR =
+ new UnmodifiableListIterator<Object>() {
@Override
public boolean hasNext() {
return false;
}
+
@Override
public Object next() {
throw new NoSuchElementException();
}
+
@Override
public boolean hasPrevious() {
return false;
}
+
@Override
public Object previous() {
throw new NoSuchElementException();
}
+
@Override
public int nextIndex() {
return 0;
}
+
@Override
public int previousIndex() {
return -1;
@@ -124,15 +130,18 @@ public final class Iterators {
private static final Iterator<Object> EMPTY_MODIFIABLE_ITERATOR =
new Iterator<Object>() {
- @Override public boolean hasNext() {
+ @Override
+ public boolean hasNext() {
return false;
}
- @Override public Object next() {
+ @Override
+ public Object next() {
throw new NoSuchElementException();
}
- @Override public void remove() {
+ @Override
+ public void remove() {
checkRemove(false);
}
};
@@ -150,8 +159,7 @@ public final class Iterators {
}
/** Returns an unmodifiable view of {@code iterator}. */
- public static <T> UnmodifiableIterator<T> unmodifiableIterator(
- final Iterator<T> iterator) {
+ public static <T> UnmodifiableIterator<T> unmodifiableIterator(final Iterator<T> iterator) {
checkNotNull(iterator);
if (iterator instanceof UnmodifiableIterator) {
return (UnmodifiableIterator<T>) iterator;
@@ -161,6 +169,7 @@ public final class Iterators {
public boolean hasNext() {
return iterator.hasNext();
}
+
@Override
public T next() {
return iterator.next();
@@ -174,8 +183,8 @@ public final class Iterators {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <T> UnmodifiableIterator<T> unmodifiableIterator(
- UnmodifiableIterator<T> iterator) {
+ @Deprecated
+ public static <T> UnmodifiableIterator<T> unmodifiableIterator(UnmodifiableIterator<T> iterator) {
return checkNotNull(iterator);
}
@@ -209,8 +218,7 @@ public final class Iterators {
* @param elementsToRemove the elements to remove
* @return {@code true} if any element was removed from {@code iterator}
*/
- public static boolean removeAll(
- Iterator<?> removeFrom, Collection<?> elementsToRemove) {
+ public static boolean removeAll(Iterator<?> removeFrom, Collection<?> elementsToRemove) {
return removeIf(removeFrom, in(elementsToRemove));
}
@@ -225,8 +233,7 @@ public final class Iterators {
* @return {@code true} if any elements were removed from the iterator
* @since 2.0
*/
- public static <T> boolean removeIf(
- Iterator<T> removeFrom, Predicate<? super T> predicate) {
+ public static <T> boolean removeIf(Iterator<T> removeFrom, Predicate<? super T> predicate) {
checkNotNull(predicate);
boolean modified = false;
while (removeFrom.hasNext()) {
@@ -247,8 +254,7 @@ public final class Iterators {
* @param elementsToRetain the elements to retain
* @return {@code true} if any element was removed from {@code iterator}
*/
- public static boolean retainAll(
- Iterator<?> removeFrom, Collection<?> elementsToRetain) {
+ public static boolean retainAll(Iterator<?> removeFrom, Collection<?> elementsToRetain) {
return removeIf(removeFrom, not(in(elementsToRetain)));
}
@@ -262,8 +268,7 @@ public final class Iterators {
* <p>Note that this will modify the supplied iterators, since they will have
* been advanced some number of elements forward.
*/
- public static boolean elementsEqual(
- Iterator<?> iterator1, Iterator<?> iterator2) {
+ public static boolean elementsEqual(Iterator<?> iterator1, Iterator<?> iterator2) {
while (iterator1.hasNext()) {
if (!iterator2.hasNext()) {
return false;
@@ -335,8 +340,7 @@ public final class Iterators {
* @return {@code true} if {@code collection} was modified as a result of this
* operation
*/
- public static <T> boolean addAll(
- Collection<T> addTo, Iterator<? extends T> iterator) {
+ public static <T> boolean addAll(Collection<T> addTo, Iterator<? extends T> iterator) {
checkNotNull(addTo);
checkNotNull(iterator);
boolean wasModified = false;
@@ -374,29 +378,36 @@ public final class Iterators {
public static <T> Iterator<T> cycle(final Iterable<T> iterable) {
checkNotNull(iterable);
return new Iterator<T>() {
- Iterator<T> iterator = emptyIterator();
- Iterator<T> removeFrom;
+ Iterator<T> iterator = emptyModifiableIterator();
@Override
public boolean hasNext() {
- if (!iterator.hasNext()) {
- iterator = iterable.iterator();
- }
- return iterator.hasNext();
+ /*
+ * Don't store a new Iterator until we know the user can't remove() the last returned
+ * element anymore. Otherwise, when we remove from the old iterator, we may be invalidating
+ * the new one. The result is a ConcurrentModificationException or other bad behavior.
+ *
+ * (If we decide that we really, really hate allocating two Iterators per cycle instead of
+ * one, we can optimistically store the new Iterator and then be willing to throw it out if
+ * the user calls remove().)
+ */
+ return iterator.hasNext() || iterable.iterator().hasNext();
}
+
@Override
public T next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
+ if (!iterator.hasNext()) {
+ iterator = iterable.iterator();
+ if (!iterator.hasNext()) {
+ throw new NoSuchElementException();
+ }
}
- removeFrom = iterator;
return iterator.next();
}
+
@Override
public void remove() {
- checkRemove(removeFrom != null);
- removeFrom.remove();
- removeFrom = null;
+ iterator.remove();
}
};
}
@@ -431,9 +442,10 @@ public final class Iterators {
* {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
* resulting iterator has a cubic complexity to the depth of the nesting.
*/
- public static <T> Iterator<T> concat(Iterator<? extends T> a,
- Iterator<? extends T> b) {
- return concat(ImmutableList.of(a, b).iterator());
+ public static <T> Iterator<T> concat(Iterator<? extends T> a, Iterator<? extends T> b) {
+ checkNotNull(a);
+ checkNotNull(b);
+ return concat(new ConsumingQueueIterator<Iterator<? extends T>>(a, b));
}
/**
@@ -450,9 +462,12 @@ public final class Iterators {
* {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
* resulting iterator has a cubic complexity to the depth of the nesting.
*/
- public static <T> Iterator<T> concat(Iterator<? extends T> a,
- Iterator<? extends T> b, Iterator<? extends T> c) {
- return concat(ImmutableList.of(a, b, c).iterator());
+ public static <T> Iterator<T> concat(
+ Iterator<? extends T> a, Iterator<? extends T> b, Iterator<? extends T> c) {
+ checkNotNull(a);
+ checkNotNull(b);
+ checkNotNull(c);
+ return concat(new ConsumingQueueIterator<Iterator<? extends T>>(a, b, c));
}
/**
@@ -469,10 +484,16 @@ public final class Iterators {
* {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
* resulting iterator has a cubic complexity to the depth of the nesting.
*/
- public static <T> Iterator<T> concat(Iterator<? extends T> a,
- Iterator<? extends T> b, Iterator<? extends T> c,
+ public static <T> Iterator<T> concat(
+ Iterator<? extends T> a,
+ Iterator<? extends T> b,
+ Iterator<? extends T> c,
Iterator<? extends T> d) {
- return concat(ImmutableList.of(a, b, c, d).iterator());
+ checkNotNull(a);
+ checkNotNull(b);
+ checkNotNull(c);
+ checkNotNull(d);
+ return concat(new ConsumingQueueIterator<Iterator<? extends T>>(a, b, c, d));
}
/**
@@ -491,7 +512,10 @@ public final class Iterators {
* @throws NullPointerException if any of the provided iterators is null
*/
public static <T> Iterator<T> concat(Iterator<? extends T>... inputs) {
- return concat(ImmutableList.copyOf(inputs).iterator());
+ for (Iterator<? extends T> input : checkNotNull(inputs)) {
+ checkNotNull(input);
+ }
+ return concat(new ConsumingQueueIterator<Iterator<? extends T>>(inputs));
}
/**
@@ -508,8 +532,7 @@ public final class Iterators {
* {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
* resulting iterator has a cubic complexity to the depth of the nesting.
*/
- public static <T> Iterator<T> concat(
- final Iterator<? extends Iterator<? extends T>> inputs) {
+ public static <T> Iterator<T> concat(final Iterator<? extends Iterator<? extends T>> inputs) {
checkNotNull(inputs);
return new Iterator<T>() {
Iterator<? extends T> current = emptyIterator();
@@ -525,12 +548,12 @@ public final class Iterators {
// because otherwise we'll have called inputs.next() before throwing
// the first NPE, and the next time around we'll call inputs.next()
// again, incorrectly moving beyond the error.
- while (!(currentHasNext = checkNotNull(current).hasNext())
- && inputs.hasNext()) {
+ while (!(currentHasNext = checkNotNull(current).hasNext()) && inputs.hasNext()) {
current = inputs.next();
}
return currentHasNext;
}
+
@Override
public T next() {
if (!hasNext()) {
@@ -539,6 +562,7 @@ public final class Iterators {
removeFrom = current;
return current.next();
}
+
@Override
public void remove() {
checkRemove(removeFrom != null);
@@ -563,8 +587,7 @@ public final class Iterators {
* iterator} divided into partitions
* @throws IllegalArgumentException if {@code size} is nonpositive
*/
- public static <T> UnmodifiableIterator<List<T>> partition(
- Iterator<T> iterator, int size) {
+ public static <T> UnmodifiableIterator<List<T>> partition(Iterator<T> iterator, int size) {
return partitionImpl(iterator, size, false);
}
@@ -584,8 +607,7 @@ public final class Iterators {
* trailing null elements)
* @throws IllegalArgumentException if {@code size} is nonpositive
*/
- public static <T> UnmodifiableIterator<List<T>> paddedPartition(
- Iterator<T> iterator, int size) {
+ public static <T> UnmodifiableIterator<List<T>> paddedPartition(Iterator<T> iterator, int size) {
return partitionImpl(iterator, size, true);
}
@@ -598,6 +620,7 @@ public final class Iterators {
public boolean hasNext() {
return iterator.hasNext();
}
+
@Override
public List<T> next() {
if (!hasNext()) {
@@ -613,8 +636,7 @@ public final class Iterators {
}
@SuppressWarnings("unchecked") // we only put Ts in it
- List<T> list = Collections.unmodifiableList(
- (List<T>) Arrays.asList(array));
+ List<T> list = Collections.unmodifiableList((List<T>) Arrays.asList(array));
return (pad || count == size) ? list : list.subList(0, count);
}
};
@@ -623,12 +645,14 @@ public final class Iterators {
/**
* Returns the elements of {@code unfiltered} that satisfy a predicate.
*/
+ @CheckReturnValue
public static <T> UnmodifiableIterator<T> filter(
final Iterator<T> unfiltered, final Predicate<? super T> predicate) {
checkNotNull(unfiltered);
checkNotNull(predicate);
return new AbstractIterator<T>() {
- @Override protected T computeNext() {
+ @Override
+ protected T computeNext() {
while (unfiltered.hasNext()) {
T element = unfiltered.next();
if (predicate.apply(element)) {
@@ -644,8 +668,7 @@ public final class Iterators {
* Returns {@code true} if one or more elements returned by {@code iterator}
* satisfy the given predicate.
*/
- public static <T> boolean any(
- Iterator<T> iterator, Predicate<? super T> predicate) {
+ public static <T> boolean any(Iterator<T> iterator, Predicate<? super T> predicate) {
return indexOf(iterator, predicate) != -1;
}
@@ -654,8 +677,7 @@ public final class Iterators {
* satisfies the given predicate. If {@code iterator} is empty, {@code true}
* is returned.
*/
- public static <T> boolean all(
- Iterator<T> iterator, Predicate<? super T> predicate) {
+ public static <T> boolean all(Iterator<T> iterator, Predicate<? super T> predicate) {
checkNotNull(predicate);
while (iterator.hasNext()) {
T element = iterator.next();
@@ -677,8 +699,7 @@ public final class Iterators {
* @throws NoSuchElementException if no element in {@code iterator} matches
* the given predicate
*/
- public static <T> T find(
- Iterator<T> iterator, Predicate<? super T> predicate) {
+ public static <T> T find(Iterator<T> iterator, Predicate<? super T> predicate) {
return filter(iterator, predicate).next();
}
@@ -693,8 +714,8 @@ public final class Iterators {
* @since 7.0
*/
@Nullable
- public static <T> T find(Iterator<? extends T> iterator, Predicate<? super T> predicate,
- @Nullable T defaultValue) {
+ public static <T> T find(
+ Iterator<? extends T> iterator, Predicate<? super T> predicate, @Nullable T defaultValue) {
return getNext(filter(iterator, predicate), defaultValue);
}
@@ -711,8 +732,7 @@ public final class Iterators {
*
* @since 11.0
*/
- public static <T> Optional<T> tryFind(
- Iterator<T> iterator, Predicate<? super T> predicate) {
+ public static <T> Optional<T> tryFind(Iterator<T> iterator, Predicate<? super T> predicate) {
UnmodifiableIterator<T> filteredIterator = filter(iterator, predicate);
return filteredIterator.hasNext()
? Optional.of(filteredIterator.next())
@@ -735,8 +755,7 @@ public final class Iterators {
*
* @since 2.0
*/
- public static <T> int indexOf(
- Iterator<T> iterator, Predicate<? super T> predicate) {
+ public static <T> int indexOf(Iterator<T> iterator, Predicate<? super T> predicate) {
checkNotNull(predicate, "predicate");
for (int i = 0; iterator.hasNext(); i++) {
T current = iterator.next();
@@ -755,8 +774,8 @@ public final class Iterators {
* does. After a successful {@code remove()} call, {@code fromIterator} no
* longer contains the corresponding element.
*/
- public static <F, T> Iterator<T> transform(final Iterator<F> fromIterator,
- final Function<? super F, ? extends T> function) {
+ public static <F, T> Iterator<T> transform(
+ final Iterator<F> fromIterator, final Function<? super F, ? extends T> function) {
checkNotNull(function);
return new TransformedIterator<F, T>(fromIterator) {
@Override
@@ -780,17 +799,19 @@ public final class Iterators {
checkNonnegative(position);
int skipped = advance(iterator, position);
if (!iterator.hasNext()) {
- throw new IndexOutOfBoundsException("position (" + position
- + ") must be less than the number of elements that remained ("
- + skipped + ")");
+ throw new IndexOutOfBoundsException(
+ "position ("
+ + position
+ + ") must be less than the number of elements that remained ("
+ + skipped
+ + ")");
}
return iterator.next();
}
static void checkNonnegative(int position) {
if (position < 0) {
- throw new IndexOutOfBoundsException("position (" + position
- + ") must not be negative");
+ throw new IndexOutOfBoundsException("position (" + position + ") must not be negative");
}
}
@@ -888,8 +909,7 @@ public final class Iterators {
* @throws IllegalArgumentException if {@code limitSize} is negative
* @since 3.0
*/
- public static <T> Iterator<T> limit(
- final Iterator<T> iterator, final int limitSize) {
+ public static <T> Iterator<T> limit(final Iterator<T> iterator, final int limitSize) {
checkNotNull(iterator);
checkArgument(limitSize >= 0, "limit is negative");
return new Iterator<T>() {
@@ -1021,7 +1041,8 @@ public final class Iterators {
* past the beginning of the iteration.
*/
return new AbstractIndexedListIterator<T>(length, index) {
- @Override protected T get(int index) {
+ @Override
+ protected T get(int index) {
return array[offset + index];
}
};
@@ -1033,14 +1054,15 @@ public final class Iterators {
* <p>The {@link Iterable} equivalent of this method is {@link
* Collections#singleton}.
*/
- public static <T> UnmodifiableIterator<T> singletonIterator(
- @Nullable final T value) {
+ public static <T> UnmodifiableIterator<T> singletonIterator(@Nullable final T value) {
return new UnmodifiableIterator<T>() {
boolean done;
+
@Override
public boolean hasNext() {
return !done;
}
+
@Override
public T next() {
if (done) {
@@ -1060,14 +1082,14 @@ public final class Iterators {
* contents can be <i>copied</i> into a collection using {@link
* Collections#list}.
*/
- public static <T> UnmodifiableIterator<T> forEnumeration(
- final Enumeration<T> enumeration) {
+ public static <T> UnmodifiableIterator<T> forEnumeration(final Enumeration<T> enumeration) {
checkNotNull(enumeration);
return new UnmodifiableIterator<T>() {
@Override
public boolean hasNext() {
return enumeration.hasMoreElements();
}
+
@Override
public T next() {
return enumeration.nextElement();
@@ -1089,6 +1111,7 @@ public final class Iterators {
public boolean hasMoreElements() {
return iterator.hasNext();
}
+
@Override
public T nextElement() {
return iterator.next();
@@ -1179,8 +1202,7 @@ public final class Iterators {
* additional {@link PeekingIterator#peek()} method, this iterator behaves
* exactly the same as {@code iterator}.
*/
- public static <T> PeekingIterator<T> peekingIterator(
- Iterator<? extends T> iterator) {
+ public static <T> PeekingIterator<T> peekingIterator(Iterator<? extends T> iterator) {
if (iterator instanceof PeekingImpl) {
// Safe to cast <? extends T> to <T> because PeekingImpl only uses T
// covariantly (and cannot be subclassed to add non-covariant uses).
@@ -1197,8 +1219,8 @@ public final class Iterators {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <T> PeekingIterator<T> peekingIterator(
- PeekingIterator<T> iterator) {
+ @Deprecated
+ public static <T> PeekingIterator<T> peekingIterator(PeekingIterator<T> iterator) {
return checkNotNull(iterator);
}
@@ -1217,8 +1239,7 @@ public final class Iterators {
*/
@Beta
public static <T> UnmodifiableIterator<T> mergeSorted(
- Iterable<? extends Iterator<? extends T>> iterators,
- Comparator<? super T> comparator) {
+ Iterable<? extends Iterator<? extends T>> iterators, Comparator<? super T> comparator) {
checkNotNull(iterators, "iterators");
checkNotNull(comparator, "comparator");
@@ -1237,7 +1258,8 @@ public final class Iterators {
private static class MergingIterator<T> extends UnmodifiableIterator<T> {
final Queue<PeekingIterator<T>> queue;
- public MergingIterator(Iterable<? extends Iterator<? extends T>> iterators,
+ public MergingIterator(
+ Iterable<? extends Iterator<? extends T>> iterators,
final Comparator<? super T> itemComparator) {
// A comparator that's used by the heap, allowing the heap
// to be sorted based on the top of each iterator.
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimap.java
index 1223678..5c9961c 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimap.java
@@ -22,6 +22,7 @@ import static com.google.common.collect.CollectPreconditions.checkRemove;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.Arrays;
import java.util.Collection;
@@ -67,12 +68,12 @@ import javax.annotation.Nullable;
* Multimaps#synchronizedSetMultimap}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
* {@code Multimap}</a>.
*
* @author Jared Levy
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
@@ -94,11 +95,9 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
* @throws IllegalArgumentException if {@code expectedKeys} or {@code
* expectedValuesPerKey} is negative
*/
- public static <K, V> LinkedHashMultimap<K, V> create(
- int expectedKeys, int expectedValuesPerKey) {
+ public static <K, V> LinkedHashMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
return new LinkedHashMultimap<K, V>(
- Maps.capacity(expectedKeys),
- Maps.capacity(expectedValuesPerKey));
+ Maps.capacity(expectedKeys), Maps.capacity(expectedValuesPerKey));
}
/**
@@ -119,9 +118,11 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
private interface ValueSetLink<K, V> {
ValueSetLink<K, V> getPredecessorInValueSet();
+
ValueSetLink<K, V> getSuccessorInValueSet();
void setPredecessorInValueSet(ValueSetLink<K, V> entry);
+
void setSuccessorInValueSet(ValueSetLink<K, V> entry);
}
@@ -130,8 +131,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
succ.setPredecessorInValueSet(pred);
}
- private static <K, V> void succeedsInMultimap(
- ValueEntry<K, V> pred, ValueEntry<K, V> succ) {
+ private static <K, V> void succeedsInMultimap(ValueEntry<K, V> pred, ValueEntry<K, V> succ) {
pred.setSuccessorInMultimap(succ);
succ.setPredecessorInMultimap(pred);
}
@@ -151,8 +151,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
* in the LinkedHashMultimap as a whole.
*/
@VisibleForTesting
- static final class ValueEntry<K, V> extends ImmutableEntry<K, V>
- implements ValueSetLink<K, V> {
+ static final class ValueEntry<K, V> extends ImmutableEntry<K, V> implements ValueSetLink<K, V> {
final int smearedValueHash;
@Nullable ValueEntry<K, V> nextInValueBucket;
@@ -163,13 +162,16 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
ValueEntry<K, V> predecessorInMultimap;
ValueEntry<K, V> successorInMultimap;
- ValueEntry(@Nullable K key, @Nullable V value, int smearedValueHash,
+ ValueEntry(
+ @Nullable K key,
+ @Nullable V value,
+ int smearedValueHash,
@Nullable ValueEntry<K, V> nextInValueBucket) {
super(key, value);
this.smearedValueHash = smearedValueHash;
this.nextInValueBucket = nextInValueBucket;
}
-
+
boolean matchesValue(@Nullable Object v, int smearedVHash) {
return smearedValueHash == smearedVHash && Objects.equal(getValue(), v);
}
@@ -280,7 +282,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
* multimap, taken at the time the entry is returned by a method call to the
* collection or its iterator.
*/
- @Override public Set<Map.Entry<K, V>> entries() {
+ @Override
+ public Set<Map.Entry<K, V>> entries() {
return super.entries();
}
@@ -291,11 +294,13 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
* <p>The iterator generated by the returned collection traverses the values
* in the order they were added to the multimap.
*/
- @Override public Collection<V> values() {
+ @Override
+ public Collection<V> values() {
return super.values();
}
@VisibleForTesting
+ @WeakOuter
final class ValueSet extends Sets.ImprovedAbstractSet<V> implements ValueSetLink<K, V> {
/*
* We currently use a fixed load factor of 1.0, a bit higher than normal to reduce memory
@@ -318,12 +323,12 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
this.lastEntry = this;
// Round expected values up to a power of 2 to get the table size.
int tableSize = Hashing.closedTableSize(expectedValues, VALUE_SET_LOAD_FACTOR);
-
+
@SuppressWarnings("unchecked")
ValueEntry<K, V>[] hashTable = new ValueEntry[tableSize];
this.hashTable = hashTable;
}
-
+
private int mask() {
return hashTable.length - 1;
}
@@ -398,7 +403,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
@Override
public boolean contains(@Nullable Object o) {
int smearedHash = Hashing.smearedHash(o);
- for (ValueEntry<K, V> entry = hashTable[smearedHash & mask()]; entry != null;
+ for (ValueEntry<K, V> entry = hashTable[smearedHash & mask()];
+ entry != null;
entry = entry.nextInValueBucket) {
if (entry.matchesValue(o, smearedHash)) {
return true;
@@ -412,8 +418,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
int smearedHash = Hashing.smearedHash(value);
int bucket = smearedHash & mask();
ValueEntry<K, V> rowHead = hashTable[bucket];
- for (ValueEntry<K, V> entry = rowHead; entry != null;
- entry = entry.nextInValueBucket) {
+ for (ValueEntry<K, V> entry = rowHead; entry != null; entry = entry.nextInValueBucket) {
if (entry.matchesValue(value, smearedHash)) {
return false;
}
@@ -438,7 +443,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
this.hashTable = hashTable;
int mask = hashTable.length - 1;
for (ValueSetLink<K, V> entry = firstEntry;
- entry != this; entry = entry.getSuccessorInValueSet()) {
+ entry != this;
+ entry = entry.getSuccessorInValueSet()) {
ValueEntry<K, V> valueEntry = (ValueEntry<K, V>) entry;
int bucket = valueEntry.smearedValueHash & mask;
valueEntry.nextInValueBucket = hashTable[bucket];
@@ -452,8 +458,9 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
int smearedHash = Hashing.smearedHash(o);
int bucket = smearedHash & mask();
ValueEntry<K, V> prev = null;
- for (ValueEntry<K, V> entry = hashTable[bucket]; entry != null;
- prev = entry, entry = entry.nextInValueBucket) {
+ for (ValueEntry<K, V> entry = hashTable[bucket];
+ entry != null;
+ prev = entry, entry = entry.nextInValueBucket) {
if (entry.matchesValue(o, smearedHash)) {
if (prev == null) {
// first entry in the bucket
@@ -476,7 +483,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
Arrays.fill(hashTable, null);
size = 0;
for (ValueSetLink<K, V> entry = firstEntry;
- entry != this; entry = entry.getSuccessorInValueSet()) {
+ entry != this;
+ entry = entry.getSuccessorInValueSet()) {
ValueEntry<K, V> valueEntry = (ValueEntry<K, V>) entry;
deleteFromMultimap(valueEntry);
}
@@ -515,7 +523,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
}
};
}
-
+
@Override
Iterator<V> valueIterator() {
return Maps.valueIterator(entryIterator());
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultiset.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultiset.java
index da93ead..3259636 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultiset.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultiset.java
@@ -27,14 +27,14 @@ import java.util.LinkedHashMap;
* element, those instances are consecutive in the iteration order. If all
* occurrences of an element are removed, after which that element is added to
* the multiset, the element will appear at the end of the iteration.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
* {@code Multiset}</a>.
*
* @author Kevin Bourrillion
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
@@ -67,10 +67,8 @@ public final class LinkedHashMultiset<E> extends AbstractMapBasedMultiset<E> {
*
* @param elements the elements that the multiset should contain
*/
- public static <E> LinkedHashMultiset<E> create(
- Iterable<? extends E> elements) {
- LinkedHashMultiset<E> multiset =
- create(Multisets.inferDistinctElements(elements));
+ public static <E> LinkedHashMultiset<E> create(Iterable<? extends E> elements) {
+ LinkedHashMultiset<E> multiset = create(Multisets.inferDistinctElements(elements));
Iterables.addAll(multiset, elements);
return multiset;
}
@@ -80,8 +78,7 @@ public final class LinkedHashMultiset<E> extends AbstractMapBasedMultiset<E> {
}
private LinkedHashMultiset(int distinctElements) {
- // Could use newLinkedHashMapWithExpectedSize() if it existed
- super(new LinkedHashMap<E, Count>(Maps.capacity(distinctElements)));
+ super(Maps.<E, Count>newLinkedHashMapWithExpectedSize(distinctElements));
}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimap.java
index f648b51..3ac726f 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimap.java
@@ -22,6 +22,7 @@ import static com.google.common.collect.CollectPreconditions.checkRemove;
import static java.util.Collections.unmodifiableList;
import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.AbstractSequentialList;
@@ -88,11 +89,11 @@ import javax.annotation.Nullable;
* Multimaps#synchronizedListMultimap}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
* {@code Multimap}</a>.
*
* @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
@@ -134,12 +135,12 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
return result;
}
}
-
+
private static class KeyList<K, V> {
Node<K, V> head;
Node<K, V> tail;
int count;
-
+
KeyList(Node<K, V> firstNode) {
this.head = firstNode;
this.tail = firstNode;
@@ -153,7 +154,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
private transient Node<K, V> tail; // the tail for all keys
private transient Map<K, KeyList<K, V>> keyToKeyList;
private transient int size;
-
+
/*
* Tracks modifications to keyToKeyList so that addition or removal of keys invalidates
* preexisting iterators. This does *not* track simple additions and removals of values
@@ -211,8 +212,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
* nextSibling} is null. Note: if {@code nextSibling} is specified, it MUST be
* for an node for the same {@code key}!
*/
- private Node<K, V> addNode(
- @Nullable K key, @Nullable V value, @Nullable Node<K, V> nextSibling) {
+ private Node<K, V> addNode(@Nullable K key, @Nullable V value, @Nullable Node<K, V> nextSibling) {
Node<K, V> node = new Node<K, V>(key, value);
if (head == null) { // empty list
head = tail = node;
@@ -286,7 +286,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
} else {
node.previousSibling.nextSibling = node.nextSibling;
}
-
+
if (node.nextSibling == null) {
keyList.tail = node.previousSibling;
} else {
@@ -333,16 +333,19 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
}
current = null;
}
+
private void checkForConcurrentModification() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
+
@Override
public boolean hasNext() {
checkForConcurrentModification();
return next != null;
}
+
@Override
public Node<K, V> next() {
checkForConcurrentModification();
@@ -352,6 +355,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
nextIndex++;
return current;
}
+
@Override
public void remove() {
checkForConcurrentModification();
@@ -366,11 +370,13 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
current = null;
expectedModCount = modCount;
}
+
@Override
public boolean hasPrevious() {
checkForConcurrentModification();
return previous != null;
}
+
@Override
public Node<K, V> previous() {
checkForConcurrentModification();
@@ -380,22 +386,27 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
nextIndex--;
return current;
}
+
@Override
public int nextIndex() {
return nextIndex;
}
+
@Override
public int previousIndex() {
return nextIndex - 1;
}
+
@Override
public void set(Entry<K, V> e) {
throw new UnsupportedOperationException();
}
+
@Override
public void add(Entry<K, V> e) {
throw new UnsupportedOperationException();
}
+
void setValue(V value) {
checkState(current != null);
current.value = value;
@@ -408,17 +419,19 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
Node<K, V> next = head;
Node<K, V> current;
int expectedModCount = modCount;
-
+
private void checkForConcurrentModification() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
+
@Override
public boolean hasNext() {
checkForConcurrentModification();
return next != null;
}
+
@Override
public K next() {
checkForConcurrentModification();
@@ -430,6 +443,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
} while ((next != null) && !seenKeys.add(next.key));
return current.key;
}
+
@Override
public void remove() {
checkForConcurrentModification();
@@ -665,11 +679,14 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
@Override
public List<V> get(final @Nullable K key) {
return new AbstractSequentialList<V>() {
- @Override public int size() {
+ @Override
+ public int size() {
KeyList<K, V> keyList = keyToKeyList.get(key);
return (keyList == null) ? 0 : keyList.count;
}
- @Override public ListIterator<V> listIterator(int index) {
+
+ @Override
+ public ListIterator<V> listIterator(int index) {
return new ValueForKeyIterator(key, index);
}
};
@@ -677,21 +694,29 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
@Override
Set<K> createKeySet() {
- return new Sets.ImprovedAbstractSet<K>() {
- @Override public int size() {
+ @WeakOuter
+ class KeySetImpl extends Sets.ImprovedAbstractSet<K> {
+ @Override
+ public int size() {
return keyToKeyList.size();
}
- @Override public Iterator<K> iterator() {
+
+ @Override
+ public Iterator<K> iterator() {
return new DistinctKeyIterator();
}
- @Override public boolean contains(Object key) { // for performance
+
+ @Override
+ public boolean contains(Object key) { // for performance
return containsKey(key);
}
+
@Override
public boolean remove(Object o) { // for performance
return !LinkedListMultimap.this.removeAll(o).isEmpty();
}
- };
+ }
+ return new KeySetImpl();
}
/**
@@ -710,12 +735,15 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
@Override
List<V> createValues() {
- return new AbstractSequentialList<V>() {
- @Override public int size() {
+ @WeakOuter
+ class ValuesImpl extends AbstractSequentialList<V> {
+ @Override
+ public int size() {
return size;
}
- @Override public ListIterator<V> listIterator(int index) {
+ @Override
+ public ListIterator<V> listIterator(int index) {
final NodeIterator nodeItr = new NodeIterator(index);
return new TransformedListIterator<Entry<K, V>, V>(nodeItr) {
@Override
@@ -729,7 +757,8 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
}
};
}
- };
+ }
+ return new ValuesImpl();
}
/**
@@ -757,15 +786,19 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
@Override
List<Entry<K, V>> createEntries() {
- return new AbstractSequentialList<Entry<K, V>>() {
- @Override public int size() {
+ @WeakOuter
+ class EntriesImpl extends AbstractSequentialList<Entry<K, V>> {
+ @Override
+ public int size() {
return size;
}
- @Override public ListIterator<Entry<K, V>> listIterator(int index) {
+ @Override
+ public ListIterator<Entry<K, V>> listIterator(int index) {
return new NodeIterator(index);
}
- };
+ }
+ return new EntriesImpl();
}
@Override
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Lists.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Lists.java
index 74e9606..ab30fa5 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Lists.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Lists.java
@@ -48,6 +48,7 @@ import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.RandomAccess;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -55,13 +56,13 @@ import javax.annotation.Nullable;
* class's counterparts {@link Sets}, {@link Maps} and {@link Queues}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Lists">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#lists">
* {@code Lists}</a>.
*
* @author Kevin Bourrillion
* @author Mike Bostock
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Lists {
@@ -113,7 +114,8 @@ public final class Lists {
return list;
}
- @VisibleForTesting static int computeArrayListCapacity(int arraySize) {
+ @VisibleForTesting
+ static int computeArrayListCapacity(int arraySize) {
checkNonnegative(arraySize, "arraySize");
// TODO(kevinb): Figure out the right behavior, and document it
@@ -178,8 +180,7 @@ public final class Lists {
* @throws IllegalArgumentException if {@code initialArraySize} is negative
*/
@GwtCompatible(serializable = true)
- public static <E> ArrayList<E> newArrayListWithCapacity(
- int initialArraySize) {
+ public static <E> ArrayList<E> newArrayListWithCapacity(int initialArraySize) {
checkNonnegative(initialArraySize, "initialArraySize"); // for GWT.
return new ArrayList<E>(initialArraySize);
}
@@ -201,8 +202,7 @@ public final class Lists {
* @throws IllegalArgumentException if {@code estimatedSize} is negative
*/
@GwtCompatible(serializable = true)
- public static <E> ArrayList<E> newArrayListWithExpectedSize(
- int estimatedSize) {
+ public static <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) {
return new ArrayList<E>(computeArrayListCapacity(estimatedSize));
}
@@ -251,8 +251,7 @@ public final class Lists {
* advantage of the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
*/
@GwtCompatible(serializable = true)
- public static <E> LinkedList<E> newLinkedList(
- Iterable<? extends E> elements) {
+ public static <E> LinkedList<E> newLinkedList(Iterable<? extends E> elements) {
LinkedList<E> list = newLinkedList();
Iterables.addAll(list, elements);
return list;
@@ -288,14 +287,19 @@ public final class Lists {
this.first = first;
this.rest = checkNotNull(rest);
}
- @Override public int size() {
+
+ @Override
+ public int size() {
return rest.length + 1;
}
- @Override public E get(int index) {
+
+ @Override
+ public E get(int index) {
// check explicitly so the IOOBE will have the right message
checkElementIndex(index, size());
return (index == 0) ? first : rest[index - 1];
}
+
private static final long serialVersionUID = 0;
}
@@ -316,8 +320,7 @@ public final class Lists {
* @param rest an array of additional elements, possibly empty
* @return an unmodifiable list containing the specified elements
*/
- public static <E> List<E> asList(
- @Nullable E first, @Nullable E second, E[] rest) {
+ public static <E> List<E> asList(@Nullable E first, @Nullable E second, E[] rest) {
return new TwoPlusArrayList<E>(first, second, rest);
}
@@ -333,10 +336,14 @@ public final class Lists {
this.second = second;
this.rest = checkNotNull(rest);
}
- @Override public int size() {
+
+ @Override
+ public int size() {
return rest.length + 2;
}
- @Override public E get(int index) {
+
+ @Override
+ public E get(int index) {
switch (index) {
case 0:
return first;
@@ -348,6 +355,7 @@ public final class Lists {
return rest[index - 2];
}
}
+
private static final long serialVersionUID = 0;
}
@@ -406,8 +414,9 @@ public final class Lists {
* be greater than {@link Integer#MAX_VALUE}
* @throws NullPointerException if {@code lists}, any one of the {@code lists},
* or any element of a provided list is null
- */ static <B> List<List<B>>
- cartesianProduct(List<? extends List<? extends B>> lists) {
+ * @since 19.0
+ */
+ public static <B> List<List<B>> cartesianProduct(List<? extends List<? extends B>> lists) {
return CartesianList.create(lists);
}
@@ -466,8 +475,9 @@ public final class Lists {
* be greater than {@link Integer#MAX_VALUE}
* @throws NullPointerException if {@code lists}, any one of the
* {@code lists}, or any element of a provided list is null
- */ static <B> List<List<B>>
- cartesianProduct(List<? extends B>... lists) {
+ * @since 19.0
+ */
+ public static <B> List<List<B>> cartesianProduct(List<? extends B>... lists) {
return cartesianProduct(Arrays.asList(lists));
}
@@ -504,6 +514,7 @@ public final class Lists {
* then serialize the copy. Other methods similar to this do not implement
* serialization at all for this reason.
*/
+ @CheckReturnValue
public static <F, T> List<T> transform(
List<F> fromList, Function<? super F, ? extends T> function) {
return (fromList instanceof RandomAccess)
@@ -516,13 +527,12 @@ public final class Lists {
*
* @see Lists#transform
*/
- private static class TransformingSequentialList<F, T>
- extends AbstractSequentialList<T> implements Serializable {
+ private static class TransformingSequentialList<F, T> extends AbstractSequentialList<T>
+ implements Serializable {
final List<F> fromList;
final Function<? super F, ? extends T> function;
- TransformingSequentialList(
- List<F> fromList, Function<? super F, ? extends T> function) {
+ TransformingSequentialList(List<F> fromList, Function<? super F, ? extends T> function) {
this.fromList = checkNotNull(fromList);
this.function = checkNotNull(function);
}
@@ -531,13 +541,18 @@ public final class Lists {
* each element which can be overkill. That's why we forward this call
* directly to the backing list.
*/
- @Override public void clear() {
+ @Override
+ public void clear() {
fromList.clear();
}
- @Override public int size() {
+
+ @Override
+ public int size() {
return fromList.size();
}
- @Override public ListIterator<T> listIterator(final int index) {
+
+ @Override
+ public ListIterator<T> listIterator(final int index) {
return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
@Override
T transform(F from) {
@@ -557,26 +572,33 @@ public final class Lists {
*
* @see Lists#transform
*/
- private static class TransformingRandomAccessList<F, T>
- extends AbstractList<T> implements RandomAccess, Serializable {
+ private static class TransformingRandomAccessList<F, T> extends AbstractList<T>
+ implements RandomAccess, Serializable {
final List<F> fromList;
final Function<? super F, ? extends T> function;
- TransformingRandomAccessList(
- List<F> fromList, Function<? super F, ? extends T> function) {
+ TransformingRandomAccessList(List<F> fromList, Function<? super F, ? extends T> function) {
this.fromList = checkNotNull(fromList);
this.function = checkNotNull(function);
}
- @Override public void clear() {
+
+ @Override
+ public void clear() {
fromList.clear();
}
- @Override public T get(int index) {
+
+ @Override
+ public T get(int index) {
return function.apply(fromList.get(index));
}
- @Override public Iterator<T> iterator() {
+
+ @Override
+ public Iterator<T> iterator() {
return listIterator();
}
- @Override public ListIterator<T> listIterator(int index) {
+
+ @Override
+ public ListIterator<T> listIterator(int index) {
return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
@Override
T transform(F from) {
@@ -584,15 +606,22 @@ public final class Lists {
}
};
}
- @Override public boolean isEmpty() {
+
+ @Override
+ public boolean isEmpty() {
return fromList.isEmpty();
}
- @Override public T remove(int index) {
+
+ @Override
+ public T remove(int index) {
return function.apply(fromList.remove(index));
}
- @Override public int size() {
+
+ @Override
+ public int size() {
return fromList.size();
}
+
private static final long serialVersionUID = 0;
}
@@ -631,24 +660,26 @@ public final class Lists {
this.size = size;
}
- @Override public List<T> get(int index) {
+ @Override
+ public List<T> get(int index) {
checkElementIndex(index, size());
int start = index * size;
int end = Math.min(start + size, list.size());
return list.subList(start, end);
}
- @Override public int size() {
+ @Override
+ public int size() {
return IntMath.divide(list.size(), size, RoundingMode.CEILING);
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return list.isEmpty();
}
}
- private static class RandomAccessPartition<T> extends Partition<T>
- implements RandomAccess {
+ private static class RandomAccessPartition<T> extends Partition<T> implements RandomAccess {
RandomAccessPartition(List<T> list, int size) {
super(list, size);
}
@@ -660,13 +691,13 @@ public final class Lists {
*
* @since 7.0
*/
- @Beta public static ImmutableList<Character> charactersOf(String string) {
+ @Beta
+ public static ImmutableList<Character> charactersOf(String string) {
return new StringAsImmutableList(checkNotNull(string));
}
@SuppressWarnings("serial") // serialized using ImmutableList serialization
- private static final class StringAsImmutableList
- extends ImmutableList<Character> {
+ private static final class StringAsImmutableList extends ImmutableList<Character> {
private final String string;
@@ -674,32 +705,35 @@ public final class Lists {
this.string = string;
}
- @Override public int indexOf(@Nullable Object object) {
- return (object instanceof Character)
- ? string.indexOf((Character) object) : -1;
+ @Override
+ public int indexOf(@Nullable Object object) {
+ return (object instanceof Character) ? string.indexOf((Character) object) : -1;
}
- @Override public int lastIndexOf(@Nullable Object object) {
- return (object instanceof Character)
- ? string.lastIndexOf((Character) object) : -1;
+ @Override
+ public int lastIndexOf(@Nullable Object object) {
+ return (object instanceof Character) ? string.lastIndexOf((Character) object) : -1;
}
- @Override public ImmutableList<Character> subList(
- int fromIndex, int toIndex) {
+ @Override
+ public ImmutableList<Character> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, size()); // for GWT
return charactersOf(string.substring(fromIndex, toIndex));
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return false;
}
- @Override public Character get(int index) {
+ @Override
+ public Character get(int index) {
checkElementIndex(index, size()); // for GWT
return string.charAt(index);
}
- @Override public int size() {
+ @Override
+ public int size() {
return string.length();
}
}
@@ -715,24 +749,26 @@ public final class Lists {
* @return an {@code List<Character>} view of the character sequence
* @since 7.0
*/
- @Beta public static List<Character> charactersOf(CharSequence sequence) {
+ @Beta
+ public static List<Character> charactersOf(CharSequence sequence) {
return new CharSequenceAsList(checkNotNull(sequence));
}
- private static final class CharSequenceAsList
- extends AbstractList<Character> {
+ private static final class CharSequenceAsList extends AbstractList<Character> {
private final CharSequence sequence;
CharSequenceAsList(CharSequence sequence) {
this.sequence = sequence;
}
- @Override public Character get(int index) {
+ @Override
+ public Character get(int index) {
checkElementIndex(index, size()); // for GWT
return sequence.charAt(index);
}
- @Override public int size() {
+ @Override
+ public int size() {
return sequence.length();
}
}
@@ -749,6 +785,7 @@ public final class Lists {
*
* @since 7.0
*/
+ @CheckReturnValue
public static <T> List<T> reverse(List<T> list) {
if (list instanceof ImmutableList) {
return ((ImmutableList<T>) list).reverse();
@@ -784,66 +821,79 @@ public final class Lists {
return size - index;
}
- @Override public void add(int index, @Nullable T element) {
+ @Override
+ public void add(int index, @Nullable T element) {
forwardList.add(reversePosition(index), element);
}
- @Override public void clear() {
+ @Override
+ public void clear() {
forwardList.clear();
}
- @Override public T remove(int index) {
+ @Override
+ public T remove(int index) {
return forwardList.remove(reverseIndex(index));
}
- @Override protected void removeRange(int fromIndex, int toIndex) {
+ @Override
+ protected void removeRange(int fromIndex, int toIndex) {
subList(fromIndex, toIndex).clear();
}
- @Override public T set(int index, @Nullable T element) {
+ @Override
+ public T set(int index, @Nullable T element) {
return forwardList.set(reverseIndex(index), element);
}
- @Override public T get(int index) {
+ @Override
+ public T get(int index) {
return forwardList.get(reverseIndex(index));
}
- @Override public int size() {
+ @Override
+ public int size() {
return forwardList.size();
}
- @Override public List<T> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<T> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, size());
- return reverse(forwardList.subList(
- reversePosition(toIndex), reversePosition(fromIndex)));
+ return reverse(forwardList.subList(reversePosition(toIndex), reversePosition(fromIndex)));
}
- @Override public Iterator<T> iterator() {
+ @Override
+ public Iterator<T> iterator() {
return listIterator();
}
- @Override public ListIterator<T> listIterator(int index) {
+ @Override
+ public ListIterator<T> listIterator(int index) {
int start = reversePosition(index);
final ListIterator<T> forwardIterator = forwardList.listIterator(start);
return new ListIterator<T>() {
boolean canRemoveOrSet;
- @Override public void add(T e) {
+ @Override
+ public void add(T e) {
forwardIterator.add(e);
forwardIterator.previous();
canRemoveOrSet = false;
}
- @Override public boolean hasNext() {
+ @Override
+ public boolean hasNext() {
return forwardIterator.hasPrevious();
}
- @Override public boolean hasPrevious() {
+ @Override
+ public boolean hasPrevious() {
return forwardIterator.hasNext();
}
- @Override public T next() {
+ @Override
+ public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
@@ -851,11 +901,13 @@ public final class Lists {
return forwardIterator.previous();
}
- @Override public int nextIndex() {
+ @Override
+ public int nextIndex() {
return reversePosition(forwardIterator.nextIndex());
}
- @Override public T previous() {
+ @Override
+ public T previous() {
if (!hasPrevious()) {
throw new NoSuchElementException();
}
@@ -863,17 +915,20 @@ public final class Lists {
return forwardIterator.next();
}
- @Override public int previousIndex() {
+ @Override
+ public int previousIndex() {
return nextIndex() - 1;
}
- @Override public void remove() {
+ @Override
+ public void remove() {
checkRemove(canRemoveOrSet);
forwardIterator.remove();
canRemoveOrSet = false;
}
- @Override public void set(T e) {
+ @Override
+ public void set(T e) {
checkState(canRemoveOrSet);
forwardIterator.set(e);
}
@@ -881,8 +936,7 @@ public final class Lists {
}
}
- private static class RandomAccessReverseList<T> extends ReverseList<T>
- implements RandomAccess {
+ private static class RandomAccessReverseList<T> extends ReverseList<T> implements RandomAccess {
RandomAccessReverseList(List<T> forwardList) {
super(forwardList);
}
@@ -892,7 +946,7 @@ public final class Lists {
* An implementation of {@link List#hashCode()}.
*/
static int hashCodeImpl(List<?> list) {
- // TODO(user): worth optimizing for RandomAccess?
+ // TODO(lowasser): worth optimizing for RandomAccess?
int hashCode = 1;
for (Object o : list) {
hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
@@ -906,25 +960,35 @@ public final class Lists {
/**
* An implementation of {@link List#equals(Object)}.
*/
- static boolean equalsImpl(List<?> list, @Nullable Object object) {
- if (object == checkNotNull(list)) {
+ static boolean equalsImpl(List<?> thisList, @Nullable Object other) {
+ if (other == checkNotNull(thisList)) {
return true;
}
- if (!(object instanceof List)) {
+ if (!(other instanceof List)) {
return false;
}
-
- List<?> o = (List<?>) object;
-
- return list.size() == o.size()
- && Iterators.elementsEqual(list.iterator(), o.iterator());
+ List<?> otherList = (List<?>) other;
+ int size = thisList.size();
+ if (size != otherList.size()) {
+ return false;
+ }
+ if (thisList instanceof RandomAccess && otherList instanceof RandomAccess) {
+ // avoid allocation and use the faster loop
+ for (int i = 0; i < size; i++) {
+ if (!Objects.equal(thisList.get(i), otherList.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return Iterators.elementsEqual(thisList.iterator(), otherList.iterator());
+ }
}
/**
* An implementation of {@link List#addAll(int, Collection)}.
*/
- static <E> boolean addAllImpl(
- List<E> list, int index, Iterable<? extends E> elements) {
+ static <E> boolean addAllImpl(List<E> list, int index, Iterable<? extends E> elements) {
boolean changed = false;
ListIterator<E> listIterator = list.listIterator(index);
for (E e : elements) {
@@ -938,10 +1002,32 @@ public final class Lists {
* An implementation of {@link List#indexOf(Object)}.
*/
static int indexOfImpl(List<?> list, @Nullable Object element) {
- ListIterator<?> listIterator = list.listIterator();
- while (listIterator.hasNext()) {
- if (Objects.equal(element, listIterator.next())) {
- return listIterator.previousIndex();
+ if (list instanceof RandomAccess) {
+ return indexOfRandomAccess(list, element);
+ } else {
+ ListIterator<?> listIterator = list.listIterator();
+ while (listIterator.hasNext()) {
+ if (Objects.equal(element, listIterator.next())) {
+ return listIterator.previousIndex();
+ }
+ }
+ return -1;
+ }
+ }
+
+ private static int indexOfRandomAccess(List<?> list, @Nullable Object element) {
+ int size = list.size();
+ if (element == null) {
+ for (int i = 0; i < size; i++) {
+ if (list.get(i) == null) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = 0; i < size; i++) {
+ if (element.equals(list.get(i))) {
+ return i;
+ }
}
}
return -1;
@@ -951,10 +1037,31 @@ public final class Lists {
* An implementation of {@link List#lastIndexOf(Object)}.
*/
static int lastIndexOfImpl(List<?> list, @Nullable Object element) {
- ListIterator<?> listIterator = list.listIterator(list.size());
- while (listIterator.hasPrevious()) {
- if (Objects.equal(element, listIterator.previous())) {
- return listIterator.nextIndex();
+ if (list instanceof RandomAccess) {
+ return lastIndexOfRandomAccess(list, element);
+ } else {
+ ListIterator<?> listIterator = list.listIterator(list.size());
+ while (listIterator.hasPrevious()) {
+ if (Objects.equal(element, listIterator.previous())) {
+ return listIterator.nextIndex();
+ }
+ }
+ return -1;
+ }
+ }
+
+ private static int lastIndexOfRandomAccess(List<?> list, @Nullable Object element) {
+ if (element == null) {
+ for (int i = list.size() - 1; i >= 0; i--) {
+ if (list.get(i) == null) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = list.size() - 1; i >= 0; i--) {
+ if (element.equals(list.get(i))) {
+ return i;
+ }
}
}
return -1;
@@ -970,12 +1077,12 @@ public final class Lists {
/**
* An implementation of {@link List#subList(int, int)}.
*/
- static <E> List<E> subListImpl(
- final List<E> list, int fromIndex, int toIndex) {
+ static <E> List<E> subListImpl(final List<E> list, int fromIndex, int toIndex) {
List<E> wrapper;
if (list instanceof RandomAccess) {
wrapper = new RandomAccessListWrapper<E>(list) {
- @Override public ListIterator<E> listIterator(int index) {
+ @Override
+ public ListIterator<E> listIterator(int index) {
return backingList.listIterator(index);
}
@@ -983,7 +1090,8 @@ public final class Lists {
};
} else {
wrapper = new AbstractListWrapper<E>(list) {
- @Override public ListIterator<E> listIterator(int index) {
+ @Override
+ public ListIterator<E> listIterator(int index) {
return backingList.listIterator(index);
}
@@ -1000,37 +1108,44 @@ public final class Lists {
this.backingList = checkNotNull(backingList);
}
- @Override public void add(int index, E element) {
+ @Override
+ public void add(int index, E element) {
backingList.add(index, element);
}
- @Override public boolean addAll(int index, Collection<? extends E> c) {
+ @Override
+ public boolean addAll(int index, Collection<? extends E> c) {
return backingList.addAll(index, c);
}
- @Override public E get(int index) {
+ @Override
+ public E get(int index) {
return backingList.get(index);
}
- @Override public E remove(int index) {
+ @Override
+ public E remove(int index) {
return backingList.remove(index);
}
- @Override public E set(int index, E element) {
+ @Override
+ public E set(int index, E element) {
return backingList.set(index, element);
}
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
return backingList.contains(o);
}
- @Override public int size() {
+ @Override
+ public int size() {
return backingList.size();
}
}
- private static class RandomAccessListWrapper<E>
- extends AbstractListWrapper<E> implements RandomAccess {
+ private static class RandomAccessListWrapper<E> extends AbstractListWrapper<E>
+ implements RandomAccess {
RandomAccessListWrapper(List<E> backingList) {
super(backingList);
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/MapMaker.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/MapMaker.java
index ac4c06a..69abc79 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/MapMaker.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/MapMaker.java
@@ -33,7 +33,7 @@ import java.util.concurrent.TimeUnit;
*/
public final class MapMaker extends GenericMapMaker<Object, Object> {
- // TODO(fry,user): ConcurrentHashMap never throws a CME when mutating the map during iteration, but
+ // TODO(fry,kak): ConcurrentHashMap never throws a CME when mutating the map during iteration, but
// this implementation (based on a LHM) does. This will all be replaced soon anyways, so leaving
// it as is for now.
private static class ExpiringComputingMap<K, V> extends LinkedHashMap<K, V>
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Maps.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Maps.java
index f5d84ae..e9e046a 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Maps.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Maps.java
@@ -36,6 +36,8 @@ import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.MapDifference.ValueDifference;
import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.AbstractCollection;
@@ -56,6 +58,7 @@ import java.util.SortedSet;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentMap;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -64,14 +67,14 @@ import javax.annotation.Nullable;
* {@link Lists}, {@link Sets} and {@link Queues}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Maps">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#maps">
* {@code Maps}</a>.
*
* @author Kevin Bourrillion
* @author Mike Bostock
* @author Isaac Shum
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Maps {
@@ -112,21 +115,6 @@ public final class Maps {
return Iterators.transform(entryIterator, Maps.<V>valueFunction());
}
- static <K, V> UnmodifiableIterator<V> valueIterator(
- final UnmodifiableIterator<Entry<K, V>> entryIterator) {
- return new UnmodifiableIterator<V>() {
- @Override
- public boolean hasNext() {
- return entryIterator.hasNext();
- }
-
- @Override
- public V next() {
- return entryIterator.next().getValue();
- }
- };
- }
-
/**
* Returns an immutable map instance containing the given entries.
* Internally, the returned map will be backed by an {@link EnumMap}.
@@ -176,17 +164,16 @@ public final class Maps {
* Creates a {@code HashMap} instance, with a high enough "initial capacity"
* that it <i>should</i> hold {@code expectedSize} elements without growth.
* This behavior cannot be broadly guaranteed, but it is observed to be true
- * for OpenJDK 1.6. It also can't be guaranteed that the method isn't
+ * for OpenJDK 1.7. It also can't be guaranteed that the method isn't
* inadvertently <i>oversizing</i> the returned map.
*
- * @param expectedSize the number of elements you expect to add to the
+ * @param expectedSize the number of entries you expect to add to the
* returned map
* @return a new, empty {@code HashMap} with enough capacity to hold {@code
- * expectedSize} elements without resizing
+ * expectedSize} entries without resizing
* @throws IllegalArgumentException if {@code expectedSize} is negative
*/
- public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(
- int expectedSize) {
+ public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(int expectedSize) {
return new HashMap<K, V>(capacity(expectedSize));
}
@@ -201,7 +188,10 @@ public final class Maps {
return expectedSize + 1;
}
if (expectedSize < Ints.MAX_POWER_OF_TWO) {
- return expectedSize + expectedSize / 3;
+ // This is the calculation used in JDK8 to resize when a putAll
+ // happens; it seems to be the most conservative calculation we
+ // can make. 0.75 is the default load factor.
+ return (int) ((float) expectedSize / 0.75F + 1.0F);
}
return Integer.MAX_VALUE; // any large value
}
@@ -220,8 +210,7 @@ public final class Maps {
* @return a new {@code HashMap} initialized with the mappings from {@code
* map}
*/
- public static <K, V> HashMap<K, V> newHashMap(
- Map<? extends K, ? extends V> map) {
+ public static <K, V> HashMap<K, V> newHashMap(Map<? extends K, ? extends V> map) {
return new HashMap<K, V>(map);
}
@@ -239,6 +228,24 @@ public final class Maps {
}
/**
+ * Creates a {@code LinkedHashMap} instance, with a high enough
+ * "initial capacity" that it <i>should</i> hold {@code expectedSize}
+ * elements without growth. This behavior cannot be broadly guaranteed, but
+ * it is observed to be true for OpenJDK 1.7. It also can't be guaranteed
+ * that the method isn't inadvertently <i>oversizing</i> the returned map.
+ *
+ * @param expectedSize the number of entries you expect to add to the
+ * returned map
+ * @return a new, empty {@code LinkedHashMap} with enough capacity to hold
+ * {@code expectedSize} entries without resizing
+ * @throws IllegalArgumentException if {@code expectedSize} is negative
+ * @since 19.0
+ */
+ public static <K, V> LinkedHashMap<K, V> newLinkedHashMapWithExpectedSize(int expectedSize) {
+ return new LinkedHashMap<K, V>(capacity(expectedSize));
+ }
+
+ /**
* Creates a <i>mutable</i>, insertion-ordered {@code LinkedHashMap} instance
* with the same mappings as the specified map.
*
@@ -249,8 +256,7 @@ public final class Maps {
* @return a new, {@code LinkedHashMap} initialized with the mappings from
* {@code map}
*/
- public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(
- Map<? extends K, ? extends V> map) {
+ public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(Map<? extends K, ? extends V> map) {
return new LinkedHashMap<K, V>(map);
}
@@ -312,8 +318,7 @@ public final class Maps {
* @param comparator the comparator to sort the keys with
* @return a new, empty {@code TreeMap}
*/
- public static <C, K extends C, V> TreeMap<K, V> newTreeMap(
- @Nullable Comparator<C> comparator) {
+ public static <C, K extends C, V> TreeMap<K, V> newTreeMap(@Nullable Comparator<C> comparator) {
// Ideally, the extra type parameter "C" shouldn't be necessary. It is a
// work-around of a compiler type inference quirk that prevents the
// following code from being compiled:
@@ -341,8 +346,7 @@ public final class Maps {
* @throws IllegalArgumentException if {@code m} is not an {@code EnumMap}
* instance and contains no mappings
*/
- public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(
- Map<K, ? extends V> map) {
+ public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(Map<K, ? extends V> map) {
return new EnumMap<K, V>(map);
}
@@ -403,22 +407,26 @@ public final class Maps {
*/
@Beta
public static <K, V> MapDifference<K, V> difference(
- Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right,
+ Map<? extends K, ? extends V> left,
+ Map<? extends K, ? extends V> right,
Equivalence<? super V> valueEquivalence) {
Preconditions.checkNotNull(valueEquivalence);
- Map<K, V> onlyOnLeft = newHashMap();
- Map<K, V> onlyOnRight = new HashMap<K, V>(right); // will whittle it down
- Map<K, V> onBoth = newHashMap();
- Map<K, MapDifference.ValueDifference<V>> differences = newHashMap();
+ Map<K, V> onlyOnLeft = newLinkedHashMap();
+ Map<K, V> onlyOnRight = new LinkedHashMap<K, V>(right); // will whittle it down
+ Map<K, V> onBoth = newLinkedHashMap();
+ Map<K, MapDifference.ValueDifference<V>> differences = newLinkedHashMap();
doDifference(left, right, valueEquivalence, onlyOnLeft, onlyOnRight, onBoth, differences);
return new MapDifferenceImpl<K, V>(onlyOnLeft, onlyOnRight, onBoth, differences);
}
private static <K, V> void doDifference(
- Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right,
+ Map<? extends K, ? extends V> left,
+ Map<? extends K, ? extends V> right,
Equivalence<? super V> valueEquivalence,
- Map<K, V> onlyOnLeft, Map<K, V> onlyOnRight, Map<K, V> onBoth,
+ Map<K, V> onlyOnLeft,
+ Map<K, V> onlyOnRight,
+ Map<K, V> onBoth,
Map<K, MapDifference.ValueDifference<V>> differences) {
for (Entry<? extends K, ? extends V> entry : left.entrySet()) {
K leftKey = entry.getKey();
@@ -428,8 +436,7 @@ public final class Maps {
if (valueEquivalence.equivalent(leftValue, rightValue)) {
onBoth.put(leftKey, leftValue);
} else {
- differences.put(
- leftKey, ValueDifferenceImpl.create(leftValue, rightValue));
+ differences.put(leftKey, ValueDifferenceImpl.create(leftValue, rightValue));
}
} else {
onlyOnLeft.put(leftKey, leftValue);
@@ -451,8 +458,10 @@ public final class Maps {
final Map<K, V> onBoth;
final Map<K, ValueDifference<V>> differences;
- MapDifferenceImpl(Map<K, V> onlyOnLeft,
- Map<K, V> onlyOnRight, Map<K, V> onBoth,
+ MapDifferenceImpl(
+ Map<K, V> onlyOnLeft,
+ Map<K, V> onlyOnRight,
+ Map<K, V> onBoth,
Map<K, ValueDifference<V>> differences) {
this.onlyOnLeft = unmodifiableMap(onlyOnLeft);
this.onlyOnRight = unmodifiableMap(onlyOnRight);
@@ -485,7 +494,8 @@ public final class Maps {
return differences;
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(Object object) {
if (object == this) {
return true;
}
@@ -499,12 +509,14 @@ public final class Maps {
return false;
}
- @Override public int hashCode() {
- return Objects.hashCode(entriesOnlyOnLeft(), entriesOnlyOnRight(),
- entriesInCommon(), entriesDiffering());
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(
+ entriesOnlyOnLeft(), entriesOnlyOnRight(), entriesInCommon(), entriesDiffering());
}
- @Override public String toString() {
+ @Override
+ public String toString() {
if (areEqual()) {
return "equal";
}
@@ -523,8 +535,7 @@ public final class Maps {
}
}
- static class ValueDifferenceImpl<V>
- implements MapDifference.ValueDifference<V> {
+ static class ValueDifferenceImpl<V> implements MapDifference.ValueDifference<V> {
private final V left;
private final V right;
@@ -547,21 +558,23 @@ public final class Maps {
return right;
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object instanceof MapDifference.ValueDifference) {
- MapDifference.ValueDifference<?> that =
- (MapDifference.ValueDifference<?>) object;
+ MapDifference.ValueDifference<?> that = (MapDifference.ValueDifference<?>) object;
return Objects.equal(this.left, that.leftValue())
&& Objects.equal(this.right, that.rightValue());
}
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Objects.hashCode(left, right);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "(" + left + ", " + right + ")";
}
}
@@ -594,33 +607,38 @@ public final class Maps {
SortedMap<K, V> onlyOnRight = Maps.newTreeMap(comparator);
onlyOnRight.putAll(right); // will whittle it down
SortedMap<K, V> onBoth = Maps.newTreeMap(comparator);
- SortedMap<K, MapDifference.ValueDifference<V>> differences =
- Maps.newTreeMap(comparator);
+ SortedMap<K, MapDifference.ValueDifference<V>> differences = Maps.newTreeMap(comparator);
doDifference(left, right, Equivalence.equals(), onlyOnLeft, onlyOnRight, onBoth, differences);
return new SortedMapDifferenceImpl<K, V>(onlyOnLeft, onlyOnRight, onBoth, differences);
}
static class SortedMapDifferenceImpl<K, V> extends MapDifferenceImpl<K, V>
implements SortedMapDifference<K, V> {
- SortedMapDifferenceImpl(SortedMap<K, V> onlyOnLeft,
- SortedMap<K, V> onlyOnRight, SortedMap<K, V> onBoth,
+ SortedMapDifferenceImpl(
+ SortedMap<K, V> onlyOnLeft,
+ SortedMap<K, V> onlyOnRight,
+ SortedMap<K, V> onBoth,
SortedMap<K, ValueDifference<V>> differences) {
super(onlyOnLeft, onlyOnRight, onBoth, differences);
}
- @Override public SortedMap<K, ValueDifference<V>> entriesDiffering() {
+ @Override
+ public SortedMap<K, ValueDifference<V>> entriesDiffering() {
return (SortedMap<K, ValueDifference<V>>) super.entriesDiffering();
}
- @Override public SortedMap<K, V> entriesInCommon() {
+ @Override
+ public SortedMap<K, V> entriesInCommon() {
return (SortedMap<K, V>) super.entriesInCommon();
}
- @Override public SortedMap<K, V> entriesOnlyOnLeft() {
+ @Override
+ public SortedMap<K, V> entriesOnlyOnLeft() {
return (SortedMap<K, V>) super.entriesOnlyOnLeft();
}
- @Override public SortedMap<K, V> entriesOnlyOnRight() {
+ @Override
+ public SortedMap<K, V> entriesOnlyOnRight() {
return (SortedMap<K, V>) super.entriesOnlyOnRight();
}
}
@@ -631,8 +649,7 @@ public final class Maps {
* purpose of this method is to contain the ugly type-casting in one place.
*/
@SuppressWarnings("unchecked")
- static <E> Comparator<? super E> orNaturalOrder(
- @Nullable Comparator<? super E> comparator) {
+ static <E> Comparator<? super E> orNaturalOrder(@Nullable Comparator<? super E> comparator) {
if (comparator != null) { // can't use ? : because of javac bug 5080917
return comparator;
}
@@ -666,9 +683,7 @@ public final class Maps {
*
* @since 14.0
*/
- @Beta
- public static <K, V> Map<K, V> asMap(
- Set<K> set, Function<? super K, V> function) {
+ public static <K, V> Map<K, V> asMap(Set<K> set, Function<? super K, V> function) {
if (set instanceof SortedSet) {
return asMap((SortedSet<K>) set, function);
} else {
@@ -702,18 +717,16 @@ public final class Maps {
*
* @since 14.0
*/
- @Beta
- public static <K, V> SortedMap<K, V> asMap(
- SortedSet<K> set, Function<? super K, V> function) {
+ public static <K, V> SortedMap<K, V> asMap(SortedSet<K> set, Function<? super K, V> function) {
return Platform.mapsAsMapSortedSet(set, function);
}
- static <K, V> SortedMap<K, V> asMapSortedIgnoreNavigable(SortedSet<K> set,
- Function<? super K, V> function) {
+ static <K, V> SortedMap<K, V> asMapSortedIgnoreNavigable(
+ SortedSet<K> set, Function<? super K, V> function) {
return new SortedAsMapView<K, V>(set, function);
}
- private static class AsMapView<K, V> extends ImprovedAbstractMap<K, V> {
+ private static class AsMapView<K, V> extends ViewCachingAbstractMap<K, V> {
private final Set<K> set;
final Function<? super K, V> function;
@@ -776,7 +789,8 @@ public final class Maps {
@Override
protected Set<Entry<K, V>> createEntrySet() {
- return new EntrySet<K, V>() {
+ @WeakOuter
+ class EntrySetImpl extends EntrySet<K, V> {
@Override
Map<K, V> map() {
return AsMapView.this;
@@ -786,13 +800,14 @@ public final class Maps {
public Iterator<Entry<K, V>> iterator() {
return asMapEntryIterator(backingSet(), function);
}
- };
+ }
+ return new EntrySetImpl();
}
}
static <K, V> Iterator<Entry<K, V>> asMapEntryIterator(
Set<K> set, final Function<? super K, V> function) {
- return new TransformedIterator<K, Entry<K,V>>(set.iterator()) {
+ return new TransformedIterator<K, Entry<K, V>>(set.iterator()) {
@Override
Entry<K, V> transform(final K key) {
return immutableEntry(key, function.apply(key));
@@ -800,8 +815,7 @@ public final class Maps {
};
}
- private static class SortedAsMapView<K, V> extends AsMapView<K, V>
- implements SortedMap<K, V> {
+ private static class SortedAsMapView<K, V> extends AsMapView<K, V> implements SortedMap<K, V> {
SortedAsMapView(SortedSet<K> set, Function<? super K, V> function) {
super(set, function);
@@ -907,6 +921,11 @@ public final class Maps {
* The map's iteration order is the order of the first appearance of each key
* in {@code keys}.
*
+ * <p>When there are multiple instances of a key in {@code keys}, it is
+ * unspecified whether {@code valueFunction} will be applied to more than one
+ * instance of that key and, if it is, which result will be mapped to that
+ * key in the returned map.
+ *
* <p>If {@code keys} is a {@link Set}, a live view can be obtained instead of
* a copy using {@link Maps#asMap(Set, Function)}.
*
@@ -915,9 +934,8 @@ public final class Maps {
* for any key
* @since 14.0
*/
- @Beta
- public static <K, V> ImmutableMap<K, V> toMap(Iterable<K> keys,
- Function<? super K, V> valueFunction) {
+ public static <K, V> ImmutableMap<K, V> toMap(
+ Iterable<K> keys, Function<? super K, V> valueFunction) {
return toMap(keys.iterator(), valueFunction);
}
@@ -927,14 +945,18 @@ public final class Maps {
* The map's iteration order is the order of the first appearance of each key
* in {@code keys}.
*
+ * <p>When there are multiple instances of a key in {@code keys}, it is
+ * unspecified whether {@code valueFunction} will be applied to more than one
+ * instance of that key and, if it is, which result will be mapped to that
+ * key in the returned map.
+ *
* @throws NullPointerException if any element of {@code keys} is
* {@code null}, or if {@code valueFunction} produces {@code null}
* for any key
* @since 14.0
*/
- @Beta
- public static <K, V> ImmutableMap<K, V> toMap(Iterator<K> keys,
- Function<? super K, V> valueFunction) {
+ public static <K, V> ImmutableMap<K, V> toMap(
+ Iterator<K> keys, Function<? super K, V> valueFunction) {
checkNotNull(valueFunction);
// Using LHM instead of a builder so as not to fail on duplicate keys
Map<K, V> builder = newLinkedHashMap();
@@ -946,9 +968,22 @@ public final class Maps {
}
/**
- * Returns an immutable map for which the {@link Map#values} are the given
- * elements in the given order, and each key is the product of invoking a
- * supplied function on its corresponding value.
+ * Returns a map with the given {@code values}, indexed by keys derived from
+ * those values. In other words, each input value produces an entry in the map
+ * whose key is the result of applying {@code keyFunction} to that value.
+ * These entries appear in the same order as the input values. Example usage:
+ * <pre> {@code
+ *
+ * Color red = new Color("red", 255, 0, 0);
+ * ...
+ * ImmutableSet<Color> allColors = ImmutableSet.of(red, green, blue);
+ *
+ * Map<String, Color> colorForName =
+ * uniqueIndex(allColors, toStringFunction());
+ * assertThat(colorForName).containsEntry("red", red);}</pre>
+ *
+ * <p>If your index may associate multiple values with each key, use {@link
+ * Multimaps#index(Iterable, Function) Multimaps.index}.
*
* @param values the values to use when constructing the {@code Map}
* @param keyFunction the function used to produce the key for each value
@@ -961,13 +996,27 @@ public final class Maps {
*/
public static <K, V> ImmutableMap<K, V> uniqueIndex(
Iterable<V> values, Function<? super V, K> keyFunction) {
+ // TODO(lowasser): consider presizing the builder if values is a Collection
return uniqueIndex(values.iterator(), keyFunction);
}
/**
- * Returns an immutable map for which the {@link Map#values} are the given
- * elements in the given order, and each key is the product of invoking a
- * supplied function on its corresponding value.
+ * Returns a map with the given {@code values}, indexed by keys derived from
+ * those values. In other words, each input value produces an entry in the map
+ * whose key is the result of applying {@code keyFunction} to that value.
+ * These entries appear in the same order as the input values. Example usage:
+ * <pre> {@code
+ *
+ * Color red = new Color("red", 255, 0, 0);
+ * ...
+ * Iterator<Color> allColors = ImmutableSet.of(red, green, blue).iterator();
+ *
+ * Map<String, Color> colorForName =
+ * uniqueIndex(allColors, toStringFunction());
+ * assertThat(colorForName).containsEntry("red", red);}</pre>
+ *
+ * <p>If your index may associate multiple values with each key, use {@link
+ * Multimaps#index(Iterator, Function) Multimaps.index}.
*
* @param values the values to use when constructing the {@code Map}
* @param keyFunction the function used to produce the key for each value
@@ -987,7 +1036,13 @@ public final class Maps {
V value = values.next();
builder.put(keyFunction.apply(value), value);
}
- return builder.build();
+ try {
+ return builder.build();
+ } catch (IllegalArgumentException duplicateKeys) {
+ throw new IllegalArgumentException(
+ duplicateKeys.getMessage()
+ + ". To index multiple values under a key, use Multimaps.index.");
+ }
}
/**
@@ -1000,8 +1055,7 @@ public final class Maps {
* @param value the value to be associated with the returned entry
*/
@GwtCompatible(serializable = true)
- public static <K, V> Entry<K, V> immutableEntry(
- @Nullable K key, @Nullable V value) {
+ public static <K, V> Entry<K, V> immutableEntry(@Nullable K key, @Nullable V value) {
return new ImmutableEntry<K, V>(key, value);
}
@@ -1013,10 +1067,8 @@ public final class Maps {
* @param entrySet the entries for which to return an unmodifiable view
* @return an unmodifiable view of the entries
*/
- static <K, V> Set<Entry<K, V>> unmodifiableEntrySet(
- Set<Entry<K, V>> entrySet) {
- return new UnmodifiableEntrySet<K, V>(
- Collections.unmodifiableSet(entrySet));
+ static <K, V> Set<Entry<K, V>> unmodifiableEntrySet(Set<Entry<K, V>> entrySet) {
+ return new UnmodifiableEntrySet<K, V>(Collections.unmodifiableSet(entrySet));
}
/**
@@ -1031,68 +1083,80 @@ public final class Maps {
static <K, V> Entry<K, V> unmodifiableEntry(final Entry<? extends K, ? extends V> entry) {
checkNotNull(entry);
return new AbstractMapEntry<K, V>() {
- @Override public K getKey() {
+ @Override
+ public K getKey() {
return entry.getKey();
}
- @Override public V getValue() {
+ @Override
+ public V getValue() {
return entry.getValue();
}
};
}
+ static <K, V> UnmodifiableIterator<Entry<K, V>> unmodifiableEntryIterator(
+ final Iterator<Entry<K, V>> entryIterator) {
+ return new UnmodifiableIterator<Entry<K, V>>() {
+ @Override
+ public boolean hasNext() {
+ return entryIterator.hasNext();
+ }
+
+ @Override
+ public Entry<K, V> next() {
+ return unmodifiableEntry(entryIterator.next());
+ }
+ };
+ }
+
/** @see Multimaps#unmodifiableEntries */
- static class UnmodifiableEntries<K, V>
- extends ForwardingCollection<Entry<K, V>> {
+ static class UnmodifiableEntries<K, V> extends ForwardingCollection<Entry<K, V>> {
private final Collection<Entry<K, V>> entries;
UnmodifiableEntries(Collection<Entry<K, V>> entries) {
this.entries = entries;
}
- @Override protected Collection<Entry<K, V>> delegate() {
+ @Override
+ protected Collection<Entry<K, V>> delegate() {
return entries;
}
- @Override public Iterator<Entry<K, V>> iterator() {
- final Iterator<Entry<K, V>> delegate = super.iterator();
- return new UnmodifiableIterator<Entry<K, V>>() {
- @Override
- public boolean hasNext() {
- return delegate.hasNext();
- }
-
- @Override public Entry<K, V> next() {
- return unmodifiableEntry(delegate.next());
- }
- };
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return unmodifiableEntryIterator(entries.iterator());
}
// See java.util.Collections.UnmodifiableEntrySet for details on attacks.
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
return standardToArray();
}
- @Override public <T> T[] toArray(T[] array) {
+ @Override
+ public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
}
/** @see Maps#unmodifiableEntrySet(Set) */
- static class UnmodifiableEntrySet<K, V>
- extends UnmodifiableEntries<K, V> implements Set<Entry<K, V>> {
+ static class UnmodifiableEntrySet<K, V> extends UnmodifiableEntries<K, V>
+ implements Set<Entry<K, V>> {
UnmodifiableEntrySet(Set<Entry<K, V>> entries) {
super(entries);
}
// See java.util.Collections.UnmodifiableEntrySet for details on attacks.
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return Sets.equalsImpl(this, object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Sets.hashCodeImpl(this);
}
}
@@ -1204,27 +1268,26 @@ public final class Maps {
* @param bimap the bimap for which an unmodifiable view is to be returned
* @return an unmodifiable view of the specified bimap
*/
- public static <K, V> BiMap<K, V> unmodifiableBiMap(
- BiMap<? extends K, ? extends V> bimap) {
+ public static <K, V> BiMap<K, V> unmodifiableBiMap(BiMap<? extends K, ? extends V> bimap) {
return new UnmodifiableBiMap<K, V>(bimap, null);
}
/** @see Maps#unmodifiableBiMap(BiMap) */
- private static class UnmodifiableBiMap<K, V>
- extends ForwardingMap<K, V> implements BiMap<K, V>, Serializable {
+ private static class UnmodifiableBiMap<K, V> extends ForwardingMap<K, V>
+ implements BiMap<K, V>, Serializable {
final Map<K, V> unmodifiableMap;
final BiMap<? extends K, ? extends V> delegate;
BiMap<V, K> inverse;
transient Set<V> values;
- UnmodifiableBiMap(BiMap<? extends K, ? extends V> delegate,
- @Nullable BiMap<V, K> inverse) {
+ UnmodifiableBiMap(BiMap<? extends K, ? extends V> delegate, @Nullable BiMap<V, K> inverse) {
unmodifiableMap = Collections.unmodifiableMap(delegate);
this.delegate = delegate;
this.inverse = inverse;
}
- @Override protected Map<K, V> delegate() {
+ @Override
+ protected Map<K, V> delegate() {
return unmodifiableMap;
}
@@ -1241,7 +1304,8 @@ public final class Maps {
: result;
}
- @Override public Set<V> values() {
+ @Override
+ public Set<V> values() {
Set<V> result = values;
return (result == null)
? values = Collections.unmodifiableSet(delegate.values())
@@ -1388,8 +1452,7 @@ public final class Maps {
* @since 7.0
*/
public static <K, V1, V2> Map<K, V2> transformEntries(
- Map<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ Map<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
if (fromMap instanceof SortedMap) {
return transformEntries((SortedMap<K, V1>) fromMap, transformer);
}
@@ -1449,14 +1512,12 @@ public final class Maps {
* @since 11.0
*/
public static <K, V1, V2> SortedMap<K, V2> transformEntries(
- SortedMap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
return Platform.mapsTransformEntriesSortedMap(fromMap, transformer);
}
static <K, V1, V2> SortedMap<K, V2> transformEntriesIgnoreNavigable(
- SortedMap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
return new TransformedEntriesSortedMap<K, V1, V2>(fromMap, transformer);
}
@@ -1494,8 +1555,8 @@ public final class Maps {
/**
* Views a function as an entry transformer that ignores the entry key.
*/
- static <K, V1, V2> EntryTransformer<K, V1, V2>
- asEntryTransformer(final Function<? super V1, V2> function) {
+ static <K, V1, V2> EntryTransformer<K, V1, V2> asEntryTransformer(
+ final Function<? super V1, V2> function) {
checkNotNull(function);
return new EntryTransformer<K, V1, V2>() {
@Override
@@ -1564,29 +1625,30 @@ public final class Maps {
};
}
- static class TransformedEntriesMap<K, V1, V2>
- extends ImprovedAbstractMap<K, V2> {
+ static class TransformedEntriesMap<K, V1, V2> extends IteratorBasedAbstractMap<K, V2> {
final Map<K, V1> fromMap;
final EntryTransformer<? super K, ? super V1, V2> transformer;
TransformedEntriesMap(
- Map<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ Map<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
this.fromMap = checkNotNull(fromMap);
this.transformer = checkNotNull(transformer);
}
- @Override public int size() {
+ @Override
+ public int size() {
return fromMap.size();
}
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return fromMap.containsKey(key);
}
// safe as long as the user followed the <b>Warning</b> in the javadoc
@SuppressWarnings("unchecked")
- @Override public V2 get(Object key) {
+ @Override
+ public V2 get(Object key) {
V1 value = fromMap.get(key);
return (value != null || fromMap.containsKey(key))
? transformer.transformEntry((K) key, value)
@@ -1595,69 +1657,74 @@ public final class Maps {
// safe as long as the user followed the <b>Warning</b> in the javadoc
@SuppressWarnings("unchecked")
- @Override public V2 remove(Object key) {
+ @Override
+ public V2 remove(Object key) {
return fromMap.containsKey(key)
? transformer.transformEntry((K) key, fromMap.remove(key))
: null;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
fromMap.clear();
}
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
return fromMap.keySet();
}
@Override
- protected Set<Entry<K, V2>> createEntrySet() {
- return new EntrySet<K, V2>() {
- @Override Map<K, V2> map() {
- return TransformedEntriesMap.this;
- }
+ Iterator<Entry<K, V2>> entryIterator() {
+ return Iterators.transform(
+ fromMap.entrySet().iterator(), Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
+ }
- @Override public Iterator<Entry<K, V2>> iterator() {
- return Iterators.transform(fromMap.entrySet().iterator(),
- Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
- }
- };
+ @Override
+ public Collection<V2> values() {
+ return new Values<K, V2>(this);
}
}
- static class TransformedEntriesSortedMap<K, V1, V2>
- extends TransformedEntriesMap<K, V1, V2> implements SortedMap<K, V2> {
+ static class TransformedEntriesSortedMap<K, V1, V2> extends TransformedEntriesMap<K, V1, V2>
+ implements SortedMap<K, V2> {
protected SortedMap<K, V1> fromMap() {
return (SortedMap<K, V1>) fromMap;
}
- TransformedEntriesSortedMap(SortedMap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ TransformedEntriesSortedMap(
+ SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
super(fromMap, transformer);
}
- @Override public Comparator<? super K> comparator() {
+ @Override
+ public Comparator<? super K> comparator() {
return fromMap().comparator();
}
- @Override public K firstKey() {
+ @Override
+ public K firstKey() {
return fromMap().firstKey();
}
- @Override public SortedMap<K, V2> headMap(K toKey) {
+ @Override
+ public SortedMap<K, V2> headMap(K toKey) {
return transformEntries(fromMap().headMap(toKey), transformer);
}
- @Override public K lastKey() {
+ @Override
+ public K lastKey() {
return fromMap().lastKey();
}
- @Override public SortedMap<K, V2> subMap(K fromKey, K toKey) {
- return transformEntries(
- fromMap().subMap(fromKey, toKey), transformer);
+ @Override
+ public SortedMap<K, V2> subMap(K fromKey, K toKey) {
+ return transformEntries(fromMap().subMap(fromKey, toKey), transformer);
}
- @Override public SortedMap<K, V2> tailMap(K fromKey) {
+ @Override
+ public SortedMap<K, V2> tailMap(K fromKey) {
return transformEntries(fromMap().tailMap(fromKey), transformer);
}
}
@@ -1698,6 +1765,7 @@ public final class Maps {
* predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is
* inconsistent with equals.
*/
+ @CheckReturnValue
public static <K, V> Map<K, V> filterKeys(
Map<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
if (unfiltered instanceof SortedMap) {
@@ -1709,8 +1777,7 @@ public final class Maps {
Predicate<Entry<K, ?>> entryPredicate = keyPredicateOnEntries(keyPredicate);
return (unfiltered instanceof AbstractFilteredMap)
? filterFiltered((AbstractFilteredMap<K, V>) unfiltered, entryPredicate)
- : new FilteredKeyMap<K, V>(
- checkNotNull(unfiltered), keyPredicate, entryPredicate);
+ : new FilteredKeyMap<K, V>(checkNotNull(unfiltered), keyPredicate, entryPredicate);
}
/**
@@ -1743,9 +1810,10 @@ public final class Maps {
*
* @since 11.0
*/
+ @CheckReturnValue
public static <K, V> SortedMap<K, V> filterKeys(
SortedMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
- // TODO(user): Return a subclass of Maps.FilteredKeyMap for slightly better
+ // TODO(lowasser): Return a subclass of Maps.FilteredKeyMap for slightly better
// performance.
return filterEntries(unfiltered, Maps.<K>keyPredicateOnEntries(keyPredicate));
}
@@ -1775,6 +1843,7 @@ public final class Maps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> BiMap<K, V> filterKeys(
BiMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
checkNotNull(keyPredicate);
@@ -1810,6 +1879,7 @@ public final class Maps {
* predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is
* inconsistent with equals.
*/
+ @CheckReturnValue
public static <K, V> Map<K, V> filterValues(
Map<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
if (unfiltered instanceof SortedMap) {
@@ -1851,6 +1921,7 @@ public final class Maps {
*
* @since 11.0
*/
+ @CheckReturnValue
public static <K, V> SortedMap<K, V> filterValues(
SortedMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -1884,6 +1955,7 @@ public final class Maps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> BiMap<K, V> filterValues(
BiMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -1918,6 +1990,7 @@ public final class Maps {
* <p><b>Warning:</b> {@code entryPredicate} must be <i>consistent with
* equals</i>, as documented at {@link Predicate#apply}.
*/
+ @CheckReturnValue
public static <K, V> Map<K, V> filterEntries(
Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
if (unfiltered instanceof SortedMap) {
@@ -1962,15 +2035,14 @@ public final class Maps {
*
* @since 11.0
*/
+ @CheckReturnValue
public static <K, V> SortedMap<K, V> filterEntries(
- SortedMap<K, V> unfiltered,
- Predicate<? super Entry<K, V>> entryPredicate) {
+ SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
return Platform.mapsFilterSortedMap(unfiltered, entryPredicate);
}
static <K, V> SortedMap<K, V> filterSortedIgnoreNavigable(
- SortedMap<K, V> unfiltered,
- Predicate<? super Entry<K, V>> entryPredicate) {
+ SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
checkNotNull(entryPredicate);
return (unfiltered instanceof FilteredEntrySortedMap)
? filterFiltered((FilteredEntrySortedMap<K, V>) unfiltered, entryPredicate)
@@ -2004,6 +2076,7 @@ public final class Maps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> BiMap<K, V> filterEntries(
BiMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
checkNotNull(unfiltered);
@@ -2017,19 +2090,17 @@ public final class Maps {
* Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when
* filtering a filtered map.
*/
- private static <K, V> Map<K, V> filterFiltered(AbstractFilteredMap<K, V> map,
- Predicate<? super Entry<K, V>> entryPredicate) {
- return new FilteredEntryMap<K, V>(map.unfiltered,
- Predicates.<Entry<K, V>>and(map.predicate, entryPredicate));
+ private static <K, V> Map<K, V> filterFiltered(
+ AbstractFilteredMap<K, V> map, Predicate<? super Entry<K, V>> entryPredicate) {
+ return new FilteredEntryMap<K, V>(
+ map.unfiltered, Predicates.<Entry<K, V>>and(map.predicate, entryPredicate));
}
- private abstract static class AbstractFilteredMap<K, V>
- extends ImprovedAbstractMap<K, V> {
+ private abstract static class AbstractFilteredMap<K, V> extends ViewCachingAbstractMap<K, V> {
final Map<K, V> unfiltered;
final Predicate<? super Entry<K, V>> predicate;
- AbstractFilteredMap(
- Map<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
+ AbstractFilteredMap(Map<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
this.unfiltered = unfiltered;
this.predicate = predicate;
}
@@ -2042,32 +2113,38 @@ public final class Maps {
return predicate.apply(Maps.immutableEntry(k, value));
}
- @Override public V put(K key, V value) {
+ @Override
+ public V put(K key, V value) {
checkArgument(apply(key, value));
return unfiltered.put(key, value);
}
- @Override public void putAll(Map<? extends K, ? extends V> map) {
+ @Override
+ public void putAll(Map<? extends K, ? extends V> map) {
for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
checkArgument(apply(entry.getKey(), entry.getValue()));
}
unfiltered.putAll(map);
}
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return unfiltered.containsKey(key) && apply(key, unfiltered.get(key));
}
- @Override public V get(Object key) {
+ @Override
+ public V get(Object key) {
V value = unfiltered.get(key);
return ((value != null) && apply(key, value)) ? value : null;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return entrySet().isEmpty();
}
- @Override public V remove(Object key) {
+ @Override
+ public V remove(Object key) {
return containsKey(key) ? unfiltered.remove(key) : null;
}
@@ -2081,38 +2158,45 @@ public final class Maps {
Map<K, V> unfiltered;
Predicate<? super Entry<K, V>> predicate;
- FilteredMapValues(Map<K, V> filteredMap, Map<K, V> unfiltered,
- Predicate<? super Entry<K, V>> predicate) {
+ FilteredMapValues(
+ Map<K, V> filteredMap, Map<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
super(filteredMap);
this.unfiltered = unfiltered;
this.predicate = predicate;
}
- @Override public boolean remove(Object o) {
- return Iterables.removeFirstMatching(unfiltered.entrySet(),
- Predicates.<Entry<K, V>>and(predicate, Maps.<V>valuePredicateOnEntries(equalTo(o))))
+ @Override
+ public boolean remove(Object o) {
+ return Iterables.removeFirstMatching(
+ unfiltered.entrySet(),
+ Predicates.<Entry<K, V>>and(predicate, Maps.<V>valuePredicateOnEntries(equalTo(o))))
!= null;
}
private boolean removeIf(Predicate<? super V> valuePredicate) {
- return Iterables.removeIf(unfiltered.entrySet(), Predicates.<Entry<K, V>>and(
- predicate, Maps.<V>valuePredicateOnEntries(valuePredicate)));
+ return Iterables.removeIf(
+ unfiltered.entrySet(),
+ Predicates.<Entry<K, V>>and(predicate, Maps.<V>valuePredicateOnEntries(valuePredicate)));
}
- @Override public boolean removeAll(Collection<?> collection) {
+ @Override
+ public boolean removeAll(Collection<?> collection) {
return removeIf(in(collection));
}
- @Override public boolean retainAll(Collection<?> collection) {
+ @Override
+ public boolean retainAll(Collection<?> collection) {
return removeIf(not(in(collection)));
}
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
// creating an ArrayList so filtering happens once
return Lists.newArrayList(iterator()).toArray();
}
- @Override public <T> T[] toArray(T[] array) {
+ @Override
+ public <T> T[] toArray(T[] array) {
return Lists.newArrayList(iterator()).toArray(array);
}
}
@@ -2120,7 +2204,9 @@ public final class Maps {
private static class FilteredKeyMap<K, V> extends AbstractFilteredMap<K, V> {
Predicate<? super K> keyPredicate;
- FilteredKeyMap(Map<K, V> unfiltered, Predicate<? super K> keyPredicate,
+ FilteredKeyMap(
+ Map<K, V> unfiltered,
+ Predicate<? super K> keyPredicate,
Predicate<? super Entry<K, V>> entryPredicate) {
super(unfiltered, entryPredicate);
this.keyPredicate = keyPredicate;
@@ -2152,8 +2238,7 @@ public final class Maps {
*/
final Set<Entry<K, V>> filteredEntrySet;
- FilteredEntryMap(
- Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
+ FilteredEntryMap(Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
super(unfiltered, entryPredicate);
filteredEntrySet = Sets.filter(unfiltered.entrySet(), predicate);
}
@@ -2163,12 +2248,15 @@ public final class Maps {
return new EntrySet();
}
+ @WeakOuter
private class EntrySet extends ForwardingSet<Entry<K, V>> {
- @Override protected Set<Entry<K, V>> delegate() {
+ @Override
+ protected Set<Entry<K, V>> delegate() {
return filteredEntrySet;
}
- @Override public Iterator<Entry<K, V>> iterator() {
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
return new TransformedIterator<Entry<K, V>, Entry<K, V>>(filteredEntrySet.iterator()) {
@Override
Entry<K, V> transform(final Entry<K, V> entry) {
@@ -2194,12 +2282,14 @@ public final class Maps {
return new KeySet();
}
+ @WeakOuter
class KeySet extends Maps.KeySet<K, V> {
KeySet() {
super(FilteredEntryMap.this);
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
if (containsKey(o)) {
unfiltered.remove(o);
return true;
@@ -2208,8 +2298,9 @@ public final class Maps {
}
private boolean removeIf(Predicate<? super K> keyPredicate) {
- return Iterables.removeIf(unfiltered.entrySet(), Predicates.<Entry<K, V>>and(
- predicate, Maps.<K>keyPredicateOnEntries(keyPredicate)));
+ return Iterables.removeIf(
+ unfiltered.entrySet(),
+ Predicates.<Entry<K, V>>and(predicate, Maps.<K>keyPredicateOnEntries(keyPredicate)));
}
@Override
@@ -2222,12 +2313,14 @@ public final class Maps {
return removeIf(not(in(c)));
}
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
// creating an ArrayList so filtering happens once
return Lists.newArrayList(iterator()).toArray();
}
- @Override public <T> T[] toArray(T[] array) {
+ @Override
+ public <T> T[] toArray(T[] array) {
return Lists.newArrayList(iterator()).toArray(array);
}
}
@@ -2238,18 +2331,16 @@ public final class Maps {
* filtering a filtered sorted map.
*/
private static <K, V> SortedMap<K, V> filterFiltered(
- FilteredEntrySortedMap<K, V> map,
- Predicate<? super Entry<K, V>> entryPredicate) {
- Predicate<Entry<K, V>> predicate
- = Predicates.and(map.predicate, entryPredicate);
+ FilteredEntrySortedMap<K, V> map, Predicate<? super Entry<K, V>> entryPredicate) {
+ Predicate<Entry<K, V>> predicate = Predicates.and(map.predicate, entryPredicate);
return new FilteredEntrySortedMap<K, V>(map.sortedMap(), predicate);
}
- private static class FilteredEntrySortedMap<K, V>
- extends FilteredEntryMap<K, V> implements SortedMap<K, V> {
+ private static class FilteredEntrySortedMap<K, V> extends FilteredEntryMap<K, V>
+ implements SortedMap<K, V> {
- FilteredEntrySortedMap(SortedMap<K, V> unfiltered,
- Predicate<? super Entry<K, V>> entryPredicate) {
+ FilteredEntrySortedMap(
+ SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
super(unfiltered, entryPredicate);
}
@@ -2257,7 +2348,8 @@ public final class Maps {
return (SortedMap<K, V>) unfiltered;
}
- @Override public SortedSet<K> keySet() {
+ @Override
+ public SortedSet<K> keySet() {
return (SortedSet<K>) super.keySet();
}
@@ -2266,6 +2358,7 @@ public final class Maps {
return new SortedKeySet();
}
+ @WeakOuter
class SortedKeySet extends KeySet implements SortedSet<K> {
@Override
public Comparator<? super K> comparator() {
@@ -2298,16 +2391,19 @@ public final class Maps {
}
}
- @Override public Comparator<? super K> comparator() {
+ @Override
+ public Comparator<? super K> comparator() {
return sortedMap().comparator();
}
- @Override public K firstKey() {
+ @Override
+ public K firstKey() {
// correctly throws NoSuchElementException when filtered map is empty.
return keySet().iterator().next();
}
- @Override public K lastKey() {
+ @Override
+ public K lastKey() {
SortedMap<K, V> headMap = sortedMap();
while (true) {
// correctly throws NoSuchElementException when filtered map is empty.
@@ -2319,18 +2415,19 @@ public final class Maps {
}
}
- @Override public SortedMap<K, V> headMap(K toKey) {
+ @Override
+ public SortedMap<K, V> headMap(K toKey) {
return new FilteredEntrySortedMap<K, V>(sortedMap().headMap(toKey), predicate);
}
- @Override public SortedMap<K, V> subMap(K fromKey, K toKey) {
- return new FilteredEntrySortedMap<K, V>(
- sortedMap().subMap(fromKey, toKey), predicate);
+ @Override
+ public SortedMap<K, V> subMap(K fromKey, K toKey) {
+ return new FilteredEntrySortedMap<K, V>(sortedMap().subMap(fromKey, toKey), predicate);
}
- @Override public SortedMap<K, V> tailMap(K fromKey) {
- return new FilteredEntrySortedMap<K, V>(
- sortedMap().tailMap(fromKey), predicate);
+ @Override
+ public SortedMap<K, V> tailMap(K fromKey) {
+ return new FilteredEntrySortedMap<K, V>(sortedMap().tailMap(fromKey), predicate);
}
}
@@ -2353,22 +2450,19 @@ public final class Maps {
return new Predicate<Entry<V, K>>() {
@Override
public boolean apply(Entry<V, K> input) {
- return forwardPredicate.apply(
- Maps.immutableEntry(input.getValue(), input.getKey()));
+ return forwardPredicate.apply(Maps.immutableEntry(input.getValue(), input.getKey()));
}
};
}
- FilteredEntryBiMap(BiMap<K, V> delegate,
- Predicate<? super Entry<K, V>> predicate) {
+ FilteredEntryBiMap(BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate) {
super(delegate, predicate);
- this.inverse = new FilteredEntryBiMap<V, K>(
- delegate.inverse(), inversePredicate(predicate), this);
+ this.inverse =
+ new FilteredEntryBiMap<V, K>(delegate.inverse(), inversePredicate(predicate), this);
}
private FilteredEntryBiMap(
- BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate,
- BiMap<V, K> inverse) {
+ BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate, BiMap<V, K> inverse) {
super(delegate, predicate);
this.inverse = inverse;
}
@@ -2394,19 +2488,17 @@ public final class Maps {
}
}
- @Nullable private static <K, V> Entry<K, V> unmodifiableOrNull(@Nullable Entry<K, V> entry) {
+ @Nullable
+ private static <K, V> Entry<K, V> unmodifiableOrNull(@Nullable Entry<K, V> entry) {
return (entry == null) ? null : Maps.unmodifiableEntry(entry);
}
/**
- * {@code AbstractMap} extension that implements {@link #isEmpty()} as {@code
- * entrySet().isEmpty()} instead of {@code size() == 0} to speed up
- * implementations where {@code size()} is O(n), and it delegates the {@code
- * isEmpty()} methods of its key set and value collection to this
- * implementation.
+ * {@code AbstractMap} extension that makes it easy to cache customized keySet, values,
+ * and entrySet views.
*/
@GwtCompatible
- abstract static class ImprovedAbstractMap<K, V> extends AbstractMap<K, V> {
+ abstract static class ViewCachingAbstractMap<K, V> extends AbstractMap<K, V> {
/**
* Creates the entry set to be returned by {@link #entrySet()}. This method
* is invoked at most once on a given map, at the time when {@code entrySet}
@@ -2416,14 +2508,16 @@ public final class Maps {
private transient Set<Entry<K, V>> entrySet;
- @Override public Set<Entry<K, V>> entrySet() {
+ @Override
+ public Set<Entry<K, V>> entrySet() {
Set<Entry<K, V>> result = entrySet;
return (result == null) ? entrySet = createEntrySet() : result;
}
private transient Set<K> keySet;
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
Set<K> result = keySet;
return (result == null) ? keySet = createKeySet() : result;
}
@@ -2434,7 +2528,8 @@ public final class Maps {
private transient Collection<V> values;
- @Override public Collection<V> values() {
+ @Override
+ public Collection<V> values() {
Collection<V> result = values;
return (result == null) ? values = createValues() : result;
}
@@ -2444,6 +2539,33 @@ public final class Maps {
}
}
+ abstract static class IteratorBasedAbstractMap<K, V> extends AbstractMap<K, V> {
+ @Override
+ public abstract int size();
+
+ abstract Iterator<Entry<K, V>> entryIterator();
+
+ @Override
+ public Set<Entry<K, V>> entrySet() {
+ return new EntrySet<K, V>() {
+ @Override
+ Map<K, V> map() {
+ return IteratorBasedAbstractMap.this;
+ }
+
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return entryIterator();
+ }
+ };
+ }
+
+ @Override
+ public void clear() {
+ Iterators.clear(entryIterator());
+ }
+ }
+
/**
* Delegates to {@link Map#get}. Returns {@code null} on {@code
* ClassCastException} and {@code NullPointerException}.
@@ -2556,15 +2678,13 @@ public final class Maps {
return false;
}
- static final MapJoiner STANDARD_JOINER =
- Collections2.STANDARD_JOINER.withKeyValueSeparator("=");
+ static final MapJoiner STANDARD_JOINER = Collections2.STANDARD_JOINER.withKeyValueSeparator("=");
/**
* An implementation of {@link Map#toString}.
*/
static String toStringImpl(Map<?, ?> map) {
- StringBuilder sb
- = Collections2.newStringBuilderForCollection(map.size()).append('{');
+ StringBuilder sb = Collections2.newStringBuilderForCollection(map.size()).append('{');
STANDARD_JOINER.appendTo(sb, map);
return sb.append('}').toString();
}
@@ -2572,15 +2692,14 @@ public final class Maps {
/**
* An implementation of {@link Map#putAll}.
*/
- static <K, V> void putAllImpl(
- Map<K, V> self, Map<? extends K, ? extends V> map) {
+ static <K, V> void putAllImpl(Map<K, V> self, Map<? extends K, ? extends V> map) {
for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
self.put(entry.getKey(), entry.getValue());
}
}
static class KeySet<K, V> extends Sets.ImprovedAbstractSet<K> {
- final Map<K, V> map;
+ @Weak final Map<K, V> map;
KeySet(Map<K, V> map) {
this.map = checkNotNull(map);
@@ -2590,23 +2709,28 @@ public final class Maps {
return map;
}
- @Override public Iterator<K> iterator() {
+ @Override
+ public Iterator<K> iterator() {
return keyIterator(map().entrySet().iterator());
}
- @Override public int size() {
+ @Override
+ public int size() {
return map().size();
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return map().isEmpty();
}
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
return map().containsKey(o);
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
if (contains(o)) {
map().remove(o);
return true;
@@ -2614,7 +2738,8 @@ public final class Maps {
return false;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
map().clear();
}
}
@@ -2671,7 +2796,7 @@ public final class Maps {
}
static class Values<K, V> extends AbstractCollection<V> {
- final Map<K, V> map;
+ @Weak final Map<K, V> map;
Values(Map<K, V> map) {
this.map = checkNotNull(map);
@@ -2681,11 +2806,13 @@ public final class Maps {
return map;
}
- @Override public Iterator<V> iterator() {
+ @Override
+ public Iterator<V> iterator() {
return valueIterator(map().entrySet().iterator());
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
try {
return super.remove(o);
} catch (UnsupportedOperationException e) {
@@ -2699,7 +2826,8 @@ public final class Maps {
}
}
- @Override public boolean removeAll(Collection<?> c) {
+ @Override
+ public boolean removeAll(Collection<?> c) {
try {
return super.removeAll(checkNotNull(c));
} catch (UnsupportedOperationException e) {
@@ -2713,7 +2841,8 @@ public final class Maps {
}
}
- @Override public boolean retainAll(Collection<?> c) {
+ @Override
+ public boolean retainAll(Collection<?> c) {
try {
return super.retainAll(checkNotNull(c));
} catch (UnsupportedOperationException e) {
@@ -2727,51 +2856,58 @@ public final class Maps {
}
}
- @Override public int size() {
+ @Override
+ public int size() {
return map().size();
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return map().isEmpty();
}
- @Override public boolean contains(@Nullable Object o) {
+ @Override
+ public boolean contains(@Nullable Object o) {
return map().containsValue(o);
}
- @Override public void clear() {
+ @Override
+ public void clear() {
map().clear();
}
}
- abstract static class EntrySet<K, V>
- extends Sets.ImprovedAbstractSet<Entry<K, V>> {
+ abstract static class EntrySet<K, V> extends Sets.ImprovedAbstractSet<Entry<K, V>> {
abstract Map<K, V> map();
- @Override public int size() {
+ @Override
+ public int size() {
return map().size();
}
- @Override public void clear() {
+ @Override
+ public void clear() {
map().clear();
}
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
if (o instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) o;
Object key = entry.getKey();
V value = Maps.safeGet(map(), key);
- return Objects.equal(value, entry.getValue())
- && (value != null || map().containsKey(key));
+ return Objects.equal(value, entry.getValue()) && (value != null || map().containsKey(key));
}
return false;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return map().isEmpty();
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
if (contains(o)) {
Entry<?, ?> entry = (Entry<?, ?>) o;
return map().keySet().remove(entry.getKey());
@@ -2779,7 +2915,8 @@ public final class Maps {
return false;
}
- @Override public boolean removeAll(Collection<?> c) {
+ @Override
+ public boolean removeAll(Collection<?> c) {
try {
return super.removeAll(checkNotNull(c));
} catch (UnsupportedOperationException e) {
@@ -2788,7 +2925,8 @@ public final class Maps {
}
}
- @Override public boolean retainAll(Collection<?> c) {
+ @Override
+ public boolean retainAll(Collection<?> c) {
try {
return super.retainAll(checkNotNull(c));
} catch (UnsupportedOperationException e) {
@@ -2804,4 +2942,17 @@ public final class Maps {
}
}
}
+
+ /**
+ * Returns a map from the ith element of list to i.
+ */
+ static <E> ImmutableMap<E, Integer> indexMap(Collection<E> list) {
+ ImmutableMap.Builder<E, Integer> builder = new ImmutableMap.Builder<E, Integer>(list.size());
+ int i = 0;
+ for (E e : list) {
+ builder.put(e, i++);
+ }
+ return builder.build();
+ }
}
+
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Multimaps.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Multimaps.java
index 271e59e..ad5a1c8 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Multimaps.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Multimaps.java
@@ -27,6 +27,8 @@ import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.collect.Maps.EntryTransformer;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.AbstractCollection;
@@ -42,20 +44,21 @@ import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Provides static methods acting on or generating a {@code Multimap}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Multimaps">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#multimaps">
* {@code Multimaps}</a>.
*
* @author Jared Levy
* @author Robert Konigsberg
* @author Mike Bostock
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Multimaps {
@@ -104,21 +107,21 @@ public final class Multimaps {
* values for a given key
* @throws IllegalArgumentException if {@code map} is not empty
*/
- public static <K, V> Multimap<K, V> newMultimap(Map<K, Collection<V>> map,
- final Supplier<? extends Collection<V>> factory) {
+ public static <K, V> Multimap<K, V> newMultimap(
+ Map<K, Collection<V>> map, final Supplier<? extends Collection<V>> factory) {
return new CustomMultimap<K, V>(map, factory);
}
private static class CustomMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
transient Supplier<? extends Collection<V>> factory;
- CustomMultimap(Map<K, Collection<V>> map,
- Supplier<? extends Collection<V>> factory) {
+ CustomMultimap(Map<K, Collection<V>> map, Supplier<? extends Collection<V>> factory) {
super(map);
this.factory = checkNotNull(factory);
}
- @Override protected Collection<V> createCollection() {
+ @Override
+ protected Collection<V> createCollection() {
return factory.get();
}
@@ -169,17 +172,16 @@ public final class Multimaps {
return new CustomListMultimap<K, V>(map, factory);
}
- private static class CustomListMultimap<K, V>
- extends AbstractListMultimap<K, V> {
+ private static class CustomListMultimap<K, V> extends AbstractListMultimap<K, V> {
transient Supplier<? extends List<V>> factory;
- CustomListMultimap(Map<K, Collection<V>> map,
- Supplier<? extends List<V>> factory) {
+ CustomListMultimap(Map<K, Collection<V>> map, Supplier<? extends List<V>> factory) {
super(map);
this.factory = checkNotNull(factory);
}
- @Override protected List<V> createCollection() {
+ @Override
+ protected List<V> createCollection() {
return factory.get();
}
}
@@ -226,17 +228,16 @@ public final class Multimaps {
return new CustomSetMultimap<K, V>(map, factory);
}
- private static class CustomSetMultimap<K, V>
- extends AbstractSetMultimap<K, V> {
+ private static class CustomSetMultimap<K, V> extends AbstractSetMultimap<K, V> {
transient Supplier<? extends Set<V>> factory;
- CustomSetMultimap(Map<K, Collection<V>> map,
- Supplier<? extends Set<V>> factory) {
+ CustomSetMultimap(Map<K, Collection<V>> map, Supplier<? extends Set<V>> factory) {
super(map);
this.factory = checkNotNull(factory);
}
- @Override protected Set<V> createCollection() {
+ @Override
+ protected Set<V> createCollection() {
return factory.get();
}
}
@@ -278,28 +279,27 @@ public final class Multimaps {
* @throws IllegalArgumentException if {@code map} is not empty
*/
public static <K, V> SortedSetMultimap<K, V> newSortedSetMultimap(
- Map<K, Collection<V>> map,
- final Supplier<? extends SortedSet<V>> factory) {
+ Map<K, Collection<V>> map, final Supplier<? extends SortedSet<V>> factory) {
return new CustomSortedSetMultimap<K, V>(map, factory);
}
- private static class CustomSortedSetMultimap<K, V>
- extends AbstractSortedSetMultimap<K, V> {
+ private static class CustomSortedSetMultimap<K, V> extends AbstractSortedSetMultimap<K, V> {
transient Supplier<? extends SortedSet<V>> factory;
transient Comparator<? super V> valueComparator;
- CustomSortedSetMultimap(Map<K, Collection<V>> map,
- Supplier<? extends SortedSet<V>> factory) {
+ CustomSortedSetMultimap(Map<K, Collection<V>> map, Supplier<? extends SortedSet<V>> factory) {
super(map);
this.factory = checkNotNull(factory);
valueComparator = factory.get().comparator();
}
- @Override protected SortedSet<V> createCollection() {
+ @Override
+ protected SortedSet<V> createCollection() {
return factory.get();
}
- @Override public Comparator<? super V> valueComparator() {
+ @Override
+ public Comparator<? super V> valueComparator() {
return valueComparator;
}
}
@@ -357,8 +357,7 @@ public final class Multimaps {
* @param multimap the multimap to be wrapped in a synchronized view
* @return a synchronized view of the specified multimap
*/
- public static <K, V> Multimap<K, V> synchronizedMultimap(
- Multimap<K, V> multimap) {
+ public static <K, V> Multimap<K, V> synchronizedMultimap(Multimap<K, V> multimap) {
return Synchronized.multimap(multimap, null);
}
@@ -379,10 +378,8 @@ public final class Multimaps {
* returned
* @return an unmodifiable view of the specified multimap
*/
- public static <K, V> Multimap<K, V> unmodifiableMultimap(
- Multimap<K, V> delegate) {
- if (delegate instanceof UnmodifiableMultimap ||
- delegate instanceof ImmutableMultimap) {
+ public static <K, V> Multimap<K, V> unmodifiableMultimap(Multimap<K, V> delegate) {
+ if (delegate instanceof UnmodifiableMultimap || delegate instanceof ImmutableMultimap) {
return delegate;
}
return new UnmodifiableMultimap<K, V>(delegate);
@@ -394,13 +391,13 @@ public final class Multimaps {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <K, V> Multimap<K, V> unmodifiableMultimap(
- ImmutableMultimap<K, V> delegate) {
+ @Deprecated
+ public static <K, V> Multimap<K, V> unmodifiableMultimap(ImmutableMultimap<K, V> delegate) {
return checkNotNull(delegate);
}
- private static class UnmodifiableMultimap<K, V>
- extends ForwardingMultimap<K, V> implements Serializable {
+ private static class UnmodifiableMultimap<K, V> extends ForwardingMultimap<K, V>
+ implements Serializable {
final Multimap<K, V> delegate;
transient Collection<Entry<K, V>> entries;
transient Multiset<K> keys;
@@ -412,29 +409,36 @@ public final class Multimaps {
this.delegate = checkNotNull(delegate);
}
- @Override protected Multimap<K, V> delegate() {
+ @Override
+ protected Multimap<K, V> delegate() {
return delegate;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
throw new UnsupportedOperationException();
}
- @Override public Map<K, Collection<V>> asMap() {
+ @Override
+ public Map<K, Collection<V>> asMap() {
Map<K, Collection<V>> result = map;
if (result == null) {
- result = map = Collections.unmodifiableMap(
- Maps.transformValues(delegate.asMap(), new Function<Collection<V>, Collection<V>>() {
- @Override
- public Collection<V> apply(Collection<V> collection) {
- return unmodifiableValueCollection(collection);
- }
- }));
+ result = map =
+ Collections.unmodifiableMap(
+ Maps.transformValues(
+ delegate.asMap(),
+ new Function<Collection<V>, Collection<V>>() {
+ @Override
+ public Collection<V> apply(Collection<V> collection) {
+ return unmodifiableValueCollection(collection);
+ }
+ }));
}
return result;
}
- @Override public Collection<Entry<K, V>> entries() {
+ @Override
+ public Collection<Entry<K, V>> entries() {
Collection<Entry<K, V>> result = entries;
if (result == null) {
entries = result = unmodifiableEntries(delegate.entries());
@@ -442,11 +446,13 @@ public final class Multimaps {
return result;
}
- @Override public Collection<V> get(K key) {
+ @Override
+ public Collection<V> get(K key) {
return unmodifiableValueCollection(delegate.get(key));
}
- @Override public Multiset<K> keys() {
+ @Override
+ public Multiset<K> keys() {
Multiset<K> result = keys;
if (result == null) {
keys = result = Multisets.unmodifiableMultiset(delegate.keys());
@@ -454,7 +460,8 @@ public final class Multimaps {
return result;
}
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
Set<K> result = keySet;
if (result == null) {
keySet = result = Collections.unmodifiableSet(delegate.keySet());
@@ -462,11 +469,13 @@ public final class Multimaps {
return result;
}
- @Override public boolean put(K key, V value) {
+ @Override
+ public boolean put(K key, V value) {
throw new UnsupportedOperationException();
}
- @Override public boolean putAll(K key, Iterable<? extends V> values) {
+ @Override
+ public boolean putAll(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
@@ -475,20 +484,23 @@ public final class Multimaps {
throw new UnsupportedOperationException();
}
- @Override public boolean remove(Object key, Object value) {
+ @Override
+ public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
}
- @Override public Collection<V> removeAll(Object key) {
+ @Override
+ public Collection<V> removeAll(Object key) {
throw new UnsupportedOperationException();
}
- @Override public Collection<V> replaceValues(
- K key, Iterable<? extends V> values) {
+ @Override
+ public Collection<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
- @Override public Collection<V> values() {
+ @Override
+ public Collection<V> values() {
Collection<V> result = values;
if (result == null) {
values = result = Collections.unmodifiableCollection(delegate.values());
@@ -499,77 +511,104 @@ public final class Multimaps {
private static final long serialVersionUID = 0;
}
- private static class UnmodifiableListMultimap<K, V>
- extends UnmodifiableMultimap<K, V> implements ListMultimap<K, V> {
+ private static class UnmodifiableListMultimap<K, V> extends UnmodifiableMultimap<K, V>
+ implements ListMultimap<K, V> {
UnmodifiableListMultimap(ListMultimap<K, V> delegate) {
super(delegate);
}
- @Override public ListMultimap<K, V> delegate() {
+
+ @Override
+ public ListMultimap<K, V> delegate() {
return (ListMultimap<K, V>) super.delegate();
}
- @Override public List<V> get(K key) {
+
+ @Override
+ public List<V> get(K key) {
return Collections.unmodifiableList(delegate().get(key));
}
- @Override public List<V> removeAll(Object key) {
+
+ @Override
+ public List<V> removeAll(Object key) {
throw new UnsupportedOperationException();
}
- @Override public List<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public List<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
+
private static final long serialVersionUID = 0;
}
- private static class UnmodifiableSetMultimap<K, V>
- extends UnmodifiableMultimap<K, V> implements SetMultimap<K, V> {
+ private static class UnmodifiableSetMultimap<K, V> extends UnmodifiableMultimap<K, V>
+ implements SetMultimap<K, V> {
UnmodifiableSetMultimap(SetMultimap<K, V> delegate) {
super(delegate);
}
- @Override public SetMultimap<K, V> delegate() {
+
+ @Override
+ public SetMultimap<K, V> delegate() {
return (SetMultimap<K, V>) super.delegate();
}
- @Override public Set<V> get(K key) {
+
+ @Override
+ public Set<V> get(K key) {
/*
* Note that this doesn't return a SortedSet when delegate is a
* SortedSetMultiset, unlike (SortedSet<V>) super.get().
*/
return Collections.unmodifiableSet(delegate().get(key));
}
- @Override public Set<Map.Entry<K, V>> entries() {
+
+ @Override
+ public Set<Map.Entry<K, V>> entries() {
return Maps.unmodifiableEntrySet(delegate().entries());
}
- @Override public Set<V> removeAll(Object key) {
+
+ @Override
+ public Set<V> removeAll(Object key) {
throw new UnsupportedOperationException();
}
- @Override public Set<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public Set<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
+
private static final long serialVersionUID = 0;
}
- private static class UnmodifiableSortedSetMultimap<K, V>
- extends UnmodifiableSetMultimap<K, V> implements SortedSetMultimap<K, V> {
+ private static class UnmodifiableSortedSetMultimap<K, V> extends UnmodifiableSetMultimap<K, V>
+ implements SortedSetMultimap<K, V> {
UnmodifiableSortedSetMultimap(SortedSetMultimap<K, V> delegate) {
super(delegate);
}
- @Override public SortedSetMultimap<K, V> delegate() {
+
+ @Override
+ public SortedSetMultimap<K, V> delegate() {
return (SortedSetMultimap<K, V>) super.delegate();
}
- @Override public SortedSet<V> get(K key) {
+
+ @Override
+ public SortedSet<V> get(K key) {
return Collections.unmodifiableSortedSet(delegate().get(key));
}
- @Override public SortedSet<V> removeAll(Object key) {
+
+ @Override
+ public SortedSet<V> removeAll(Object key) {
throw new UnsupportedOperationException();
}
- @Override public SortedSet<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
+
@Override
public Comparator<? super V> valueComparator() {
return delegate().valueComparator();
}
+
private static final long serialVersionUID = 0;
}
@@ -585,8 +624,7 @@ public final class Multimaps {
* @param multimap the multimap to be wrapped
* @return a synchronized view of the specified multimap
*/
- public static <K, V> SetMultimap<K, V> synchronizedSetMultimap(
- SetMultimap<K, V> multimap) {
+ public static <K, V> SetMultimap<K, V> synchronizedSetMultimap(SetMultimap<K, V> multimap) {
return Synchronized.setMultimap(multimap, null);
}
@@ -608,10 +646,8 @@ public final class Multimaps {
* returned
* @return an unmodifiable view of the specified multimap
*/
- public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
- SetMultimap<K, V> delegate) {
- if (delegate instanceof UnmodifiableSetMultimap ||
- delegate instanceof ImmutableSetMultimap) {
+ public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(SetMultimap<K, V> delegate) {
+ if (delegate instanceof UnmodifiableSetMultimap || delegate instanceof ImmutableSetMultimap) {
return delegate;
}
return new UnmodifiableSetMultimap<K, V>(delegate);
@@ -623,7 +659,8 @@ public final class Multimaps {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
+ @Deprecated
+ public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
ImmutableSetMultimap<K, V> delegate) {
return checkNotNull(delegate);
}
@@ -640,8 +677,8 @@ public final class Multimaps {
* @param multimap the multimap to be wrapped
* @return a synchronized view of the specified multimap
*/
- public static <K, V> SortedSetMultimap<K, V>
- synchronizedSortedSetMultimap(SortedSetMultimap<K, V> multimap) {
+ public static <K, V> SortedSetMultimap<K, V> synchronizedSortedSetMultimap(
+ SortedSetMultimap<K, V> multimap) {
return Synchronized.sortedSetMultimap(multimap, null);
}
@@ -680,8 +717,7 @@ public final class Multimaps {
* @param multimap the multimap to be wrapped
* @return a synchronized view of the specified multimap
*/
- public static <K, V> ListMultimap<K, V> synchronizedListMultimap(
- ListMultimap<K, V> multimap) {
+ public static <K, V> ListMultimap<K, V> synchronizedListMultimap(ListMultimap<K, V> multimap) {
return Synchronized.listMultimap(multimap, null);
}
@@ -703,10 +739,8 @@ public final class Multimaps {
* returned
* @return an unmodifiable view of the specified multimap
*/
- public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
- ListMultimap<K, V> delegate) {
- if (delegate instanceof UnmodifiableListMultimap ||
- delegate instanceof ImmutableListMultimap) {
+ public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(ListMultimap<K, V> delegate) {
+ if (delegate instanceof UnmodifiableListMultimap || delegate instanceof ImmutableListMultimap) {
return delegate;
}
return new UnmodifiableListMultimap<K, V>(delegate);
@@ -718,7 +752,8 @@ public final class Multimaps {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
+ @Deprecated
+ public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
ImmutableListMultimap<K, V> delegate) {
return checkNotNull(delegate);
}
@@ -731,8 +766,7 @@ public final class Multimaps {
* @param collection the collection for which to return an unmodifiable view
* @return an unmodifiable view of the collection
*/
- private static <V> Collection<V> unmodifiableValueCollection(
- Collection<V> collection) {
+ private static <V> Collection<V> unmodifiableValueCollection(Collection<V> collection) {
if (collection instanceof SortedSet) {
return Collections.unmodifiableSortedSet((SortedSet<V>) collection);
} else if (collection instanceof Set) {
@@ -757,8 +791,7 @@ public final class Multimaps {
if (entries instanceof Set) {
return Maps.unmodifiableEntrySet((Set<Entry<K, V>>) entries);
}
- return new Maps.UnmodifiableEntries<K, V>(
- Collections.unmodifiableCollection(entries));
+ return new Maps.UnmodifiableEntries<K, V>(Collections.unmodifiableCollection(entries));
}
/**
@@ -797,8 +830,7 @@ public final class Multimaps {
@Beta
@SuppressWarnings("unchecked")
// safe by specification of SortedSetMultimap.asMap()
- public static <K, V> Map<K, SortedSet<V>> asMap(
- SortedSetMultimap<K, V> multimap) {
+ public static <K, V> Map<K, SortedSet<V>> asMap(SortedSetMultimap<K, V> multimap) {
return (Map<K, SortedSet<V>>) (Map<K, ?>) multimap.asMap();
}
@@ -835,8 +867,8 @@ public final class Multimaps {
}
/** @see Multimaps#forMap */
- private static class MapMultimap<K, V>
- extends AbstractMultimap<K, V> implements SetMultimap<K, V>, Serializable {
+ private static class MapMultimap<K, V> extends AbstractMultimap<K, V>
+ implements SetMultimap<K, V>, Serializable {
final Map<K, V> map;
MapMultimap(Map<K, V> map) {
@@ -866,7 +898,8 @@ public final class Multimaps {
@Override
public Set<V> get(final K key) {
return new Sets.ImprovedAbstractSet<V>() {
- @Override public Iterator<V> iterator() {
+ @Override
+ public Iterator<V> iterator() {
return new Iterator<V>() {
int i;
@@ -893,7 +926,8 @@ public final class Multimaps {
};
}
- @Override public int size() {
+ @Override
+ public int size() {
return map.containsKey(key) ? 1 : 0;
}
};
@@ -953,7 +987,7 @@ public final class Multimaps {
public Set<Entry<K, V>> entries() {
return map.entrySet();
}
-
+
@Override
Iterator<Entry<K, V>> entryIterator() {
return map.entrySet().iterator();
@@ -964,10 +998,11 @@ public final class Multimaps {
return new AsMap<K, V>(this);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return map.hashCode();
}
-
+
private static final long serialVersionUID = 7845222491160860175L;
}
@@ -1078,25 +1113,23 @@ public final class Multimaps {
* @since 7.0
*/
public static <K, V1, V2> Multimap<K, V2> transformEntries(
- Multimap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ Multimap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
return new TransformedEntriesMultimap<K, V1, V2>(fromMap, transformer);
}
- private static class TransformedEntriesMultimap<K, V1, V2>
- extends AbstractMultimap<K, V2> {
+ private static class TransformedEntriesMultimap<K, V1, V2> extends AbstractMultimap<K, V2> {
final Multimap<K, V1> fromMultimap;
final EntryTransformer<? super K, ? super V1, V2> transformer;
- TransformedEntriesMultimap(Multimap<K, V1> fromMultimap,
+ TransformedEntriesMultimap(
+ Multimap<K, V1> fromMultimap,
final EntryTransformer<? super K, ? super V1, V2> transformer) {
this.fromMultimap = checkNotNull(fromMultimap);
this.transformer = checkNotNull(transformer);
}
Collection<V2> transform(K key, Collection<V1> values) {
- Function<? super V1, V2> function =
- Maps.asValueToValueFunction(transformer, key);
+ Function<? super V1, V2> function = Maps.asValueToValueFunction(transformer, key);
if (values instanceof List) {
return Lists.transform((List<V1>) values, function);
} else {
@@ -1106,77 +1139,89 @@ public final class Multimaps {
@Override
Map<K, Collection<V2>> createAsMap() {
- return Maps.transformEntries(fromMultimap.asMap(),
+ return Maps.transformEntries(
+ fromMultimap.asMap(),
new EntryTransformer<K, Collection<V1>, Collection<V2>>() {
- @Override public Collection<V2> transformEntry(
- K key, Collection<V1> value) {
- return transform(key, value);
- }
- });
+ @Override
+ public Collection<V2> transformEntry(K key, Collection<V1> value) {
+ return transform(key, value);
+ }
+ });
}
- @Override public void clear() {
+ @Override
+ public void clear() {
fromMultimap.clear();
}
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return fromMultimap.containsKey(key);
}
@Override
Iterator<Entry<K, V2>> entryIterator() {
- return Iterators.transform(fromMultimap.entries().iterator(),
- Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
+ return Iterators.transform(
+ fromMultimap.entries().iterator(), Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
}
- @Override public Collection<V2> get(final K key) {
+ @Override
+ public Collection<V2> get(final K key) {
return transform(key, fromMultimap.get(key));
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return fromMultimap.isEmpty();
}
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
return fromMultimap.keySet();
}
- @Override public Multiset<K> keys() {
+ @Override
+ public Multiset<K> keys() {
return fromMultimap.keys();
}
- @Override public boolean put(K key, V2 value) {
+ @Override
+ public boolean put(K key, V2 value) {
throw new UnsupportedOperationException();
}
- @Override public boolean putAll(K key, Iterable<? extends V2> values) {
+ @Override
+ public boolean putAll(K key, Iterable<? extends V2> values) {
throw new UnsupportedOperationException();
}
- @Override public boolean putAll(
- Multimap<? extends K, ? extends V2> multimap) {
+ @Override
+ public boolean putAll(Multimap<? extends K, ? extends V2> multimap) {
throw new UnsupportedOperationException();
}
@SuppressWarnings("unchecked")
- @Override public boolean remove(Object key, Object value) {
+ @Override
+ public boolean remove(Object key, Object value) {
return get((K) key).remove(value);
}
@SuppressWarnings("unchecked")
- @Override public Collection<V2> removeAll(Object key) {
+ @Override
+ public Collection<V2> removeAll(Object key) {
return transform((K) key, fromMultimap.removeAll(key));
}
- @Override public Collection<V2> replaceValues(
- K key, Iterable<? extends V2> values) {
+ @Override
+ public Collection<V2> replaceValues(K key, Iterable<? extends V2> values) {
throw new UnsupportedOperationException();
}
- @Override public int size() {
+ @Override
+ public int size() {
return fromMultimap.size();
}
-
+
@Override
Collection<V2> createValues() {
return Collections2.transform(
@@ -1226,8 +1271,7 @@ public final class Multimaps {
* @since 7.0
*/
public static <K, V1, V2> ListMultimap<K, V2> transformValues(
- ListMultimap<K, V1> fromMultimap,
- final Function<? super V1, V2> function) {
+ ListMultimap<K, V1> fromMultimap, final Function<? super V1, V2> function) {
checkNotNull(function);
EntryTransformer<K, V1, V2> transformer = Maps.asEntryTransformer(function);
return transformEntries(fromMultimap, transformer);
@@ -1286,35 +1330,36 @@ public final class Multimaps {
* @since 7.0
*/
public static <K, V1, V2> ListMultimap<K, V2> transformEntries(
- ListMultimap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ ListMultimap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
return new TransformedEntriesListMultimap<K, V1, V2>(fromMap, transformer);
}
private static final class TransformedEntriesListMultimap<K, V1, V2>
- extends TransformedEntriesMultimap<K, V1, V2>
- implements ListMultimap<K, V2> {
+ extends TransformedEntriesMultimap<K, V1, V2> implements ListMultimap<K, V2> {
- TransformedEntriesListMultimap(ListMultimap<K, V1> fromMultimap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ TransformedEntriesListMultimap(
+ ListMultimap<K, V1> fromMultimap, EntryTransformer<? super K, ? super V1, V2> transformer) {
super(fromMultimap, transformer);
}
- @Override List<V2> transform(K key, Collection<V1> values) {
+ @Override
+ List<V2> transform(K key, Collection<V1> values) {
return Lists.transform((List<V1>) values, Maps.asValueToValueFunction(transformer, key));
}
- @Override public List<V2> get(K key) {
+ @Override
+ public List<V2> get(K key) {
return transform(key, fromMultimap.get(key));
}
@SuppressWarnings("unchecked")
- @Override public List<V2> removeAll(Object key) {
+ @Override
+ public List<V2> removeAll(Object key) {
return transform((K) key, fromMultimap.removeAll(key));
}
- @Override public List<V2> replaceValues(
- K key, Iterable<? extends V2> values) {
+ @Override
+ public List<V2> replaceValues(K key, Iterable<? extends V2> values) {
throw new UnsupportedOperationException();
}
}
@@ -1412,8 +1457,7 @@ public final class Multimaps {
public static <K, V> ImmutableListMultimap<K, V> index(
Iterator<V> values, Function<? super V, K> keyFunction) {
checkNotNull(keyFunction);
- ImmutableListMultimap.Builder<K, V> builder
- = ImmutableListMultimap.builder();
+ ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
while (values.hasNext()) {
V value = values.next();
checkNotNull(value, values);
@@ -1423,18 +1467,18 @@ public final class Multimaps {
}
static class Keys<K, V> extends AbstractMultiset<K> {
- final Multimap<K, V> multimap;
-
+ @Weak final Multimap<K, V> multimap;
+
Keys(Multimap<K, V> multimap) {
this.multimap = multimap;
}
- @Override Iterator<Multiset.Entry<K>> entryIterator() {
+ @Override
+ Iterator<Multiset.Entry<K>> entryIterator() {
return new TransformedIterator<Map.Entry<K, Collection<V>>, Multiset.Entry<K>>(
multimap.asMap().entrySet().iterator()) {
@Override
- Multiset.Entry<K> transform(
- final Map.Entry<K, Collection<V>> backingEntry) {
+ Multiset.Entry<K> transform(final Map.Entry<K, Collection<V>> backingEntry) {
return new Multisets.AbstractEntry<K>() {
@Override
public K getElement() {
@@ -1450,32 +1494,40 @@ public final class Multimaps {
};
}
- @Override int distinctElements() {
+ @Override
+ int distinctElements() {
return multimap.asMap().size();
}
- @Override Set<Multiset.Entry<K>> createEntrySet() {
+ @Override
+ Set<Multiset.Entry<K>> createEntrySet() {
return new KeysEntrySet();
}
+ @WeakOuter
class KeysEntrySet extends Multisets.EntrySet<K> {
- @Override Multiset<K> multiset() {
+ @Override
+ Multiset<K> multiset() {
return Keys.this;
}
- @Override public Iterator<Multiset.Entry<K>> iterator() {
+ @Override
+ public Iterator<Multiset.Entry<K>> iterator() {
return entryIterator();
}
- @Override public int size() {
+ @Override
+ public int size() {
return distinctElements();
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return multimap.isEmpty();
}
- @Override public boolean contains(@Nullable Object o) {
+ @Override
+ public boolean contains(@Nullable Object o) {
if (o instanceof Multiset.Entry) {
Multiset.Entry<?> entry = (Multiset.Entry<?>) o;
Collection<V> collection = multimap.asMap().get(entry.getElement());
@@ -1484,7 +1536,8 @@ public final class Multimaps {
return false;
}
- @Override public boolean remove(@Nullable Object o) {
+ @Override
+ public boolean remove(@Nullable Object o) {
if (o instanceof Multiset.Entry) {
Multiset.Entry<?> entry = (Multiset.Entry<?>) o;
Collection<V> collection = multimap.asMap().get(entry.getElement());
@@ -1497,20 +1550,24 @@ public final class Multimaps {
}
}
- @Override public boolean contains(@Nullable Object element) {
+ @Override
+ public boolean contains(@Nullable Object element) {
return multimap.containsKey(element);
}
- @Override public Iterator<K> iterator() {
+ @Override
+ public Iterator<K> iterator() {
return Maps.keyIterator(multimap.entries().iterator());
}
- @Override public int count(@Nullable Object element) {
+ @Override
+ public int count(@Nullable Object element) {
Collection<V> values = Maps.safeGet(multimap.asMap(), element);
return (values == null) ? 0 : values.size();
}
- @Override public int remove(@Nullable Object element, int occurrences) {
+ @Override
+ public int remove(@Nullable Object element, int occurrences) {
checkNonnegative(occurrences, "occurrences");
if (occurrences == 0) {
return count(element);
@@ -1535,11 +1592,13 @@ public final class Multimaps {
return oldCount;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
multimap.clear();
}
- @Override public Set<K> elementSet() {
+ @Override
+ public Set<K> elementSet() {
return multimap.keySet();
}
}
@@ -1547,15 +1606,16 @@ public final class Multimaps {
/**
* A skeleton implementation of {@link Multimap#entries()}.
*/
- abstract static class Entries<K, V> extends
- AbstractCollection<Map.Entry<K, V>> {
+ abstract static class Entries<K, V> extends AbstractCollection<Map.Entry<K, V>> {
abstract Multimap<K, V> multimap();
- @Override public int size() {
+ @Override
+ public int size() {
return multimap().size();
}
- @Override public boolean contains(@Nullable Object o) {
+ @Override
+ public boolean contains(@Nullable Object o) {
if (o instanceof Map.Entry) {
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
return multimap().containsEntry(entry.getKey(), entry.getValue());
@@ -1563,7 +1623,8 @@ public final class Multimaps {
return false;
}
- @Override public boolean remove(@Nullable Object o) {
+ @Override
+ public boolean remove(@Nullable Object o) {
if (o instanceof Map.Entry) {
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
return multimap().remove(entry.getKey(), entry.getValue());
@@ -1571,7 +1632,8 @@ public final class Multimaps {
return false;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
multimap().clear();
}
}
@@ -1579,19 +1641,20 @@ public final class Multimaps {
/**
* A skeleton implementation of {@link Multimap#asMap()}.
*/
- static final class AsMap<K, V> extends
- Maps.ImprovedAbstractMap<K, Collection<V>> {
- private final Multimap<K, V> multimap;
-
+ static final class AsMap<K, V> extends Maps.ViewCachingAbstractMap<K, Collection<V>> {
+ @Weak private final Multimap<K, V> multimap;
+
AsMap(Multimap<K, V> multimap) {
this.multimap = checkNotNull(multimap);
}
- @Override public int size() {
+ @Override
+ public int size() {
return multimap.keySet().size();
}
- @Override protected Set<Entry<K, Collection<V>>> createEntrySet() {
+ @Override
+ protected Set<Entry<K, Collection<V>>> createEntrySet() {
return new EntrySet();
}
@@ -1599,21 +1662,27 @@ public final class Multimaps {
multimap.keySet().remove(key);
}
+ @WeakOuter
class EntrySet extends Maps.EntrySet<K, Collection<V>> {
- @Override Map<K, Collection<V>> map() {
+ @Override
+ Map<K, Collection<V>> map() {
return AsMap.this;
}
- @Override public Iterator<Entry<K, Collection<V>>> iterator() {
- return Maps.asMapEntryIterator(multimap.keySet(), new Function<K, Collection<V>>() {
- @Override
- public Collection<V> apply(K key) {
- return multimap.get(key);
- }
- });
+ @Override
+ public Iterator<Entry<K, Collection<V>>> iterator() {
+ return Maps.asMapEntryIterator(
+ multimap.keySet(),
+ new Function<K, Collection<V>>() {
+ @Override
+ public Collection<V> apply(K key) {
+ return multimap.get(key);
+ }
+ });
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
if (!contains(o)) {
return false;
}
@@ -1624,27 +1693,33 @@ public final class Multimaps {
}
@SuppressWarnings("unchecked")
- @Override public Collection<V> get(Object key) {
+ @Override
+ public Collection<V> get(Object key) {
return containsKey(key) ? multimap.get((K) key) : null;
}
- @Override public Collection<V> remove(Object key) {
+ @Override
+ public Collection<V> remove(Object key) {
return containsKey(key) ? multimap.removeAll(key) : null;
}
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
return multimap.keySet();
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return multimap.isEmpty();
}
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return multimap.containsKey(key);
}
- @Override public void clear() {
+ @Override
+ public void clear() {
multimap.clear();
}
}
@@ -1679,6 +1754,7 @@ public final class Multimaps {
*
* @since 11.0
*/
+ @CheckReturnValue
public static <K, V> Multimap<K, V> filterKeys(
Multimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
if (unfiltered instanceof SetMultimap) {
@@ -1687,8 +1763,8 @@ public final class Multimaps {
return filterKeys((ListMultimap<K, V>) unfiltered, keyPredicate);
} else if (unfiltered instanceof FilteredKeyMultimap) {
FilteredKeyMultimap<K, V> prev = (FilteredKeyMultimap<K, V>) unfiltered;
- return new FilteredKeyMultimap<K, V>(prev.unfiltered,
- Predicates.and(prev.keyPredicate, keyPredicate));
+ return new FilteredKeyMultimap<K, V>(
+ prev.unfiltered, Predicates.and(prev.keyPredicate, keyPredicate));
} else if (unfiltered instanceof FilteredMultimap) {
FilteredMultimap<K, V> prev = (FilteredMultimap<K, V>) unfiltered;
return filterFiltered(prev, Maps.<K>keyPredicateOnEntries(keyPredicate));
@@ -1696,7 +1772,7 @@ public final class Multimaps {
return new FilteredKeyMultimap<K, V>(unfiltered, keyPredicate);
}
}
-
+
/**
* Returns a multimap containing the mappings in {@code unfiltered} whose keys
* satisfy a predicate. The returned multimap is a live view of
@@ -1727,12 +1803,13 @@ public final class Multimaps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> SetMultimap<K, V> filterKeys(
SetMultimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
if (unfiltered instanceof FilteredKeySetMultimap) {
FilteredKeySetMultimap<K, V> prev = (FilteredKeySetMultimap<K, V>) unfiltered;
- return new FilteredKeySetMultimap<K, V>(prev.unfiltered(),
- Predicates.and(prev.keyPredicate, keyPredicate));
+ return new FilteredKeySetMultimap<K, V>(
+ prev.unfiltered(), Predicates.and(prev.keyPredicate, keyPredicate));
} else if (unfiltered instanceof FilteredSetMultimap) {
FilteredSetMultimap<K, V> prev = (FilteredSetMultimap<K, V>) unfiltered;
return filterFiltered(prev, Maps.<K>keyPredicateOnEntries(keyPredicate));
@@ -1740,7 +1817,7 @@ public final class Multimaps {
return new FilteredKeySetMultimap<K, V>(unfiltered, keyPredicate);
}
}
-
+
/**
* Returns a multimap containing the mappings in {@code unfiltered} whose keys
* satisfy a predicate. The returned multimap is a live view of
@@ -1771,12 +1848,13 @@ public final class Multimaps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> ListMultimap<K, V> filterKeys(
ListMultimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
if (unfiltered instanceof FilteredKeyListMultimap) {
FilteredKeyListMultimap<K, V> prev = (FilteredKeyListMultimap<K, V>) unfiltered;
- return new FilteredKeyListMultimap<K, V>(prev.unfiltered(),
- Predicates.and(prev.keyPredicate, keyPredicate));
+ return new FilteredKeyListMultimap<K, V>(
+ prev.unfiltered(), Predicates.and(prev.keyPredicate, keyPredicate));
} else {
return new FilteredKeyListMultimap<K, V>(unfiltered, keyPredicate);
}
@@ -1812,11 +1890,12 @@ public final class Multimaps {
*
* @since 11.0
*/
+ @CheckReturnValue
public static <K, V> Multimap<K, V> filterValues(
Multimap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
}
-
+
/**
* Returns a multimap containing the mappings in {@code unfiltered} whose values
* satisfy a predicate. The returned multimap is a live view of
@@ -1847,6 +1926,7 @@ public final class Multimaps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> SetMultimap<K, V> filterValues(
SetMultimap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -1880,6 +1960,7 @@ public final class Multimaps {
*
* @since 11.0
*/
+ @CheckReturnValue
public static <K, V> Multimap<K, V> filterEntries(
Multimap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
checkNotNull(entryPredicate);
@@ -1890,7 +1971,7 @@ public final class Multimaps {
? filterFiltered((FilteredMultimap<K, V>) unfiltered, entryPredicate)
: new FilteredEntryMultimap<K, V>(checkNotNull(unfiltered), entryPredicate);
}
-
+
/**
* Returns a multimap containing the mappings in {@code unfiltered} that
* satisfy a predicate. The returned multimap is a live view of
@@ -1919,6 +2000,7 @@ public final class Multimaps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> SetMultimap<K, V> filterEntries(
SetMultimap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
checkNotNull(entryPredicate);
@@ -1934,10 +2016,9 @@ public final class Multimaps {
* operations would fail. This method combines the predicates to avoid that
* problem.
*/
- private static <K, V> Multimap<K, V> filterFiltered(FilteredMultimap<K, V> multimap,
- Predicate<? super Entry<K, V>> entryPredicate) {
- Predicate<Entry<K, V>> predicate
- = Predicates.and(multimap.entryPredicate(), entryPredicate);
+ private static <K, V> Multimap<K, V> filterFiltered(
+ FilteredMultimap<K, V> multimap, Predicate<? super Entry<K, V>> entryPredicate) {
+ Predicate<Entry<K, V>> predicate = Predicates.and(multimap.entryPredicate(), entryPredicate);
return new FilteredEntryMultimap<K, V>(multimap.unfiltered(), predicate);
}
@@ -1948,13 +2029,11 @@ public final class Multimaps {
* avoid that problem.
*/
private static <K, V> SetMultimap<K, V> filterFiltered(
- FilteredSetMultimap<K, V> multimap,
- Predicate<? super Entry<K, V>> entryPredicate) {
- Predicate<Entry<K, V>> predicate
- = Predicates.and(multimap.entryPredicate(), entryPredicate);
+ FilteredSetMultimap<K, V> multimap, Predicate<? super Entry<K, V>> entryPredicate) {
+ Predicate<Entry<K, V>> predicate = Predicates.and(multimap.entryPredicate(), entryPredicate);
return new FilteredEntrySetMultimap<K, V>(multimap.unfiltered(), predicate);
}
-
+
static boolean equalsImpl(Multimap<?, ?> multimap, @Nullable Object object) {
if (object == multimap) {
return true;
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ObjectArrays.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ObjectArrays.java
index 340985c..73d7573 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ObjectArrays.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/ObjectArrays.java
@@ -28,7 +28,7 @@ import javax.annotation.Nullable;
* Static utility methods pertaining to object arrays.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class ObjectArrays {
@@ -81,8 +81,7 @@ public final class ObjectArrays {
/** GWT safe version of Arrays.copyOf. */
static <T> T[] arraysCopyOf(T[] original, int newLength) {
T[] copy = newArray(original, newLength);
- System.arraycopy(
- original, 0, copy, 0, Math.min(original.length, newLength));
+ System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
@@ -121,7 +120,7 @@ public final class ObjectArrays {
}
return array;
}
-
+
/**
* Implementation of {@link Collection#toArray(Object[])} for collections backed by an object
* array. the runtime type of the returned array is that of the specified array. If the collection
@@ -196,7 +195,7 @@ public final class ObjectArrays {
static Object[] checkElementsNotNull(Object... array) {
return checkElementsNotNull(array, array.length);
}
-
+
static Object[] checkElementsNotNull(Object[] array, int length) {
for (int i = 0; i < length; i++) {
checkElementNotNull(array[i], i);
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Platform.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Platform.java
index 3af12bd..be5b600 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Platform.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Platform.java
@@ -26,7 +26,9 @@ import java.io.Serializable;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.Map;
+import java.util.Queue;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
@@ -141,5 +143,9 @@ final class Platform {
return Maps.filterSortedIgnoreNavigable(unfiltered, predicate);
}
+ static <E> Queue<E> newFastestQueue(int ignored) {
+ return new LinkedList<E>();
+ }
+
private Platform() {}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularContiguousSet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularContiguousSet.java
index 0a30c0a..e57973a 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularContiguousSet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularContiguousSet.java
@@ -45,26 +45,31 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
: new EmptyContiguousSet<C>(domain);
}
- @Override ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
+ @Override
+ ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
return intersectionInCurrentDomain(Range.upTo(toElement, BoundType.forBoolean(inclusive)));
}
- @Override ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive, C toElement,
- boolean toInclusive) {
+ @Override
+ ContiguousSet<C> subSetImpl(
+ C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
if (fromElement.compareTo(toElement) == 0 && !fromInclusive && !toInclusive) {
// Range would reject our attempt to create (x, x).
return new EmptyContiguousSet<C>(domain);
}
- return intersectionInCurrentDomain(Range.range(
- fromElement, BoundType.forBoolean(fromInclusive),
- toElement, BoundType.forBoolean(toInclusive)));
+ return intersectionInCurrentDomain(
+ Range.range(
+ fromElement, BoundType.forBoolean(fromInclusive),
+ toElement, BoundType.forBoolean(toInclusive)));
}
- @Override ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive) {
+ @Override
+ ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive) {
return intersectionInCurrentDomain(Range.downTo(fromElement, BoundType.forBoolean(inclusive)));
}
- @Override public UnmodifiableIterator<C> iterator() {
+ @Override
+ public UnmodifiableIterator<C> iterator() {
return new AbstractSequentialIterator<C>(first()) {
final C last = last();
@@ -79,24 +84,29 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
return right != null && Range.compareOrThrow(left, right) == 0;
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return false;
}
- @Override public C first() {
+ @Override
+ public C first() {
return range.lowerBound.leastValueAbove(domain);
}
- @Override public C last() {
+ @Override
+ public C last() {
return range.upperBound.greatestValueBelow(domain);
}
- @Override public int size() {
+ @Override
+ public int size() {
long distance = domain.distance(first(), last());
return (distance >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) distance + 1;
}
- @Override public boolean contains(@Nullable Object object) {
+ @Override
+ public boolean contains(@Nullable Object object) {
if (object == null) {
return false;
}
@@ -107,15 +117,18 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
}
}
- @Override public boolean containsAll(Collection<?> targets) {
+ @Override
+ public boolean containsAll(Collection<?> targets) {
return Collections2.containsAllImpl(this, targets);
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public ContiguousSet<C> intersection(ContiguousSet<C> other) {
+ @Override
+ public ContiguousSet<C> intersection(ContiguousSet<C> other) {
checkNotNull(other);
checkArgument(this.domain.equals(other.domain));
if (other.isEmpty()) {
@@ -129,30 +142,34 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
}
}
- @Override public Range<C> range() {
+ @Override
+ public Range<C> range() {
return range(CLOSED, CLOSED);
}
- @Override public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
- return Range.create(range.lowerBound.withLowerBoundType(lowerBoundType, domain),
+ @Override
+ public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
+ return Range.create(
+ range.lowerBound.withLowerBoundType(lowerBoundType, domain),
range.upperBound.withUpperBoundType(upperBoundType, domain));
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
} else if (object instanceof RegularContiguousSet) {
RegularContiguousSet<?> that = (RegularContiguousSet<?>) object;
if (this.domain.equals(that.domain)) {
- return this.first().equals(that.first())
- && this.last().equals(that.last());
+ return this.first().equals(that.first()) && this.last().equals(that.last());
}
}
return super.equals(object);
}
// copied to make sure not to use the GWT-emulated version
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Sets.hashCodeImpl(this);
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableAsList.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableAsList.java
index bd6e43d..c774525 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableAsList.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableAsList.java
@@ -17,6 +17,7 @@
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.Weak;
/**
* An {@link ImmutableAsList} implementation specialized for when the delegate collection is
@@ -27,7 +28,7 @@ import com.google.common.annotations.GwtCompatible;
@GwtCompatible(emulated = true)
@SuppressWarnings("serial") // uses writeReplace, not default serialization
class RegularImmutableAsList<E> extends ImmutableAsList<E> {
- private final ImmutableCollection<E> delegate;
+ @Weak private final ImmutableCollection<E> delegate;
private final ImmutableList<? extends E> delegateList;
RegularImmutableAsList(ImmutableCollection<E> delegate, ImmutableList<? extends E> delegateList) {
@@ -48,7 +49,7 @@ class RegularImmutableAsList<E> extends ImmutableAsList<E> {
return delegateList;
}
- @SuppressWarnings("unchecked") // safe covariant cast!
+ @SuppressWarnings("unchecked") // safe covariant cast!
@Override
public UnmodifiableListIterator<E> listIterator(int index) {
return (UnmodifiableListIterator<E>) delegateList.listIterator(index);
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableBiMap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableBiMap.java
index 5b4e851..cc3b1a7 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableBiMap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableBiMap.java
@@ -16,6 +16,8 @@
package com.google.common.collect;
+import java.util.HashMap;
+
/**
* GWT emulation of {@link RegularImmutableBiMap}.
*
@@ -24,10 +26,17 @@ package com.google.common.collect;
*/
@SuppressWarnings("serial")
class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
+ static final RegularImmutableBiMap<Object, Object> EMPTY =
+ new RegularImmutableBiMap<Object, Object>();
// This reference is used both by the GWT compiler to infer the elements
// of the lists that needs to be serialized.
private ImmutableBiMap<V, K> inverse;
+
+ RegularImmutableBiMap() {
+ super(new RegularImmutableMap<K, V>(new HashMap<K, V>()));
+ this.inverse = (ImmutableBiMap<V, K>) this;
+ }
RegularImmutableBiMap(ImmutableMap<K, V> delegate) {
super(delegate);
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSet.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSet.java
index 72da3e4..7245096 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSet.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSet.java
@@ -16,8 +16,7 @@
package com.google.common.collect;
-import static com.google.common.base.Preconditions.checkArgument;
-
+import java.util.Collections;
import java.util.Set;
/**
@@ -26,11 +25,10 @@ import java.util.Set;
* @author Hayward Chan
*/
final class RegularImmutableSet<E> extends ForwardingImmutableSet<E> {
+ static final RegularImmutableSet<Object> EMPTY = new RegularImmutableSet<Object>(
+ Collections.emptySet());
+
RegularImmutableSet(Set<E> delegate) {
super(delegate);
-
- // Required for GWT deserialization because the server-side implementation
- // requires this.
- checkArgument(delegate.size() >= 2);
}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Sets.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Sets.java
index 2a0c594..eb2634c 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Sets.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Sets.java
@@ -41,6 +41,7 @@ import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -48,13 +49,13 @@ import javax.annotation.Nullable;
* class's counterparts {@link Lists}, {@link Maps} and {@link Queues}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Sets">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#sets">
* {@code Sets}</a>.
*
* @author Kevin Bourrillion
* @author Jared Levy
* @author Chris Povirk
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Sets {
@@ -107,8 +108,7 @@ public final class Sets {
*/
// http://code.google.com/p/google-web-toolkit/issues/detail?id=3028
@GwtCompatible(serializable = true)
- public static <E extends Enum<E>> ImmutableSet<E> immutableEnumSet(
- Iterable<E> elements) {
+ public static <E extends Enum<E>> ImmutableSet<E> immutableEnumSet(Iterable<E> elements) {
if (elements instanceof ImmutableEnumSet) {
return (ImmutableEnumSet<E>) elements;
} else if (elements instanceof Collection) {
@@ -131,13 +131,12 @@ public final class Sets {
}
/**
- * Returns a new {@code EnumSet} instance containing the given elements.
- * Unlike {@link EnumSet#copyOf(Collection)}, this method does not produce an
- * exception on an empty collection, and it may be called on any iterable, not
- * just a {@code Collection}.
+ * Returns a new, <i>mutable</i> {@code EnumSet} instance containing the given elements in their
+ * natural order. This method behaves identically to {@link EnumSet#copyOf(Collection)}, but also
+ * accepts non-{@code Collection} iterables and empty iterables.
*/
- public static <E extends Enum<E>> EnumSet<E> newEnumSet(Iterable<E> iterable,
- Class<E> elementType) {
+ public static <E extends Enum<E>> EnumSet<E> newEnumSet(
+ Iterable<E> iterable, Class<E> elementType) {
EnumSet<E> set = EnumSet.noneOf(elementType);
Iterables.addAll(set, iterable);
return set;
@@ -146,33 +145,33 @@ public final class Sets {
// HashSet
/**
- * Creates a <i>mutable</i>, empty {@code HashSet} instance.
+ * Creates a <i>mutable</i>, initially empty {@code HashSet} instance.
*
- * <p><b>Note:</b> if mutability is not required, use {@link
- * ImmutableSet#of()} instead.
+ * <p><b>Note:</b> if mutability is not required, use {@link ImmutableSet#of()} instead. If
+ * {@code E} is an {@link Enum} type, use {@link EnumSet#noneOf} instead. Otherwise, strongly
+ * consider using a {@code LinkedHashSet} instead, at the cost of increased memory footprint, to
+ * get deterministic iteration behavior.
*
- * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link
- * EnumSet#noneOf} instead.
- *
- * @return a new, empty {@code HashSet}
+ * <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as
+ * deprecated. Instead, use the {@code HashSet} constructor directly, taking advantage of the new
+ * <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
*/
public static <E> HashSet<E> newHashSet() {
return new HashSet<E>();
}
/**
- * Creates a <i>mutable</i> {@code HashSet} instance containing the given
- * elements in unspecified order.
+ * Creates a <i>mutable</i> {@code HashSet} instance initially containing the given elements.
*
- * <p><b>Note:</b> if mutability is not required and the elements are
- * non-null, use an overload of {@link ImmutableSet#of()} (for varargs) or
- * {@link ImmutableSet#copyOf(Object[])} (for an array) instead.
+ * <p><b>Note:</b> if elements are non-null and won't be added or removed after this point, use
+ * {@link ImmutableSet#of()} or {@link ImmutableSet#copyOf(Object[])} instead. If {@code E} is an
+ * {@link Enum} type, use {@link EnumSet#of(Enum, Enum[])} instead. Otherwise, strongly consider
+ * using a {@code LinkedHashSet} instead, at the cost of increased memory footprint, to get
+ * deterministic iteration behavior.
*
- * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link
- * EnumSet#of(Enum, Enum[])} instead.
- *
- * @param elements the elements that the set should contain
- * @return a new {@code HashSet} containing those elements (minus duplicates)
+ * <p>This method is just a small convenience, either for {@code newHashSet(}{@link Arrays#asList
+ * asList}{@code (...))}, or for creating an empty set then calling {@link Collections#addAll}.
+ * This method is not actually very useful and will likely be deprecated in the future.
*/
public static <E> HashSet<E> newHashSet(E... elements) {
HashSet<E> set = newHashSetWithExpectedSize(elements.length);
@@ -181,11 +180,10 @@ public final class Sets {
}
/**
- * Creates a {@code HashSet} instance, with a high enough "initial capacity"
- * that it <i>should</i> hold {@code expectedSize} elements without growth.
- * This behavior cannot be broadly guaranteed, but it is observed to be true
- * for OpenJDK 1.6. It also can't be guaranteed that the method isn't
- * inadvertently <i>oversizing</i> the returned set.
+ * Creates a {@code HashSet} instance, with a high enough initial table size that it <i>should</i>
+ * hold {@code expectedSize} elements without resizing. This behavior cannot be broadly
+ * guaranteed, but it is observed to be true for OpenJDK 1.7. It also can't be guaranteed that the
+ * method isn't inadvertently <i>oversizing</i> the returned set.
*
* @param expectedSize the number of elements you expect to add to the
* returned set
@@ -198,17 +196,22 @@ public final class Sets {
}
/**
- * Creates a <i>mutable</i> {@code HashSet} instance containing the given
- * elements in unspecified order.
+ * Creates a <i>mutable</i> {@code HashSet} instance containing the given elements. A very thin
+ * convenience for creating an empty set then calling {@link Collection#addAll} or {@link
+ * Iterables#addAll}.
*
- * <p><b>Note:</b> if mutability is not required and the elements are
- * non-null, use {@link ImmutableSet#copyOf(Iterable)} instead.
+ * <p><b>Note:</b> if mutability is not required and the elements are non-null, use {@link
+ * ImmutableSet#copyOf(Iterable)} instead. (Or, change {@code elements} to be a {@link
+ * FluentIterable} and call {@code elements.toSet()}.)
*
- * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use
- * {@link #newEnumSet(Iterable, Class)} instead.
+ * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link #newEnumSet(Iterable, Class)}
+ * instead.
*
- * @param elements the elements that the set should contain
- * @return a new {@code HashSet} containing those elements (minus duplicates)
+ * <p><b>Note for Java 7 and later:</b> if {@code elements} is a {@link Collection}, you don't
+ * need this method. Instead, use the {@code HashSet} constructor directly, taking advantage of
+ * the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
+ *
+ * <p>Overall, this method is not very useful and will likely be deprecated in the future.
*/
public static <E> HashSet<E> newHashSet(Iterable<? extends E> elements) {
return (elements instanceof Collection)
@@ -217,17 +220,16 @@ public final class Sets {
}
/**
- * Creates a <i>mutable</i> {@code HashSet} instance containing the given
- * elements in unspecified order.
+ * Creates a <i>mutable</i> {@code HashSet} instance containing the given elements. A very thin
+ * convenience for creating an empty set and then calling {@link Iterators#addAll}.
*
- * <p><b>Note:</b> if mutability is not required and the elements are
- * non-null, use {@link ImmutableSet#copyOf(Iterable)} instead.
+ * <p><b>Note:</b> if mutability is not required and the elements are non-null, use {@link
+ * ImmutableSet#copyOf(Iterator)} instead.
*
- * <p><b>Note:</b> if {@code E} is an {@link Enum} type, you should create an
- * {@link EnumSet} instead.
+ * <p><b>Note:</b> if {@code E} is an {@link Enum} type, you should create an {@link EnumSet}
+ * instead.
*
- * @param elements the elements that the set should contain
- * @return a new {@code HashSet} containing those elements (minus duplicates)
+ * <p>Overall, this method is not very useful and will likely be deprecated in the future.
*/
public static <E> HashSet<E> newHashSet(Iterator<? extends E> elements) {
HashSet<E> set = newHashSet();
@@ -264,8 +266,7 @@ public final class Sets {
* null
* @since 15.0
*/
- public static <E> Set<E> newConcurrentHashSet(
- Iterable<? extends E> elements) {
+ public static <E> Set<E> newConcurrentHashSet(Iterable<? extends E> elements) {
Set<E> set = newConcurrentHashSet();
Iterables.addAll(set, elements);
return set;
@@ -299,8 +300,7 @@ public final class Sets {
* @throws IllegalArgumentException if {@code expectedSize} is negative
* @since 11.0
*/
- public static <E> LinkedHashSet<E> newLinkedHashSetWithExpectedSize(
- int expectedSize) {
+ public static <E> LinkedHashSet<E> newLinkedHashSetWithExpectedSize(int expectedSize) {
return new LinkedHashSet<E>(Maps.capacity(expectedSize));
}
@@ -315,8 +315,7 @@ public final class Sets {
* @return a new {@code LinkedHashSet} containing those elements (minus
* duplicates)
*/
- public static <E> LinkedHashSet<E> newLinkedHashSet(
- Iterable<? extends E> elements) {
+ public static <E> LinkedHashSet<E> newLinkedHashSet(Iterable<? extends E> elements) {
if (elements instanceof Collection) {
return new LinkedHashSet<E>(Collections2.cast(elements));
}
@@ -355,8 +354,7 @@ public final class Sets {
* @param elements the elements that the set should contain
* @return a new {@code TreeSet} containing those elements (minus duplicates)
*/
- public static <E extends Comparable> TreeSet<E> newTreeSet(
- Iterable<? extends E> elements) {
+ public static <E extends Comparable> TreeSet<E> newTreeSet(Iterable<? extends E> elements) {
TreeSet<E> set = newTreeSet();
Iterables.addAll(set, elements);
return set;
@@ -406,13 +404,12 @@ public final class Sets {
* @throws IllegalArgumentException if {@code collection} is not an
* {@code EnumSet} instance and contains no elements
*/
- public static <E extends Enum<E>> EnumSet<E> complementOf(
- Collection<E> collection) {
+ public static <E extends Enum<E>> EnumSet<E> complementOf(Collection<E> collection) {
if (collection instanceof EnumSet) {
return EnumSet.complementOf((EnumSet<E>) collection);
}
- checkArgument(!collection.isEmpty(),
- "collection is empty; use the other version of this method");
+ checkArgument(
+ !collection.isEmpty(), "collection is empty; use the other version of this method");
Class<E> type = collection.iterator().next().getDeclaringClass();
return makeComplementByHand(collection, type);
}
@@ -467,14 +464,15 @@ public final class Sets {
* Set<Object> identityHashSet = Sets.newSetFromMap(
* new IdentityHashMap<Object, Boolean>());}</pre>
*
- * <p>This method has the same behavior as the JDK 6 method
- * {@code Collections.newSetFromMap()}. The returned set is serializable if
- * the backing map is.
+ * <p>The returned set is serializable if the backing map is.
*
* @param map the backing map
* @return the set backed by the map
* @throws IllegalArgumentException if {@code map} is not empty
+ * @deprecated Use {@link Collections#newSetFromMap} instead. This method
+ * will be removed in August 2017.
*/
+ @Deprecated
public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
return Platform.newSetFromMap(map);
}
@@ -487,7 +485,7 @@ public final class Sets {
* as a plain {@link Set}, or immediately invoke {@link #immutableCopy} or
* {@link #copyInto} and forget the {@code SetView} itself.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public abstract static class SetView<E> extends AbstractSet<E> {
private SetView() {} // no subclasses but our own
@@ -540,35 +538,44 @@ public final class Sets {
* {@code union = Sets.union(union, anotherSet);}, since iterating over the resulting
* set has a cubic complexity to the depth of the nesting.
*/
- public static <E> SetView<E> union(
- final Set<? extends E> set1, final Set<? extends E> set2) {
+ public static <E> SetView<E> union(final Set<? extends E> set1, final Set<? extends E> set2) {
checkNotNull(set1, "set1");
checkNotNull(set2, "set2");
final Set<? extends E> set2minus1 = difference(set2, set1);
return new SetView<E>() {
- @Override public int size() {
+ @Override
+ public int size() {
return set1.size() + set2minus1.size();
}
- @Override public boolean isEmpty() {
+
+ @Override
+ public boolean isEmpty() {
return set1.isEmpty() && set2.isEmpty();
}
- @Override public Iterator<E> iterator() {
+
+ @Override
+ public Iterator<E> iterator() {
return Iterators.unmodifiableIterator(
Iterators.concat(set1.iterator(), set2minus1.iterator()));
}
- @Override public boolean contains(Object object) {
+
+ @Override
+ public boolean contains(Object object) {
return set1.contains(object) || set2.contains(object);
}
- @Override public <S extends Set<E>> S copyInto(S set) {
+
+ @Override
+ public <S extends Set<E>> S copyInto(S set) {
set.addAll(set1);
set.addAll(set2);
return set;
}
- @Override public ImmutableSet<E> immutableCopy() {
- return new ImmutableSet.Builder<E>()
- .addAll(set1).addAll(set2).build();
+
+ @Override
+ public ImmutableSet<E> immutableCopy() {
+ return new ImmutableSet.Builder<E>().addAll(set1).addAll(set2).build();
}
};
}
@@ -599,28 +606,35 @@ public final class Sets {
*
* <p>This is unfortunate, but should come up only very rarely.
*/
- public static <E> SetView<E> intersection(
- final Set<E> set1, final Set<?> set2) {
+ public static <E> SetView<E> intersection(final Set<E> set1, final Set<?> set2) {
checkNotNull(set1, "set1");
checkNotNull(set2, "set2");
final Predicate<Object> inSet2 = Predicates.in(set2);
return new SetView<E>() {
- @Override public Iterator<E> iterator() {
+ @Override
+ public Iterator<E> iterator() {
return Iterators.filter(set1.iterator(), inSet2);
}
- @Override public int size() {
+
+ @Override
+ public int size() {
return Iterators.size(iterator());
}
- @Override public boolean isEmpty() {
+
+ @Override
+ public boolean isEmpty() {
return !iterator().hasNext();
}
- @Override public boolean contains(Object object) {
+
+ @Override
+ public boolean contains(Object object) {
return set1.contains(object) && set2.contains(object);
}
- @Override public boolean containsAll(Collection<?> collection) {
- return set1.containsAll(collection)
- && set2.containsAll(collection);
+
+ @Override
+ public boolean containsAll(Collection<?> collection) {
+ return set1.containsAll(collection) && set2.containsAll(collection);
}
};
}
@@ -636,23 +650,29 @@ public final class Sets {
* on different equivalence relations (as {@code HashSet}, {@code TreeSet},
* and the keySet of an {@code IdentityHashMap} all are).
*/
- public static <E> SetView<E> difference(
- final Set<E> set1, final Set<?> set2) {
+ public static <E> SetView<E> difference(final Set<E> set1, final Set<?> set2) {
checkNotNull(set1, "set1");
checkNotNull(set2, "set2");
final Predicate<Object> notInSet2 = Predicates.not(Predicates.in(set2));
return new SetView<E>() {
- @Override public Iterator<E> iterator() {
+ @Override
+ public Iterator<E> iterator() {
return Iterators.filter(set1.iterator(), notInSet2);
}
- @Override public int size() {
+
+ @Override
+ public int size() {
return Iterators.size(iterator());
}
- @Override public boolean isEmpty() {
+
+ @Override
+ public boolean isEmpty() {
return set2.containsAll(set1);
}
- @Override public boolean contains(Object element) {
+
+ @Override
+ public boolean contains(Object element) {
return set1.contains(element) && !set2.contains(element);
}
};
@@ -671,12 +691,50 @@ public final class Sets {
* @since 3.0
*/
public static <E> SetView<E> symmetricDifference(
- Set<? extends E> set1, Set<? extends E> set2) {
+ final Set<? extends E> set1, final Set<? extends E> set2) {
checkNotNull(set1, "set1");
checkNotNull(set2, "set2");
- // TODO(kevinb): Replace this with a more efficient implementation
- return difference(union(set1, set2), intersection(set1, set2));
+ return new SetView<E>() {
+ @Override
+ public Iterator<E> iterator() {
+ final Iterator<? extends E> itr1 = set1.iterator();
+ final Iterator<? extends E> itr2 = set2.iterator();
+ return new AbstractIterator<E>() {
+ @Override
+ public E computeNext() {
+ while (itr1.hasNext()) {
+ E elem1 = itr1.next();
+ if (!set2.contains(elem1)) {
+ return elem1;
+ }
+ }
+ while (itr2.hasNext()) {
+ E elem2 = itr2.next();
+ if (!set1.contains(elem2)) {
+ return elem2;
+ }
+ }
+ return endOfData();
+ }
+ };
+ }
+
+ @Override
+ public int size() {
+ return Iterators.size(iterator());
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return set1.equals(set2);
+ }
+
+ @Override
+ public boolean contains(Object element) {
+ return set1.contains(element) ^ set2.contains(element);
+ }
+ };
}
/**
@@ -706,8 +764,8 @@ public final class Sets {
* functionality.)
*/
// TODO(kevinb): how to omit that last sentence when building GWT javadoc?
- public static <E> Set<E> filter(
- Set<E> unfiltered, Predicate<? super E> predicate) {
+ @CheckReturnValue
+ public static <E> Set<E> filter(Set<E> unfiltered, Predicate<? super E> predicate) {
if (unfiltered instanceof SortedSet) {
return filter((SortedSet<E>) unfiltered, predicate);
}
@@ -715,27 +773,25 @@ public final class Sets {
// Support clear(), removeAll(), and retainAll() when filtering a filtered
// collection.
FilteredSet<E> filtered = (FilteredSet<E>) unfiltered;
- Predicate<E> combinedPredicate
- = Predicates.<E>and(filtered.predicate, predicate);
- return new FilteredSet<E>(
- (Set<E>) filtered.unfiltered, combinedPredicate);
+ Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
+ return new FilteredSet<E>((Set<E>) filtered.unfiltered, combinedPredicate);
}
- return new FilteredSet<E>(
- checkNotNull(unfiltered), checkNotNull(predicate));
+ return new FilteredSet<E>(checkNotNull(unfiltered), checkNotNull(predicate));
}
- private static class FilteredSet<E> extends FilteredCollection<E>
- implements Set<E> {
+ private static class FilteredSet<E> extends FilteredCollection<E> implements Set<E> {
FilteredSet(Set<E> unfiltered, Predicate<? super E> predicate) {
super(unfiltered, predicate);
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return equalsImpl(this, object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return hashCodeImpl(this);
}
}
@@ -769,8 +825,8 @@ public final class Sets {
*
* @since 11.0
*/
- public static <E> SortedSet<E> filter(
- SortedSet<E> unfiltered, Predicate<? super E> predicate) {
+ @CheckReturnValue
+ public static <E> SortedSet<E> filter(SortedSet<E> unfiltered, Predicate<? super E> predicate) {
return Platform.setsFilterSortedSet(unfiltered, predicate);
}
@@ -780,18 +836,14 @@ public final class Sets {
// Support clear(), removeAll(), and retainAll() when filtering a filtered
// collection.
FilteredSet<E> filtered = (FilteredSet<E>) unfiltered;
- Predicate<E> combinedPredicate
- = Predicates.<E>and(filtered.predicate, predicate);
- return new FilteredSortedSet<E>(
- (SortedSet<E>) filtered.unfiltered, combinedPredicate);
+ Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
+ return new FilteredSortedSet<E>((SortedSet<E>) filtered.unfiltered, combinedPredicate);
}
- return new FilteredSortedSet<E>(
- checkNotNull(unfiltered), checkNotNull(predicate));
+ return new FilteredSortedSet<E>(checkNotNull(unfiltered), checkNotNull(predicate));
}
- private static class FilteredSortedSet<E> extends FilteredSet<E>
- implements SortedSet<E> {
+ private static class FilteredSortedSet<E> extends FilteredSet<E> implements SortedSet<E> {
FilteredSortedSet(SortedSet<E> unfiltered, Predicate<? super E> predicate) {
super(unfiltered, predicate);
@@ -804,8 +856,8 @@ public final class Sets {
@Override
public SortedSet<E> subSet(E fromElement, E toElement) {
- return new FilteredSortedSet<E>(((SortedSet<E>) unfiltered).subSet(fromElement, toElement),
- predicate);
+ return new FilteredSortedSet<E>(
+ ((SortedSet<E>) unfiltered).subSet(fromElement, toElement), predicate);
}
@Override
@@ -891,8 +943,7 @@ public final class Sets {
* or any element of a provided set is null
* @since 2.0
*/
- public static <B> Set<List<B>> cartesianProduct(
- List<? extends Set<? extends B>> sets) {
+ public static <B> Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets) {
return CartesianSet.create(sets);
}
@@ -951,13 +1002,12 @@ public final class Sets {
* or any element of a provided set is null
* @since 2.0
*/
- public static <B> Set<List<B>> cartesianProduct(
- Set<? extends B>... sets) {
+ public static <B> Set<List<B>> cartesianProduct(Set<? extends B>... sets) {
return cartesianProduct(Arrays.asList(sets));
}
- private static final class CartesianSet<E>
- extends ForwardingCollection<List<E>> implements Set<List<E>> {
+ private static final class CartesianSet<E> extends ForwardingCollection<List<E>>
+ implements Set<List<E>> {
private transient final ImmutableList<ImmutableSet<E>> axes;
private transient final CartesianList<E> delegate;
@@ -972,28 +1022,27 @@ public final class Sets {
axesBuilder.add(copy);
}
final ImmutableList<ImmutableSet<E>> axes = axesBuilder.build();
- ImmutableList<List<E>> listAxes = new ImmutableList<List<E>>() {
-
- @Override
- public int size() {
- return axes.size();
- }
-
- @Override
- public List<E> get(int index) {
- return axes.get(index).asList();
- }
-
- @Override
- boolean isPartialView() {
- return true;
- }
- };
+ ImmutableList<List<E>> listAxes =
+ new ImmutableList<List<E>>() {
+ @Override
+ public int size() {
+ return axes.size();
+ }
+
+ @Override
+ public List<E> get(int index) {
+ return axes.get(index).asList();
+ }
+
+ @Override
+ boolean isPartialView() {
+ return true;
+ }
+ };
return new CartesianSet<E>(axes, new CartesianList<E>(listAxes));
}
- private CartesianSet(
- ImmutableList<ImmutableSet<E>> axes, CartesianList<E> delegate) {
+ private CartesianSet(ImmutableList<ImmutableSet<E>> axes, CartesianList<E> delegate) {
this.axes = axes;
this.delegate = delegate;
}
@@ -1003,7 +1052,8 @@ public final class Sets {
return delegate;
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
// Warning: this is broken if size() == 0, so it is critical that we
// substitute an empty ImmutableSet to the user in place of this
if (object instanceof CartesianSet) {
@@ -1118,33 +1168,33 @@ public final class Sets {
final ImmutableMap<E, Integer> inputSet;
PowerSet(Set<E> input) {
- ImmutableMap.Builder<E, Integer> builder = ImmutableMap.builder();
- int i = 0;
- for (E e : checkNotNull(input)) {
- builder.put(e, i++);
- }
- this.inputSet = builder.build();
- checkArgument(inputSet.size() <= 30,
- "Too many elements to create power set: %s > 30", inputSet.size());
+ this.inputSet = Maps.indexMap(input);
+ checkArgument(
+ inputSet.size() <= 30, "Too many elements to create power set: %s > 30", inputSet.size());
}
- @Override public int size() {
+ @Override
+ public int size() {
return 1 << inputSet.size();
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Iterator<Set<E>> iterator() {
+ @Override
+ public Iterator<Set<E>> iterator() {
return new AbstractIndexedListIterator<Set<E>>(size()) {
- @Override protected Set<E> get(final int setBits) {
+ @Override
+ protected Set<E> get(final int setBits) {
return new SubSet<E>(inputSet, setBits);
}
};
}
- @Override public boolean contains(@Nullable Object obj) {
+ @Override
+ public boolean contains(@Nullable Object obj) {
if (obj instanceof Set) {
Set<?> set = (Set<?>) obj;
return inputSet.keySet().containsAll(set);
@@ -1152,7 +1202,8 @@ public final class Sets {
return false;
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof PowerSet) {
PowerSet<?> that = (PowerSet<?>) obj;
return inputSet.equals(that.inputSet);
@@ -1160,7 +1211,8 @@ public final class Sets {
return super.equals(obj);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
/*
* The sum of the sums of the hash codes in each subset is just the sum of
* each input element's hash code times the number of sets that element
@@ -1169,7 +1221,8 @@ public final class Sets {
return inputSet.keySet().hashCode() << (inputSet.size() - 1);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "powerSet(" + inputSet + ")";
}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/SortedMultisets.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/SortedMultisets.java
index e3955b5..edff70c 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/SortedMultisets.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/SortedMultisets.java
@@ -21,6 +21,7 @@ import static com.google.common.collect.BoundType.OPEN;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Multiset.Entry;
+import com.google.j2objc.annotations.Weak;
import java.util.Comparator;
import java.util.NoSuchElementException;
@@ -36,45 +37,50 @@ import javax.annotation.Nullable;
*/
@GwtCompatible(emulated = true)
final class SortedMultisets {
- private SortedMultisets() {
- }
+ private SortedMultisets() {}
/**
* A skeleton implementation for {@link SortedMultiset#elementSet}.
*/
- static class ElementSet<E> extends Multisets.ElementSet<E> implements
- SortedSet<E> {
- private final SortedMultiset<E> multiset;
+ static class ElementSet<E> extends Multisets.ElementSet<E> implements SortedSet<E> {
+ @Weak private final SortedMultiset<E> multiset;
ElementSet(SortedMultiset<E> multiset) {
this.multiset = multiset;
}
- @Override final SortedMultiset<E> multiset() {
+ @Override
+ final SortedMultiset<E> multiset() {
return multiset;
}
- @Override public Comparator<? super E> comparator() {
+ @Override
+ public Comparator<? super E> comparator() {
return multiset().comparator();
}
- @Override public SortedSet<E> subSet(E fromElement, E toElement) {
+ @Override
+ public SortedSet<E> subSet(E fromElement, E toElement) {
return multiset().subMultiset(fromElement, CLOSED, toElement, OPEN).elementSet();
}
- @Override public SortedSet<E> headSet(E toElement) {
+ @Override
+ public SortedSet<E> headSet(E toElement) {
return multiset().headMultiset(toElement, OPEN).elementSet();
}
- @Override public SortedSet<E> tailSet(E fromElement) {
+ @Override
+ public SortedSet<E> tailSet(E fromElement) {
return multiset().tailMultiset(fromElement, CLOSED).elementSet();
}
- @Override public E first() {
+ @Override
+ public E first() {
return getElementOrThrow(multiset().firstEntry());
}
- @Override public E last() {
+ @Override
+ public E last() {
return getElementOrThrow(multiset().lastEntry());
}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Synchronized.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Synchronized.java
index c809da8..08378c8 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Synchronized.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Synchronized.java
@@ -69,7 +69,8 @@ final class Synchronized {
// No equals and hashCode; see ForwardingObject for details.
- @Override public String toString() {
+ @Override
+ public String toString() {
synchronized (mutex) {
return delegate.toString();
}
@@ -81,20 +82,19 @@ final class Synchronized {
// following writeObject() handles the SynchronizedObject members.
}
- private static <E> Collection<E> collection(
- Collection<E> collection, @Nullable Object mutex) {
+ private static <E> Collection<E> collection(Collection<E> collection, @Nullable Object mutex) {
return new SynchronizedCollection<E>(collection, mutex);
}
- @VisibleForTesting static class SynchronizedCollection<E>
- extends SynchronizedObject implements Collection<E> {
- private SynchronizedCollection(
- Collection<E> delegate, @Nullable Object mutex) {
+ @VisibleForTesting
+ static class SynchronizedCollection<E> extends SynchronizedObject implements Collection<E> {
+ private SynchronizedCollection(Collection<E> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
@SuppressWarnings("unchecked")
- @Override Collection<E> delegate() {
+ @Override
+ Collection<E> delegate() {
return (Collection<E>) super.delegate();
}
@@ -190,22 +190,24 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- @VisibleForTesting static <E> Set<E> set(Set<E> set, @Nullable Object mutex) {
+ @VisibleForTesting
+ static <E> Set<E> set(Set<E> set, @Nullable Object mutex) {
return new SynchronizedSet<E>(set, mutex);
}
- static class SynchronizedSet<E>
- extends SynchronizedCollection<E> implements Set<E> {
+ static class SynchronizedSet<E> extends SynchronizedCollection<E> implements Set<E> {
SynchronizedSet(Set<E> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override Set<E> delegate() {
+ @Override
+ Set<E> delegate() {
return (Set<E>) super.delegate();
}
- @Override public boolean equals(Object o) {
+ @Override
+ public boolean equals(Object o) {
if (o == this) {
return true;
}
@@ -214,7 +216,8 @@ final class Synchronized {
}
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
synchronized (mutex) {
return delegate().hashCode();
}
@@ -223,18 +226,17 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- private static <E> SortedSet<E> sortedSet(
- SortedSet<E> set, @Nullable Object mutex) {
+ private static <E> SortedSet<E> sortedSet(SortedSet<E> set, @Nullable Object mutex) {
return new SynchronizedSortedSet<E>(set, mutex);
}
- static class SynchronizedSortedSet<E> extends SynchronizedSet<E>
- implements SortedSet<E> {
+ static class SynchronizedSortedSet<E> extends SynchronizedSet<E> implements SortedSet<E> {
SynchronizedSortedSet(SortedSet<E> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override SortedSet<E> delegate() {
+ @Override
+ SortedSet<E> delegate() {
return (SortedSet<E>) super.delegate();
}
@@ -289,13 +291,13 @@ final class Synchronized {
: new SynchronizedList<E>(list, mutex);
}
- private static class SynchronizedList<E> extends SynchronizedCollection<E>
- implements List<E> {
+ private static class SynchronizedList<E> extends SynchronizedCollection<E> implements List<E> {
SynchronizedList(List<E> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override List<E> delegate() {
+ @Override
+ List<E> delegate() {
return (List<E>) super.delegate();
}
@@ -365,7 +367,8 @@ final class Synchronized {
}
}
- @Override public boolean equals(Object o) {
+ @Override
+ public boolean equals(Object o) {
if (o == this) {
return true;
}
@@ -374,7 +377,8 @@ final class Synchronized {
}
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
synchronized (mutex) {
return delegate().hashCode();
}
@@ -383,18 +387,17 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- private static class SynchronizedRandomAccessList<E>
- extends SynchronizedList<E> implements RandomAccess {
+ private static class SynchronizedRandomAccessList<E> extends SynchronizedList<E>
+ implements RandomAccess {
SynchronizedRandomAccessList(List<E> list, @Nullable Object mutex) {
super(list, mutex);
}
+
private static final long serialVersionUID = 0;
}
- static <E> Multiset<E> multiset(
- Multiset<E> multiset, @Nullable Object mutex) {
- if (multiset instanceof SynchronizedMultiset ||
- multiset instanceof ImmutableMultiset) {
+ static <E> Multiset<E> multiset(Multiset<E> multiset, @Nullable Object mutex) {
+ if (multiset instanceof SynchronizedMultiset || multiset instanceof ImmutableMultiset) {
return multiset;
}
return new SynchronizedMultiset<E>(multiset, mutex);
@@ -409,7 +412,8 @@ final class Synchronized {
super(delegate, mutex);
}
- @Override Multiset<E> delegate() {
+ @Override
+ Multiset<E> delegate() {
return (Multiset<E>) super.delegate();
}
@@ -468,7 +472,8 @@ final class Synchronized {
}
}
- @Override public boolean equals(Object o) {
+ @Override
+ public boolean equals(Object o) {
if (o == this) {
return true;
}
@@ -477,7 +482,8 @@ final class Synchronized {
}
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
synchronized (mutex) {
return delegate().hashCode();
}
@@ -486,10 +492,8 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- static <K, V> Multimap<K, V> multimap(
- Multimap<K, V> multimap, @Nullable Object mutex) {
- if (multimap instanceof SynchronizedMultimap ||
- multimap instanceof ImmutableMultimap) {
+ static <K, V> Multimap<K, V> multimap(Multimap<K, V> multimap, @Nullable Object mutex) {
+ if (multimap instanceof SynchronizedMultimap || multimap instanceof ImmutableMultimap) {
return multimap;
}
return new SynchronizedMultimap<K, V>(multimap, mutex);
@@ -504,7 +508,8 @@ final class Synchronized {
transient Multiset<K> keys;
@SuppressWarnings("unchecked")
- @Override Multimap<K, V> delegate() {
+ @Override
+ Multimap<K, V> delegate() {
return (Multimap<K, V>) super.delegate();
}
@@ -653,7 +658,8 @@ final class Synchronized {
}
}
- @Override public boolean equals(Object o) {
+ @Override
+ public boolean equals(Object o) {
if (o == this) {
return true;
}
@@ -662,7 +668,8 @@ final class Synchronized {
}
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
synchronized (mutex) {
return delegate().hashCode();
}
@@ -673,78 +680,90 @@ final class Synchronized {
static <K, V> ListMultimap<K, V> listMultimap(
ListMultimap<K, V> multimap, @Nullable Object mutex) {
- if (multimap instanceof SynchronizedListMultimap ||
- multimap instanceof ImmutableListMultimap) {
+ if (multimap instanceof SynchronizedListMultimap || multimap instanceof ImmutableListMultimap) {
return multimap;
}
return new SynchronizedListMultimap<K, V>(multimap, mutex);
}
- private static class SynchronizedListMultimap<K, V>
- extends SynchronizedMultimap<K, V> implements ListMultimap<K, V> {
- SynchronizedListMultimap(
- ListMultimap<K, V> delegate, @Nullable Object mutex) {
+ private static class SynchronizedListMultimap<K, V> extends SynchronizedMultimap<K, V>
+ implements ListMultimap<K, V> {
+ SynchronizedListMultimap(ListMultimap<K, V> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override ListMultimap<K, V> delegate() {
+
+ @Override
+ ListMultimap<K, V> delegate() {
return (ListMultimap<K, V>) super.delegate();
}
- @Override public List<V> get(K key) {
+
+ @Override
+ public List<V> get(K key) {
synchronized (mutex) {
return list(delegate().get(key), mutex);
}
}
- @Override public List<V> removeAll(Object key) {
+
+ @Override
+ public List<V> removeAll(Object key) {
synchronized (mutex) {
return delegate().removeAll(key); // copy not synchronized
}
}
- @Override public List<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public List<V> replaceValues(K key, Iterable<? extends V> values) {
synchronized (mutex) {
return delegate().replaceValues(key, values); // copy not synchronized
}
}
+
private static final long serialVersionUID = 0;
}
- static <K, V> SetMultimap<K, V> setMultimap(
- SetMultimap<K, V> multimap, @Nullable Object mutex) {
- if (multimap instanceof SynchronizedSetMultimap ||
- multimap instanceof ImmutableSetMultimap) {
+ static <K, V> SetMultimap<K, V> setMultimap(SetMultimap<K, V> multimap, @Nullable Object mutex) {
+ if (multimap instanceof SynchronizedSetMultimap || multimap instanceof ImmutableSetMultimap) {
return multimap;
}
return new SynchronizedSetMultimap<K, V>(multimap, mutex);
}
- private static class SynchronizedSetMultimap<K, V>
- extends SynchronizedMultimap<K, V> implements SetMultimap<K, V> {
+ private static class SynchronizedSetMultimap<K, V> extends SynchronizedMultimap<K, V>
+ implements SetMultimap<K, V> {
transient Set<Map.Entry<K, V>> entrySet;
- SynchronizedSetMultimap(
- SetMultimap<K, V> delegate, @Nullable Object mutex) {
+ SynchronizedSetMultimap(SetMultimap<K, V> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override SetMultimap<K, V> delegate() {
+
+ @Override
+ SetMultimap<K, V> delegate() {
return (SetMultimap<K, V>) super.delegate();
}
- @Override public Set<V> get(K key) {
+
+ @Override
+ public Set<V> get(K key) {
synchronized (mutex) {
return set(delegate().get(key), mutex);
}
}
- @Override public Set<V> removeAll(Object key) {
+
+ @Override
+ public Set<V> removeAll(Object key) {
synchronized (mutex) {
return delegate().removeAll(key); // copy not synchronized
}
}
- @Override public Set<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public Set<V> replaceValues(K key, Iterable<? extends V> values) {
synchronized (mutex) {
return delegate().replaceValues(key, values); // copy not synchronized
}
}
- @Override public Set<Map.Entry<K, V>> entries() {
+
+ @Override
+ public Set<Map.Entry<K, V>> entries() {
synchronized (mutex) {
if (entrySet == null) {
entrySet = set(delegate().entries(), mutex);
@@ -752,6 +771,7 @@ final class Synchronized {
return entrySet;
}
}
+
private static final long serialVersionUID = 0;
}
@@ -763,37 +783,45 @@ final class Synchronized {
return new SynchronizedSortedSetMultimap<K, V>(multimap, mutex);
}
- private static class SynchronizedSortedSetMultimap<K, V>
- extends SynchronizedSetMultimap<K, V> implements SortedSetMultimap<K, V> {
- SynchronizedSortedSetMultimap(
- SortedSetMultimap<K, V> delegate, @Nullable Object mutex) {
+ private static class SynchronizedSortedSetMultimap<K, V> extends SynchronizedSetMultimap<K, V>
+ implements SortedSetMultimap<K, V> {
+ SynchronizedSortedSetMultimap(SortedSetMultimap<K, V> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override SortedSetMultimap<K, V> delegate() {
+
+ @Override
+ SortedSetMultimap<K, V> delegate() {
return (SortedSetMultimap<K, V>) super.delegate();
}
- @Override public SortedSet<V> get(K key) {
+
+ @Override
+ public SortedSet<V> get(K key) {
synchronized (mutex) {
return sortedSet(delegate().get(key), mutex);
}
}
- @Override public SortedSet<V> removeAll(Object key) {
+
+ @Override
+ public SortedSet<V> removeAll(Object key) {
synchronized (mutex) {
return delegate().removeAll(key); // copy not synchronized
}
}
- @Override public SortedSet<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
synchronized (mutex) {
return delegate().replaceValues(key, values); // copy not synchronized
}
}
+
@Override
public Comparator<? super V> valueComparator() {
synchronized (mutex) {
return delegate().valueComparator();
}
}
+
private static final long serialVersionUID = 0;
}
@@ -811,8 +839,7 @@ final class Synchronized {
return collection(collection, mutex);
}
- private static <E> Set<E> typePreservingSet(
- Set<E> set, @Nullable Object mutex) {
+ private static <E> Set<E> typePreservingSet(Set<E> set, @Nullable Object mutex) {
if (set instanceof SortedSet) {
return sortedSet((SortedSet<E>) set, mutex);
} else {
@@ -822,26 +849,25 @@ final class Synchronized {
private static class SynchronizedAsMapEntries<K, V>
extends SynchronizedSet<Map.Entry<K, Collection<V>>> {
- SynchronizedAsMapEntries(
- Set<Map.Entry<K, Collection<V>>> delegate, @Nullable Object mutex) {
+ SynchronizedAsMapEntries(Set<Map.Entry<K, Collection<V>>> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override public Iterator<Map.Entry<K, Collection<V>>> iterator() {
+ @Override
+ public Iterator<Map.Entry<K, Collection<V>>> iterator() {
// Must be manually synchronized.
- final Iterator<Map.Entry<K, Collection<V>>> iterator = super.iterator();
- return new ForwardingIterator<Map.Entry<K, Collection<V>>>() {
- @Override protected Iterator<Map.Entry<K, Collection<V>>> delegate() {
- return iterator;
- }
-
- @Override public Map.Entry<K, Collection<V>> next() {
- final Map.Entry<K, Collection<V>> entry = super.next();
+ return new TransformedIterator<Map.Entry<K, Collection<V>>, Map.Entry<K, Collection<V>>>(
+ super.iterator()) {
+ @Override
+ Map.Entry<K, Collection<V>> transform(final Map.Entry<K, Collection<V>> entry) {
return new ForwardingMapEntry<K, Collection<V>>() {
- @Override protected Map.Entry<K, Collection<V>> delegate() {
+ @Override
+ protected Map.Entry<K, Collection<V>> delegate() {
return entry;
}
- @Override public Collection<V> getValue() {
+
+ @Override
+ public Collection<V> getValue() {
return typePreservingCollection(entry.getValue(), mutex);
}
};
@@ -851,27 +877,36 @@ final class Synchronized {
// See Collections.CheckedMap.CheckedEntrySet for details on attacks.
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
synchronized (mutex) {
return ObjectArrays.toArrayImpl(delegate());
}
}
- @Override public <T> T[] toArray(T[] array) {
+
+ @Override
+ public <T> T[] toArray(T[] array) {
synchronized (mutex) {
return ObjectArrays.toArrayImpl(delegate(), array);
}
}
- @Override public boolean contains(Object o) {
+
+ @Override
+ public boolean contains(Object o) {
synchronized (mutex) {
return Maps.containsEntryImpl(delegate(), o);
}
}
- @Override public boolean containsAll(Collection<?> c) {
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
synchronized (mutex) {
return Collections2.containsAllImpl(delegate(), c);
}
}
- @Override public boolean equals(Object o) {
+
+ @Override
+ public boolean equals(Object o) {
if (o == this) {
return true;
}
@@ -879,17 +914,23 @@ final class Synchronized {
return Sets.equalsImpl(delegate(), o);
}
}
- @Override public boolean remove(Object o) {
+
+ @Override
+ public boolean remove(Object o) {
synchronized (mutex) {
return Maps.removeEntryImpl(delegate(), o);
}
}
- @Override public boolean removeAll(Collection<?> c) {
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
synchronized (mutex) {
return Iterators.removeAll(delegate().iterator(), c);
}
}
- @Override public boolean retainAll(Collection<?> c) {
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
synchronized (mutex) {
return Iterators.retainAll(delegate().iterator(), c);
}
@@ -903,8 +944,7 @@ final class Synchronized {
return new SynchronizedMap<K, V>(map, mutex);
}
- private static class SynchronizedMap<K, V> extends SynchronizedObject
- implements Map<K, V> {
+ private static class SynchronizedMap<K, V> extends SynchronizedObject implements Map<K, V> {
transient Set<K> keySet;
transient Collection<V> values;
transient Set<Map.Entry<K, V>> entrySet;
@@ -914,7 +954,8 @@ final class Synchronized {
}
@SuppressWarnings("unchecked")
- @Override Map<K, V> delegate() {
+ @Override
+ Map<K, V> delegate() {
return (Map<K, V>) super.delegate();
}
@@ -1011,7 +1052,8 @@ final class Synchronized {
}
}
- @Override public boolean equals(Object o) {
+ @Override
+ public boolean equals(Object o) {
if (o == this) {
return true;
}
@@ -1020,7 +1062,8 @@ final class Synchronized {
}
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
synchronized (mutex) {
return delegate().hashCode();
}
@@ -1029,8 +1072,7 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- static <K, V> SortedMap<K, V> sortedMap(
- SortedMap<K, V> sortedMap, @Nullable Object mutex) {
+ static <K, V> SortedMap<K, V> sortedMap(SortedMap<K, V> sortedMap, @Nullable Object mutex) {
return new SynchronizedSortedMap<K, V>(sortedMap, mutex);
}
@@ -1041,41 +1083,48 @@ final class Synchronized {
super(delegate, mutex);
}
- @Override SortedMap<K, V> delegate() {
+ @Override
+ SortedMap<K, V> delegate() {
return (SortedMap<K, V>) super.delegate();
}
- @Override public Comparator<? super K> comparator() {
+ @Override
+ public Comparator<? super K> comparator() {
synchronized (mutex) {
return delegate().comparator();
}
}
- @Override public K firstKey() {
+ @Override
+ public K firstKey() {
synchronized (mutex) {
return delegate().firstKey();
}
}
- @Override public SortedMap<K, V> headMap(K toKey) {
+ @Override
+ public SortedMap<K, V> headMap(K toKey) {
synchronized (mutex) {
return sortedMap(delegate().headMap(toKey), mutex);
}
}
- @Override public K lastKey() {
+ @Override
+ public K lastKey() {
synchronized (mutex) {
return delegate().lastKey();
}
}
- @Override public SortedMap<K, V> subMap(K fromKey, K toKey) {
+ @Override
+ public SortedMap<K, V> subMap(K fromKey, K toKey) {
synchronized (mutex) {
return sortedMap(delegate().subMap(fromKey, toKey), mutex);
}
}
- @Override public SortedMap<K, V> tailMap(K fromKey) {
+ @Override
+ public SortedMap<K, V> tailMap(K fromKey) {
synchronized (mutex) {
return sortedMap(delegate().tailMap(fromKey), mutex);
}
@@ -1085,29 +1134,31 @@ final class Synchronized {
}
static <K, V> BiMap<K, V> biMap(BiMap<K, V> bimap, @Nullable Object mutex) {
- if (bimap instanceof SynchronizedBiMap ||
- bimap instanceof ImmutableBiMap) {
+ if (bimap instanceof SynchronizedBiMap || bimap instanceof ImmutableBiMap) {
return bimap;
}
return new SynchronizedBiMap<K, V>(bimap, mutex, null);
}
- @VisibleForTesting static class SynchronizedBiMap<K, V>
- extends SynchronizedMap<K, V> implements BiMap<K, V>, Serializable {
+ @VisibleForTesting
+ static class SynchronizedBiMap<K, V> extends SynchronizedMap<K, V>
+ implements BiMap<K, V>, Serializable {
private transient Set<V> valueSet;
private transient BiMap<V, K> inverse;
- private SynchronizedBiMap(BiMap<K, V> delegate, @Nullable Object mutex,
- @Nullable BiMap<V, K> inverse) {
+ private SynchronizedBiMap(
+ BiMap<K, V> delegate, @Nullable Object mutex, @Nullable BiMap<V, K> inverse) {
super(delegate, mutex);
this.inverse = inverse;
}
- @Override BiMap<K, V> delegate() {
+ @Override
+ BiMap<K, V> delegate() {
return (BiMap<K, V>) super.delegate();
}
- @Override public Set<V> values() {
+ @Override
+ public Set<V> values() {
synchronized (mutex) {
if (valueSet == null) {
valueSet = set(delegate().values(), mutex);
@@ -1127,8 +1178,7 @@ final class Synchronized {
public BiMap<V, K> inverse() {
synchronized (mutex) {
if (inverse == null) {
- inverse
- = new SynchronizedBiMap<V, K>(delegate().inverse(), mutex, this);
+ inverse = new SynchronizedBiMap<V, K>(delegate().inverse(), mutex, this);
}
return inverse;
}
@@ -1137,8 +1187,7 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- private static class SynchronizedAsMap<K, V>
- extends SynchronizedMap<K, Collection<V>> {
+ private static class SynchronizedAsMap<K, V> extends SynchronizedMap<K, Collection<V>> {
transient Set<Map.Entry<K, Collection<V>>> asMapEntrySet;
transient Collection<Collection<V>> asMapValues;
@@ -1146,35 +1195,36 @@ final class Synchronized {
super(delegate, mutex);
}
- @Override public Collection<V> get(Object key) {
+ @Override
+ public Collection<V> get(Object key) {
synchronized (mutex) {
Collection<V> collection = super.get(key);
- return (collection == null) ? null
- : typePreservingCollection(collection, mutex);
+ return (collection == null) ? null : typePreservingCollection(collection, mutex);
}
}
- @Override public Set<Map.Entry<K, Collection<V>>> entrySet() {
+ @Override
+ public Set<Map.Entry<K, Collection<V>>> entrySet() {
synchronized (mutex) {
if (asMapEntrySet == null) {
- asMapEntrySet = new SynchronizedAsMapEntries<K, V>(
- delegate().entrySet(), mutex);
+ asMapEntrySet = new SynchronizedAsMapEntries<K, V>(delegate().entrySet(), mutex);
}
return asMapEntrySet;
}
}
- @Override public Collection<Collection<V>> values() {
+ @Override
+ public Collection<Collection<V>> values() {
synchronized (mutex) {
if (asMapValues == null) {
- asMapValues
- = new SynchronizedAsMapValues<V>(delegate().values(), mutex);
+ asMapValues = new SynchronizedAsMapValues<V>(delegate().values(), mutex);
}
return asMapValues;
}
}
- @Override public boolean containsValue(Object o) {
+ @Override
+ public boolean containsValue(Object o) {
// values() and its contains() method are both synchronized.
return values().contains(o);
}
@@ -1182,22 +1232,18 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- private static class SynchronizedAsMapValues<V>
- extends SynchronizedCollection<Collection<V>> {
- SynchronizedAsMapValues(
- Collection<Collection<V>> delegate, @Nullable Object mutex) {
+ private static class SynchronizedAsMapValues<V> extends SynchronizedCollection<Collection<V>> {
+ SynchronizedAsMapValues(Collection<Collection<V>> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override public Iterator<Collection<V>> iterator() {
+ @Override
+ public Iterator<Collection<V>> iterator() {
// Must be manually synchronized.
- final Iterator<Collection<V>> iterator = super.iterator();
- return new ForwardingIterator<Collection<V>>() {
- @Override protected Iterator<Collection<V>> delegate() {
- return iterator;
- }
- @Override public Collection<V> next() {
- return typePreservingCollection(super.next(), mutex);
+ return new TransformedIterator<Collection<V>, Collection<V>>(super.iterator()) {
+ @Override
+ Collection<V> transform(Collection<V> from) {
+ return typePreservingCollection(from, mutex);
}
};
}
@@ -1206,19 +1252,17 @@ final class Synchronized {
}
static <E> Queue<E> queue(Queue<E> queue, @Nullable Object mutex) {
- return (queue instanceof SynchronizedQueue)
- ? queue
- : new SynchronizedQueue<E>(queue, mutex);
+ return (queue instanceof SynchronizedQueue) ? queue : new SynchronizedQueue<E>(queue, mutex);
}
- private static class SynchronizedQueue<E> extends SynchronizedCollection<E>
- implements Queue<E> {
+ private static class SynchronizedQueue<E> extends SynchronizedCollection<E> implements Queue<E> {
SynchronizedQueue(Queue<E> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override Queue<E> delegate() {
+ @Override
+ Queue<E> delegate() {
return (Queue<E>) super.delegate();
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultimap.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultimap.java
index 5023a0c..91869f8 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultimap.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultimap.java
@@ -62,12 +62,12 @@ import javax.annotation.Nullable;
* Multimaps#synchronizedSortedSetMultimap}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
* {@code Multimap}</a>.
*
* @author Jared Levy
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V> {
@@ -78,8 +78,7 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
* Creates an empty {@code TreeMultimap} ordered by the natural ordering of
* its keys and values.
*/
- public static <K extends Comparable, V extends Comparable>
- TreeMultimap<K, V> create() {
+ public static <K extends Comparable, V extends Comparable> TreeMultimap<K, V> create() {
return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural());
}
@@ -92,10 +91,8 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
* @param valueComparator the comparator that determines the value ordering
*/
public static <K, V> TreeMultimap<K, V> create(
- Comparator<? super K> keyComparator,
- Comparator<? super V> valueComparator) {
- return new TreeMultimap<K, V>(checkNotNull(keyComparator),
- checkNotNull(valueComparator));
+ Comparator<? super K> keyComparator, Comparator<? super V> valueComparator) {
+ return new TreeMultimap<K, V>(checkNotNull(keyComparator), checkNotNull(valueComparator));
}
/**
@@ -104,20 +101,19 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
*
* @param multimap the multimap whose contents are copied to this multimap
*/
- public static <K extends Comparable, V extends Comparable>
- TreeMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
- return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural(),
- multimap);
+ public static <K extends Comparable, V extends Comparable> TreeMultimap<K, V> create(
+ Multimap<? extends K, ? extends V> multimap) {
+ return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural(), multimap);
}
- TreeMultimap(Comparator<? super K> keyComparator,
- Comparator<? super V> valueComparator) {
+ TreeMultimap(Comparator<? super K> keyComparator, Comparator<? super V> valueComparator) {
super(new TreeMap<K, Collection<V>>(keyComparator));
this.keyComparator = keyComparator;
this.valueComparator = valueComparator;
}
- private TreeMultimap(Comparator<? super K> keyComparator,
+ private TreeMultimap(
+ Comparator<? super K> keyComparator,
Comparator<? super V> valueComparator,
Multimap<? extends K, ? extends V> multimap) {
this(keyComparator, valueComparator);
@@ -132,7 +128,8 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
* @return a new {@code TreeSet} containing a collection of values for one
* key
*/
- @Override SortedSet<V> createCollection() {
+ @Override
+ SortedSet<V> createCollection() {
return new TreeSet<V>(valueComparator);
}
@@ -157,7 +154,7 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
}
/*
- * The following @GwtIncompatible methods override the methods in
+ * The following @GwtIncompatible methods override the methods in
* AbstractSortedKeySortedSetMultimap, so GWT will fall back to the ASKSSM implementations,
* which return SortedSets and SortedMaps.
*/
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultiset.java b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultiset.java
index b9be3d3..b27dbf3 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultiset.java
+++ b/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/TreeMultiset.java
@@ -44,12 +44,12 @@ import javax.annotation.Nullable;
* {@link java.util.Collection} contract, which is specified in terms of {@link Object#equals}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
* {@code Multiset}</a>.
*
* @author Louis Wasserman
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements Serializable {
@@ -149,6 +149,7 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
return (root == null) ? 0 : root.distinctElements;
}
};
+
abstract int nodeAggregate(AvlNode<?> node);
abstract long treeAggregate(@Nullable AvlNode<?> root);
@@ -183,7 +184,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
throw new AssertionError();
}
} else {
- return aggr.treeAggregate(node.left) + aggr.nodeAggregate(node)
+ return aggr.treeAggregate(node.left)
+ + aggr.nodeAggregate(node)
+ aggregateBelowRange(aggr, node.right);
}
}
@@ -205,7 +207,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
throw new AssertionError();
}
} else {
- return aggr.treeAggregate(node.right) + aggr.nodeAggregate(node)
+ return aggr.treeAggregate(node.right)
+ + aggr.nodeAggregate(node)
+ aggregateAboveRange(aggr, node.left);
}
}
@@ -349,7 +352,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
/**
* Returns the first node in the tree that is in range.
*/
- @Nullable private AvlNode<E> firstNode() {
+ @Nullable
+ private AvlNode<E> firstNode() {
AvlNode<E> root = rootReference.get();
if (root == null) {
return null;
@@ -371,7 +375,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
return (node == header || !range.contains(node.getElement())) ? null : node;
}
- @Nullable private AvlNode<E> lastNode() {
+ @Nullable
+ private AvlNode<E> lastNode() {
AvlNode<E> root = rootReference.get();
if (root == null) {
return null;
@@ -479,18 +484,18 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
@Override
public SortedMultiset<E> headMultiset(@Nullable E upperBound, BoundType boundType) {
- return new TreeMultiset<E>(rootReference, range.intersect(GeneralRange.upTo(
- comparator(),
- upperBound,
- boundType)), header);
+ return new TreeMultiset<E>(
+ rootReference,
+ range.intersect(GeneralRange.upTo(comparator(), upperBound, boundType)),
+ header);
}
@Override
public SortedMultiset<E> tailMultiset(@Nullable E lowerBound, BoundType boundType) {
- return new TreeMultiset<E>(rootReference, range.intersect(GeneralRange.downTo(
- comparator(),
- lowerBound,
- boundType)), header);
+ return new TreeMultiset<E>(
+ rootReference,
+ range.intersect(GeneralRange.downTo(comparator(), lowerBound, boundType)),
+ header);
}
static int distinctElements(@Nullable AvlNode<?> node) {
@@ -500,7 +505,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
private static final class Reference<T> {
@Nullable private T value;
- @Nullable public T get() {
+ @Nullable
+ public T get() {
return value;
}
@@ -824,8 +830,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
}
private void recomputeMultiset() {
- this.distinctElements = 1 + TreeMultiset.distinctElements(left)
- + TreeMultiset.distinctElements(right);
+ this.distinctElements =
+ 1 + TreeMultiset.distinctElements(left) + TreeMultiset.distinctElements(right);
this.totalCount = elemCount + totalCount(left) + totalCount(right);
}
@@ -892,7 +898,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
return (node == null) ? 0 : node.height;
}
- @Nullable private AvlNode<E> ceiling(Comparator<? super E> comparator, E e) {
+ @Nullable
+ private AvlNode<E> ceiling(Comparator<? super E> comparator, E e) {
int cmp = comparator.compare(e, elem);
if (cmp < 0) {
return (left == null) ? this : MoreObjects.firstNonNull(left.ceiling(comparator, e), this);
@@ -903,7 +910,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
}
}
- @Nullable private AvlNode<E> floor(Comparator<? super E> comparator, E e) {
+ @Nullable
+ private AvlNode<E> floor(Comparator<? super E> comparator, E e) {
int cmp = comparator.compare(e, elem);
if (cmp > 0) {
return (right == null) ? this : MoreObjects.firstNonNull(right.floor(comparator, e), this);
diff --git a/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/BaseEncoding.java b/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/BaseEncoding.java
index ea083b6..1bcf0c7 100644
--- a/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/BaseEncoding.java
+++ b/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/BaseEncoding.java
@@ -18,8 +18,6 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.io.GwtWorkarounds.asCharInput;
-import static com.google.common.io.GwtWorkarounds.stringBuilderOutput;
import static com.google.common.math.IntMath.divide;
import static com.google.common.math.IntMath.log2;
import static java.math.RoundingMode.CEILING;
@@ -30,10 +28,6 @@ import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Ascii;
import com.google.common.base.CharMatcher;
-import com.google.common.io.GwtWorkarounds.ByteInput;
-import com.google.common.io.GwtWorkarounds.ByteOutput;
-import com.google.common.io.GwtWorkarounds.CharInput;
-import com.google.common.io.GwtWorkarounds.CharOutput;
import java.io.IOException;
import java.util.Arrays;
@@ -123,7 +117,7 @@ import javax.annotation.Nullable;
@Beta
@GwtCompatible(emulated = true)
public abstract class BaseEncoding {
- // TODO(user): consider adding encodeTo(Appendable, byte[], [int, int])
+ // TODO(lowasser): consider making encodeTo(Appendable, byte[], int, int) public.
BaseEncoding() {}
@@ -147,7 +141,7 @@ public abstract class BaseEncoding {
* Encodes the specified byte array, and returns the encoded {@code String}.
*/
public String encode(byte[] bytes) {
- return encode(checkNotNull(bytes), 0, bytes.length);
+ return encode(bytes, 0, bytes.length);
}
/**
@@ -155,22 +149,17 @@ public abstract class BaseEncoding {
* {@code String}.
*/
public final String encode(byte[] bytes, int off, int len) {
- checkNotNull(bytes);
checkPositionIndexes(off, off + len, bytes.length);
- CharOutput result = stringBuilderOutput(maxEncodedSize(len));
- ByteOutput byteOutput = encodingStream(result);
+ StringBuilder result = new StringBuilder(maxEncodedSize(len));
try {
- for (int i = 0; i < len; i++) {
- byteOutput.write(bytes[off + i]);
- }
- byteOutput.close();
+ encodeTo(result, bytes, off, len);
} catch (IOException impossible) {
- throw new AssertionError("impossible");
+ throw new AssertionError(impossible);
}
return result.toString();
}
- // TODO(user): document the extent of leniency, probably after adding ignore(CharMatcher)
+ // TODO(lowasser): document the extent of leniency, probably after adding ignore(CharMatcher)
private static byte[] extract(byte[] result, int length) {
if (length == result.length) {
@@ -206,30 +195,20 @@ public abstract class BaseEncoding {
*/
final byte[] decodeChecked(CharSequence chars) throws DecodingException {
chars = padding().trimTrailingFrom(chars);
- ByteInput decodedInput = decodingStream(asCharInput(chars));
byte[] tmp = new byte[maxDecodedSize(chars.length())];
- int index = 0;
- try {
- for (int i = decodedInput.read(); i != -1; i = decodedInput.read()) {
- tmp[index++] = (byte) i;
- }
- } catch (DecodingException badInput) {
- throw badInput;
- } catch (IOException impossible) {
- throw new AssertionError(impossible);
- }
- return extract(tmp, index);
+ int len = decodeTo(tmp, chars);
+ return extract(tmp, len);
}
// Implementations for encoding/decoding
abstract int maxEncodedSize(int bytes);
- abstract ByteOutput encodingStream(CharOutput charOutput);
+ abstract void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException;
abstract int maxDecodedSize(int chars);
- abstract ByteInput decodingStream(CharInput charInput);
+ abstract int decodeTo(byte[] target, CharSequence chars) throws DecodingException;
abstract CharMatcher padding();
@@ -285,7 +264,7 @@ public abstract class BaseEncoding {
@CheckReturnValue
public abstract BaseEncoding lowerCase();
- private static final BaseEncoding BASE64 = new StandardBaseEncoding(
+ private static final BaseEncoding BASE64 = new Base64Encoding(
"base64()", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", '=');
/**
@@ -305,7 +284,7 @@ public abstract class BaseEncoding {
return BASE64;
}
- private static final BaseEncoding BASE64_URL = new StandardBaseEncoding(
+ private static final BaseEncoding BASE64_URL = new Base64Encoding(
"base64Url()", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", '=');
/**
@@ -365,8 +344,7 @@ public abstract class BaseEncoding {
return BASE32_HEX;
}
- private static final BaseEncoding BASE16 =
- new StandardBaseEncoding("base16()", "0123456789ABCDEF", null);
+ private static final BaseEncoding BASE16 = new Base16Encoding("base16()", "0123456789ABCDEF");
/**
* The "base16" encoding specified by <a
@@ -441,9 +419,10 @@ public abstract class BaseEncoding {
return validPadding[index % charsPerChunk];
}
- int decode(char ch) throws IOException {
+ int decode(char ch) throws DecodingException {
if (ch > Ascii.MAX || decodabet[ch] == -1) {
- throw new DecodingException("Unrecognized character: " + ch);
+ throw new DecodingException("Unrecognized character: "
+ + (CharMatcher.INVISIBLE.matches(ch) ? "0x" + Integer.toHexString(ch) : ch));
}
return decodabet[ch];
}
@@ -503,12 +482,12 @@ public abstract class BaseEncoding {
}
}
- static final class StandardBaseEncoding extends BaseEncoding {
- // TODO(user): provide a useful toString
- private final Alphabet alphabet;
+ static class StandardBaseEncoding extends BaseEncoding {
+ // TODO(lowasser): provide a useful toString
+ final Alphabet alphabet;
@Nullable
- private final Character paddingChar;
+ final Character paddingChar;
StandardBaseEncoding(String name, String alphabetChars, @Nullable Character paddingChar) {
this(new Alphabet(name, alphabetChars.toCharArray()), paddingChar);
@@ -532,49 +511,38 @@ public abstract class BaseEncoding {
}
@Override
- ByteOutput encodingStream(final CharOutput out) {
- checkNotNull(out);
- return new ByteOutput() {
- int bitBuffer = 0;
- int bitBufferLength = 0;
- int writtenChars = 0;
-
- @Override
- public void write(byte b) throws IOException {
- bitBuffer <<= 8;
- bitBuffer |= b & 0xFF;
- bitBufferLength += 8;
- while (bitBufferLength >= alphabet.bitsPerChar) {
- int charIndex = (bitBuffer >> (bitBufferLength - alphabet.bitsPerChar))
- & alphabet.mask;
- out.write(alphabet.encode(charIndex));
- writtenChars++;
- bitBufferLength -= alphabet.bitsPerChar;
- }
- }
-
- @Override
- public void flush() throws IOException {
- out.flush();
- }
+ void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+ checkNotNull(target);
+ checkPositionIndexes(off, off + len, bytes.length);
+ for (int i = 0; i < len; i += alphabet.bytesPerChunk) {
+ encodeChunkTo(target, bytes, off + i, Math.min(alphabet.bytesPerChunk, len - i));
+ }
+ }
- @Override
- public void close() throws IOException {
- if (bitBufferLength > 0) {
- int charIndex = (bitBuffer << (alphabet.bitsPerChar - bitBufferLength))
- & alphabet.mask;
- out.write(alphabet.encode(charIndex));
- writtenChars++;
- if (paddingChar != null) {
- while (writtenChars % alphabet.charsPerChunk != 0) {
- out.write(paddingChar.charValue());
- writtenChars++;
- }
- }
- }
- out.close();
+ void encodeChunkTo(Appendable target, byte[] bytes, int off, int len)
+ throws IOException {
+ checkNotNull(target);
+ checkPositionIndexes(off, off + len, bytes.length);
+ checkArgument(len <= alphabet.bytesPerChunk);
+ long bitBuffer = 0;
+ for (int i = 0; i < len; ++i) {
+ bitBuffer |= bytes[off + i] & 0xFF;
+ bitBuffer <<= 8; // Add additional zero byte in the end.
+ }
+ // Position of first character is length of bitBuffer minus bitsPerChar.
+ final int bitOffset = (len + 1) * 8 - alphabet.bitsPerChar;
+ int bitsProcessed = 0;
+ while (bitsProcessed < len * 8) {
+ int charIndex = (int) (bitBuffer >>> (bitOffset - bitsProcessed)) & alphabet.mask;
+ target.append(alphabet.encode(charIndex));
+ bitsProcessed += alphabet.bitsPerChar;
+ }
+ if (paddingChar != null) {
+ while (bitsProcessed < alphabet.bytesPerChunk * 8) {
+ target.append(paddingChar.charValue());
+ bitsProcessed += alphabet.bitsPerChar;
}
- };
+ }
}
@Override
@@ -583,59 +551,33 @@ public abstract class BaseEncoding {
}
@Override
- ByteInput decodingStream(final CharInput reader) {
- checkNotNull(reader);
- return new ByteInput() {
- int bitBuffer = 0;
- int bitBufferLength = 0;
- int readChars = 0;
- boolean hitPadding = false;
- final CharMatcher paddingMatcher = padding();
-
- @Override
- public int read() throws IOException {
- while (true) {
- int readChar = reader.read();
- if (readChar == -1) {
- if (!hitPadding && !alphabet.isValidPaddingStartPosition(readChars)) {
- throw new DecodingException("Invalid input length " + readChars);
- }
- return -1;
- }
- readChars++;
- char ch = (char) readChar;
- if (paddingMatcher.matches(ch)) {
- if (!hitPadding
- && (readChars == 1 || !alphabet.isValidPaddingStartPosition(readChars - 1))) {
- throw new DecodingException("Padding cannot start at index " + readChars);
- }
- hitPadding = true;
- } else if (hitPadding) {
- throw new DecodingException(
- "Expected padding character but found '" + ch + "' at index " + readChars);
- } else {
- bitBuffer <<= alphabet.bitsPerChar;
- bitBuffer |= alphabet.decode(ch);
- bitBufferLength += alphabet.bitsPerChar;
-
- if (bitBufferLength >= 8) {
- bitBufferLength -= 8;
- return (bitBuffer >> bitBufferLength) & 0xFF;
- }
- }
+ int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+ checkNotNull(target);
+ chars = padding().trimTrailingFrom(chars);
+ if (!alphabet.isValidPaddingStartPosition(chars.length())) {
+ throw new DecodingException("Invalid input length " + chars.length());
+ }
+ int bytesWritten = 0;
+ for (int charIdx = 0; charIdx < chars.length(); charIdx += alphabet.charsPerChunk) {
+ long chunk = 0;
+ int charsProcessed = 0;
+ for (int i = 0; i < alphabet.charsPerChunk; i++) {
+ chunk <<= alphabet.bitsPerChar;
+ if (charIdx + i < chars.length()) {
+ chunk |= alphabet.decode(chars.charAt(charIdx + charsProcessed++));
}
}
-
- @Override
- public void close() throws IOException {
- reader.close();
+ final int minOffset = alphabet.bytesPerChunk * 8 - charsProcessed * alphabet.bitsPerChar;
+ for (int offset = (alphabet.bytesPerChunk - 1) * 8; offset >= minOffset; offset -= 8) {
+ target[bytesWritten++] = (byte) ((chunk >>> offset) & 0xFF);
}
- };
+ }
+ return bytesWritten;
}
@Override
public BaseEncoding omitPadding() {
- return (paddingChar == null) ? this : new StandardBaseEncoding(alphabet, null);
+ return (paddingChar == null) ? this : newInstance(alphabet, null);
}
@Override
@@ -644,15 +586,14 @@ public abstract class BaseEncoding {
(paddingChar != null && paddingChar.charValue() == padChar)) {
return this;
} else {
- return new StandardBaseEncoding(alphabet, padChar);
+ return newInstance(alphabet, padChar);
}
}
@Override
public BaseEncoding withSeparator(String separator, int afterEveryChars) {
- checkNotNull(separator);
checkArgument(padding().or(alphabet).matchesNoneOf(separator),
- "Separator cannot contain alphabet or padding characters");
+ "Separator (%s) cannot contain alphabet or padding characters", separator);
return new SeparatedBaseEncoding(this, separator, afterEveryChars);
}
@@ -665,7 +606,7 @@ public abstract class BaseEncoding {
if (result == null) {
Alphabet upper = alphabet.upperCase();
result = upperCase =
- (upper == alphabet) ? this : new StandardBaseEncoding(upper, paddingChar);
+ (upper == alphabet) ? this : newInstance(upper, paddingChar);
}
return result;
}
@@ -676,11 +617,15 @@ public abstract class BaseEncoding {
if (result == null) {
Alphabet lower = alphabet.lowerCase();
result = lowerCase =
- (lower == alphabet) ? this : new StandardBaseEncoding(lower, paddingChar);
+ (lower == alphabet) ? this : newInstance(lower, paddingChar);
}
return result;
}
+ BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
+ return new StandardBaseEncoding(alphabet, paddingChar);
+ }
+
@Override
public String toString() {
StringBuilder builder = new StringBuilder("BaseEncoding.");
@@ -696,54 +641,137 @@ public abstract class BaseEncoding {
}
}
- static CharInput ignoringInput(final CharInput delegate, final CharMatcher toIgnore) {
- checkNotNull(delegate);
- checkNotNull(toIgnore);
- return new CharInput() {
- @Override
- public int read() throws IOException {
- int readChar;
- do {
- readChar = delegate.read();
- } while (readChar != -1 && toIgnore.matches((char) readChar));
- return readChar;
+ static final class Base16Encoding extends StandardBaseEncoding {
+ final char[] encoding = new char[512];
+
+ Base16Encoding(String name, String alphabetChars) {
+ this(new Alphabet(name, alphabetChars.toCharArray()));
+ }
+
+ private Base16Encoding(Alphabet alphabet) {
+ super(alphabet, null);
+ checkArgument(alphabet.chars.length == 16);
+ for (int i = 0; i < 256; ++i) {
+ encoding[i] = alphabet.encode(i >>> 4);
+ encoding[i | 0x100] = alphabet.encode(i & 0xF);
}
+ }
- @Override
- public void close() throws IOException {
- delegate.close();
+ @Override
+ void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+ checkNotNull(target);
+ checkPositionIndexes(off, off + len, bytes.length);
+ for (int i = 0; i < len; ++i) {
+ int b = bytes[off + i] & 0xFF;
+ target.append(encoding[b]);
+ target.append(encoding[b | 0x100]);
}
- };
+ }
+
+ @Override
+ int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+ checkNotNull(target);
+ if (chars.length() % 2 == 1) {
+ throw new DecodingException("Invalid input length " + chars.length());
+ }
+ int bytesWritten = 0;
+ for (int i = 0; i < chars.length(); i += 2) {
+ int decoded = alphabet.decode(chars.charAt(i)) << 4 | alphabet.decode(chars.charAt(i + 1));
+ target[bytesWritten++] = (byte) decoded;
+ }
+ return bytesWritten;
+ }
+
+ @Override
+ BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
+ return new Base16Encoding(alphabet);
+ }
+ }
+
+ static final class Base64Encoding extends StandardBaseEncoding {
+ Base64Encoding(String name, String alphabetChars, @Nullable Character paddingChar) {
+ this(new Alphabet(name, alphabetChars.toCharArray()), paddingChar);
+ }
+
+ private Base64Encoding(Alphabet alphabet, @Nullable Character paddingChar) {
+ super(alphabet, paddingChar);
+ checkArgument(alphabet.chars.length == 64);
+ }
+
+ @Override
+ void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+ checkNotNull(target);
+ checkPositionIndexes(off, off + len, bytes.length);
+ int i = off;
+ for (int remaining = len; remaining >= 3; remaining -= 3) {
+ int chunk = (bytes[i++] & 0xFF) << 16 | (bytes[i++] & 0xFF) << 8 | bytes[i++] & 0xFF;
+ target.append(alphabet.encode(chunk >>> 18));
+ target.append(alphabet.encode((chunk >>> 12) & 0x3F));
+ target.append(alphabet.encode((chunk >>> 6) & 0x3F));
+ target.append(alphabet.encode(chunk & 0x3F));
+ }
+ if (i < off + len) {
+ encodeChunkTo(target, bytes, i, off + len - i);
+ }
+ }
+
+ @Override
+ int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+ checkNotNull(target);
+ chars = padding().trimTrailingFrom(chars);
+ if (!alphabet.isValidPaddingStartPosition(chars.length())) {
+ throw new DecodingException("Invalid input length " + chars.length());
+ }
+ int bytesWritten = 0;
+ for (int i = 0; i < chars.length();) {
+ int chunk = alphabet.decode(chars.charAt(i++)) << 18;
+ chunk |= alphabet.decode(chars.charAt(i++)) << 12;
+ target[bytesWritten++] = (byte) (chunk >>> 16);
+ if (i < chars.length()) {
+ chunk |= alphabet.decode(chars.charAt(i++)) << 6;
+ target[bytesWritten++] = (byte) ((chunk >>> 8) & 0xFF);
+ if (i < chars.length()) {
+ chunk |= alphabet.decode(chars.charAt(i++));
+ target[bytesWritten++] = (byte) (chunk & 0xFF);
+ }
+ }
+ }
+ return bytesWritten;
+ }
+
+ @Override
+ BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
+ return new Base64Encoding(alphabet, paddingChar);
+ }
}
- static CharOutput separatingOutput(
- final CharOutput delegate, final String separator, final int afterEveryChars) {
+ static Appendable separatingAppendable(
+ final Appendable delegate, final String separator, final int afterEveryChars) {
checkNotNull(delegate);
checkNotNull(separator);
checkArgument(afterEveryChars > 0);
- return new CharOutput() {
+ return new Appendable() {
int charsUntilSeparator = afterEveryChars;
@Override
- public void write(char c) throws IOException {
+ public Appendable append(char c) throws IOException {
if (charsUntilSeparator == 0) {
- for (int i = 0; i < separator.length(); i++) {
- delegate.write(separator.charAt(i));
- }
+ delegate.append(separator);
charsUntilSeparator = afterEveryChars;
}
- delegate.write(c);
+ delegate.append(c);
charsUntilSeparator--;
+ return this;
}
@Override
- public void flush() throws IOException {
- delegate.flush();
+ public Appendable append(CharSequence chars, int off, int len) throws IOException {
+ throw new UnsupportedOperationException();
}
@Override
- public void close() throws IOException {
- delegate.close();
+ public Appendable append(CharSequence chars) throws IOException {
+ throw new UnsupportedOperationException();
}
};
}
@@ -776,8 +804,8 @@ public abstract class BaseEncoding {
}
@Override
- ByteOutput encodingStream(final CharOutput output) {
- return delegate.encodingStream(separatingOutput(output, separator, afterEveryChars));
+ void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+ delegate.encodeTo(separatingAppendable(target, separator, afterEveryChars), bytes, off, len);
}
@Override
@@ -786,8 +814,8 @@ public abstract class BaseEncoding {
}
@Override
- ByteInput decodingStream(final CharInput input) {
- return delegate.decodingStream(ignoringInput(input, separatorChars));
+ int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+ return delegate.decodeTo(target, separatorChars.removeFrom(chars));
}
@Override
diff --git a/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/GwtWorkarounds.java b/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/GwtWorkarounds.java
deleted file mode 100644
index f3f955e..0000000
--- a/guava-gwt/src-super/com/google/common/io/super/com/google/common/io/GwtWorkarounds.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2012 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.google.common.io;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.common.annotations.GwtCompatible;
-
-import java.io.IOException;
-
-/**
- * Provides simple GWT-compatible substitutes for {@code InputStream}, {@code OutputStream},
- * {@code Reader}, and {@code Writer} so that {@code BaseEncoding} can use streaming implementations
- * while remaining GWT-compatible.
- *
- * @author Louis Wasserman
- */
- at GwtCompatible(emulated = true)
-final class GwtWorkarounds {
- private GwtWorkarounds() {}
-
- /**
- * A GWT-compatible substitute for a {@code Reader}.
- */
- interface CharInput {
- int read() throws IOException;
- void close() throws IOException;
- }
-
- /**
- * Views a {@code CharSequence} as a {@code CharInput}.
- */
- static CharInput asCharInput(final CharSequence chars) {
- checkNotNull(chars);
- return new CharInput() {
- int index = 0;
-
- @Override
- public int read() {
- if (index < chars.length()) {
- return chars.charAt(index++);
- } else {
- return -1;
- }
- }
-
- @Override
- public void close() {
- index = chars.length();
- }
- };
- }
-
- /**
- * A GWT-compatible substitute for an {@code InputStream}.
- */
- interface ByteInput {
- int read() throws IOException;
- void close() throws IOException;
- }
-
- /**
- * A GWT-compatible substitute for an {@code OutputStream}.
- */
- interface ByteOutput {
- void write(byte b) throws IOException;
- void flush() throws IOException;
- void close() throws IOException;
- }
-
- /**
- * A GWT-compatible substitute for a {@code Writer}.
- */
- interface CharOutput {
- void write(char c) throws IOException;
- void flush() throws IOException;
- void close() throws IOException;
- }
-
- /**
- * Returns a {@code CharOutput} whose {@code toString()} method can be used
- * to get the combined output.
- */
- static CharOutput stringBuilderOutput(int initialSize) {
- final StringBuilder builder = new StringBuilder(initialSize);
- return new CharOutput() {
-
- @Override
- public void write(char c) {
- builder.append(c);
- }
-
- @Override
- public void flush() {}
-
- @Override
- public void close() {}
-
- @Override
- public String toString() {
- return builder.toString();
- }
- };
- }
-}
-
diff --git a/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/DoubleMath.java b/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/DoubleMath.java
index 2574322..2d18344 100644
--- a/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/DoubleMath.java
+++ b/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/DoubleMath.java
@@ -16,6 +16,7 @@
package com.google.common.math;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.math.MathPreconditions.checkNonNegative;
import static java.lang.Math.log;
@@ -168,6 +169,51 @@ public final class DoubleMath {
}
}
+ /**
+ * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+ * {@code values}.
+ *
+ * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+ * the arithmetic mean of the population.
+ *
+ * @param values a nonempty series of values
+ * @throws IllegalArgumentException if {@code values} is empty
+ */
+ public static double mean(int... values) {
+ checkArgument(values.length > 0, "Cannot take mean of 0 values");
+ // The upper bound on the the length of an array and the bounds on the int values mean that, in
+ // this case only, we can compute the sum as a long without risking overflow or loss of
+ // precision. So we do that, as it's slightly quicker than the Knuth algorithm.
+ long sum = 0;
+ for (int index = 0; index < values.length; ++index) {
+ sum += values[index];
+ }
+ return (double) sum / values.length;
+ }
+
+ /**
+ * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+ * {@code values}.
+ *
+ * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+ * the arithmetic mean of the population.
+ *
+ * @param values a nonempty series of values, which will be converted to {@code double} values
+ * (this may cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15))
+ * @throws IllegalArgumentException if {@code values} is empty
+ */
+ public static double mean(long... values) {
+ checkArgument(values.length > 0, "Cannot take mean of 0 values");
+ long count = 1;
+ double mean = values[0];
+ for (int index = 1; index < values.length; ++index) {
+ count++;
+ // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
+ mean += (values[index] - mean) / count;
+ }
+ return mean;
+ }
+
private DoubleMath() {}
}
diff --git a/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/LongMath.java b/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/LongMath.java
index a210627..5a617da 100644
--- a/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/LongMath.java
+++ b/guava-gwt/src-super/com/google/common/math/super/com/google/common/math/LongMath.java
@@ -26,6 +26,7 @@ import static java.math.RoundingMode.HALF_UP;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.primitives.UnsignedLongs;
import java.math.RoundingMode;
@@ -56,7 +57,7 @@ public final class LongMath {
public static boolean isPowerOfTwo(long x) {
return x > 0 & (x & (x - 1)) == 0;
}
-
+
/**
* Returns 1 if {@code x < y} as unsigned longs, and 0 otherwise. Assumes that x - y fits into a
* signed long. The implementation is branch-free, and benchmarks suggest it is measurably
@@ -227,14 +228,14 @@ public final class LongMath {
return result;
} else {
int nBits = LongMath.log2(n, RoundingMode.CEILING);
-
+
long result = 1;
long numerator = n--;
long denominator = 1;
-
+
int numeratorBits = nBits;
// This is an upper bound on log2(numerator, ceiling).
-
+
/*
* We want to do this in long math for speed, but want to avoid overflow. We adapt the
* technique previously used by BigIntegerMath: maintain separate numerator and
@@ -259,7 +260,7 @@ public final class LongMath {
}
}
}
-
+
/**
* Returns (x * numerator / denominator), which is assumed to come out to an integral value.
*/
@@ -311,6 +312,190 @@ public final class LongMath {
// The alternative (x + y) >>> 1 fails for negative values.
return (x & y) + ((x ^ y) >> 1);
}
+
+ /*
+ * If n <= millerRabinBases[i][0], then testing n against bases millerRabinBases[i][1..]
+ * suffices to prove its primality. Values from miller-rabin.appspot.com.
+ *
+ * NOTE: We could get slightly better bases that would be treated as unsigned, but benchmarks
+ * showed negligible performance improvements.
+ */
+ private static final long[][] millerRabinBaseSets = {
+ {291830, 126401071349994536L},
+ {885594168, 725270293939359937L, 3569819667048198375L},
+ {273919523040L, 15, 7363882082L, 992620450144556L},
+ {47636622961200L, 2, 2570940, 211991001, 3749873356L},
+ {7999252175582850L,
+ 2, 4130806001517L, 149795463772692060L, 186635894390467037L, 3967304179347715805L},
+ {585226005592931976L,
+ 2, 123635709730000L, 9233062284813009L, 43835965440333360L, 761179012939631437L,
+ 1263739024124850375L},
+ {Long.MAX_VALUE,
+ 2, 325, 9375, 28178, 450775, 9780504, 1795265022}
+ };
+
+ private enum MillerRabinTester {
+ /**
+ * Works for inputs <= FLOOR_SQRT_MAX_LONG.
+ */
+ SMALL {
+ @Override
+ long mulMod(long a, long b, long m) {
+ /*
+ * NOTE(lowasser, 2015-Feb-12): Benchmarks suggest that changing this to
+ * UnsignedLongs.remainder and increasing the threshold to 2^32 doesn't pay for itself,
+ * and adding another enum constant hurts performance further -- I suspect because
+ * bimorphic implementation is a sweet spot for the JVM.
+ */
+ return (a * b) % m;
+ }
+
+ @Override
+ long squareMod(long a, long m) {
+ return (a * a) % m;
+ }
+ },
+ /**
+ * Works for all nonnegative signed longs.
+ */
+ LARGE {
+ /**
+ * Returns (a + b) mod m. Precondition: 0 <= a, b < m < 2^63.
+ */
+ private long plusMod(long a, long b, long m) {
+ return (a >= m - b) ? (a + b - m) : (a + b);
+ }
+
+ /**
+ * Returns (a * 2^32) mod m. a may be any unsigned long.
+ */
+ private long times2ToThe32Mod(long a, long m) {
+ int remainingPowersOf2 = 32;
+ do {
+ int shift = Math.min(remainingPowersOf2, Long.numberOfLeadingZeros(a));
+ // shift is either the number of powers of 2 left to multiply a by, or the biggest shift
+ // possible while keeping a in an unsigned long.
+ a = UnsignedLongs.remainder(a << shift, m);
+ remainingPowersOf2 -= shift;
+ } while (remainingPowersOf2 > 0);
+ return a;
+ }
+
+ @Override
+ long mulMod(long a, long b, long m) {
+ long aHi = a >>> 32; // < 2^31
+ long bHi = b >>> 32; // < 2^31
+ long aLo = a & 0xFFFFFFFFL; // < 2^32
+ long bLo = b & 0xFFFFFFFFL; // < 2^32
+
+ /*
+ * a * b == aHi * bHi * 2^64 + (aHi * bLo + aLo * bHi) * 2^63 + aLo * bLo.
+ * == (aHi * bHi * 2^32 + aHi * bLo + aLo * bHi) * 2^32 + aLo * bLo
+ *
+ * We carry out this computation in modular arithmetic. Since times2ToThe32Mod accepts
+ * any unsigned long, we don't have to do a mod on every operation, only when intermediate
+ * results can exceed 2^63.
+ */
+ long result = times2ToThe32Mod(aHi * bHi /* < 2^62 */, m); // < m < 2^63
+ result += aHi * bLo; // aHi * bLo < 2^63, result < 2^64
+ if (result < 0) {
+ result = UnsignedLongs.remainder(result, m);
+ }
+ // result < 2^63 again
+ result += aLo * bHi; // aLo * bHi < 2^63, result < 2^64
+ result = times2ToThe32Mod(result, m); // result < m < 2^63
+ return plusMod(
+ result,
+ UnsignedLongs.remainder(aLo * bLo /* < 2^64 */, m),
+ m);
+ }
+
+ @Override
+ long squareMod(long a, long m) {
+ long aHi = a >>> 32; // < 2^31
+ long aLo = a & 0xFFFFFFFFL; // < 2^32
+
+ /*
+ * a^2 == aHi^2 * 2^64 + aHi * aLo * 2^33 + aLo^2
+ * == (aHi^2 * 2^32 + aHi * aLo * 2) * 2^32 + aLo^2
+ * We carry out this computation in modular arithmetic. Since times2ToThe32Mod accepts
+ * any unsigned long, we don't have to do a mod on every operation, only when intermediate
+ * results can exceed 2^63.
+ */
+ long result = times2ToThe32Mod(aHi * aHi /* < 2^62 */, m); // < m < 2^63
+ long hiLo = aHi * aLo * 2;
+ if (hiLo < 0) {
+ hiLo = UnsignedLongs.remainder(hiLo, m);
+ }
+ // hiLo < 2^63
+ result += hiLo; // result < 2^64
+ result = times2ToThe32Mod(result, m); // result < m < 2^63
+ return plusMod(
+ result,
+ UnsignedLongs.remainder(aLo * aLo /* < 2^64 */, m),
+ m);
+ }
+ };
+
+ static boolean test(long base, long n) {
+ // Since base will be considered % n, it's okay if base > FLOOR_SQRT_MAX_LONG,
+ // so long as n <= FLOOR_SQRT_MAX_LONG.
+ return ((n <= FLOOR_SQRT_MAX_LONG) ? SMALL : LARGE).testWitness(base, n);
+ }
+
+ /**
+ * Returns a * b mod m.
+ */
+ abstract long mulMod(long a, long b, long m);
+
+ /**
+ * Returns a^2 mod m.
+ */
+ abstract long squareMod(long a, long m);
+
+ /**
+ * Returns a^p mod m.
+ */
+ private long powMod(long a, long p, long m) {
+ long res = 1;
+ for (; p != 0; p >>= 1) {
+ if ((p & 1) != 0) {
+ res = mulMod(res, a, m);
+ }
+ a = squareMod(a, m);
+ }
+ return res;
+ }
+
+ /**
+ * Returns true if n is a strong probable prime relative to the specified base.
+ */
+ private boolean testWitness(long base, long n) {
+ int r = Long.numberOfTrailingZeros(n - 1);
+ long d = (n - 1) >> r;
+ base %= n;
+ if (base == 0) {
+ return true;
+ }
+ // Calculate a := base^d mod n.
+ long a = powMod(base, d, n);
+ // n passes this test if
+ // base^d = 1 (mod n)
+ // or base^(2^j * d) = -1 (mod n) for some 0 <= j < r.
+ if (a == 1) {
+ return true;
+ }
+ int j = 0;
+ while (a != n - 1) {
+ if (++j == r) {
+ return false;
+ }
+ a = squareMod(a, n);
+ }
+ return true;
+ }
+ }
private LongMath() {}
}
+
diff --git a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Chars.java b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Chars.java
index c167373..df84c50 100644
--- a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Chars.java
+++ b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Chars.java
@@ -31,6 +31,9 @@ import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
/**
* Static utility methods pertaining to {@code char} primitives, that are not
* already found in either {@link Character} or {@link Arrays}.
@@ -39,12 +42,13 @@ import java.util.RandomAccess;
* numerically; they are neither Unicode-aware nor locale-dependent.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class Chars {
private Chars() {}
@@ -149,8 +153,7 @@ public final class Chars {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- char[] array, char target, int start, int end) {
+ private static int indexOf(char[] array, char target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -203,8 +206,7 @@ public final class Chars {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- char[] array, char target, int start, int end) {
+ private static int lastIndexOf(char[] array, char target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -290,8 +292,7 @@ public final class Chars {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static char[] ensureCapacity(
- char[] array, int minLength, int padding) {
+ public static char[] ensureCapacity(char[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -322,8 +323,7 @@ public final class Chars {
return "";
}
- StringBuilder builder
- = new StringBuilder(len + separator.length() * (len - 1));
+ StringBuilder builder = new StringBuilder(len + separator.length() * (len - 1));
builder.append(array[0]);
for (int i = 1; i < len; i++) {
builder.append(separator).append(array[i]);
@@ -434,26 +434,31 @@ public final class Chars {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Character get(int index) {
+ @Override
+ public Character get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Character)
&& Chars.indexOf(array, (Character) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Character) {
int i = Chars.indexOf(array, (Character) target, start, end);
@@ -464,7 +469,8 @@ public final class Chars {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Character) {
int i = Chars.lastIndexOf(array, (Character) target, start, end);
@@ -475,7 +481,8 @@ public final class Chars {
return -1;
}
- @Override public Character set(int index, Character element) {
+ @Override
+ public Character set(int index, Character element) {
checkElementIndex(index, size());
char oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -483,7 +490,8 @@ public final class Chars {
return oldValue;
}
- @Override public List<Character> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Character> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -492,7 +500,8 @@ public final class Chars {
return new CharArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -512,7 +521,8 @@ public final class Chars {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Chars.hashCode(array[i]);
@@ -520,7 +530,8 @@ public final class Chars {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 3);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
diff --git a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Doubles.java b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Doubles.java
index 0b7bb63..6117678 100644
--- a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Doubles.java
+++ b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Doubles.java
@@ -35,17 +35,21 @@ import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
/**
* Static utility methods pertaining to {@code double} primitives, that are not
* already found in either {@link Double} or {@link Arrays}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class Doubles {
private Doubles() {}
@@ -136,8 +140,7 @@ public final class Doubles {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- double[] array, double target, int start, int end) {
+ private static int indexOf(double[] array, double target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -194,8 +197,7 @@ public final class Doubles {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- double[] array, double target, int start, int end) {
+ private static int lastIndexOf(double[] array, double target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -263,8 +265,8 @@ public final class Doubles {
return result;
}
- private static final class DoubleConverter
- extends Converter<String, Double> implements Serializable {
+ private static final class DoubleConverter extends Converter<String, Double>
+ implements Serializable {
static final DoubleConverter INSTANCE = new DoubleConverter();
@Override
@@ -285,6 +287,7 @@ public final class Doubles {
private Object readResolve() {
return INSTANCE;
}
+
private static final long serialVersionUID = 1;
}
@@ -315,8 +318,7 @@ public final class Doubles {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static double[] ensureCapacity(
- double[] array, int minLength, int padding) {
+ public static double[] ensureCapacity(double[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -467,26 +469,31 @@ public final class Doubles {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Double get(int index) {
+ @Override
+ public Double get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Double)
&& Doubles.indexOf(array, (Double) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Double) {
int i = Doubles.indexOf(array, (Double) target, start, end);
@@ -497,7 +504,8 @@ public final class Doubles {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Double) {
int i = Doubles.lastIndexOf(array, (Double) target, start, end);
@@ -508,7 +516,8 @@ public final class Doubles {
return -1;
}
- @Override public Double set(int index, Double element) {
+ @Override
+ public Double set(int index, Double element) {
checkElementIndex(index, size());
double oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -516,7 +525,8 @@ public final class Doubles {
return oldValue;
}
- @Override public List<Double> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Double> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -525,7 +535,8 @@ public final class Doubles {
return new DoubleArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -545,7 +556,8 @@ public final class Doubles {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Doubles.hashCode(array[i]);
@@ -553,7 +565,8 @@ public final class Doubles {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 12);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
diff --git a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Floats.java b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Floats.java
index d669e50..4234d38 100644
--- a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Floats.java
+++ b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Floats.java
@@ -35,17 +35,21 @@ import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
/**
* Static utility methods pertaining to {@code float} primitives, that are not
* already found in either {@link Float} or {@link Arrays}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class Floats {
private Floats() {}
@@ -133,8 +137,7 @@ public final class Floats {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- float[] array, float target, int start, int end) {
+ private static int indexOf(float[] array, float target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -191,8 +194,7 @@ public final class Floats {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- float[] array, float target, int start, int end) {
+ private static int lastIndexOf(float[] array, float target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -221,7 +223,7 @@ public final class Floats {
/**
* Returns the greatest value present in {@code array}, using the same rules
- * of comparison as {@link Math#min(float, float)}.
+ * of comparison as {@link Math#max(float, float)}.
*
* @param array a <i>nonempty</i> array of {@code float} values
* @return the value present in {@code array} that is greater than or equal to
@@ -260,8 +262,8 @@ public final class Floats {
return result;
}
- private static final class FloatConverter
- extends Converter<String, Float> implements Serializable {
+ private static final class FloatConverter extends Converter<String, Float>
+ implements Serializable {
static final FloatConverter INSTANCE = new FloatConverter();
@Override
@@ -282,6 +284,7 @@ public final class Floats {
private Object readResolve() {
return INSTANCE;
}
+
private static final long serialVersionUID = 1;
}
@@ -312,8 +315,7 @@ public final class Floats {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static float[] ensureCapacity(
- float[] array, int minLength, int padding) {
+ public static float[] ensureCapacity(float[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -464,26 +466,30 @@ public final class Floats {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Float get(int index) {
+ @Override
+ public Float get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
- return (target instanceof Float)
- && Floats.indexOf(array, (Float) target, start, end) != -1;
+ return (target instanceof Float) && Floats.indexOf(array, (Float) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Float) {
int i = Floats.indexOf(array, (Float) target, start, end);
@@ -494,7 +500,8 @@ public final class Floats {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Float) {
int i = Floats.lastIndexOf(array, (Float) target, start, end);
@@ -505,7 +512,8 @@ public final class Floats {
return -1;
}
- @Override public Float set(int index, Float element) {
+ @Override
+ public Float set(int index, Float element) {
checkElementIndex(index, size());
float oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -513,7 +521,8 @@ public final class Floats {
return oldValue;
}
- @Override public List<Float> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Float> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -522,7 +531,8 @@ public final class Floats {
return new FloatArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -542,7 +552,8 @@ public final class Floats {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Floats.hashCode(array[i]);
@@ -550,7 +561,8 @@ public final class Floats {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 12);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
diff --git a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Ints.java b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Ints.java
index eb14ea5..6938ae9 100644
--- a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Ints.java
+++ b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Ints.java
@@ -27,7 +27,6 @@ import com.google.common.base.Converter;
import java.io.Serializable;
import java.util.AbstractList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -35,18 +34,21 @@ import java.util.List;
import java.util.RandomAccess;
import javax.annotation.CheckForNull;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
/**
* Static utility methods pertaining to {@code int} primitives, that are not
* already found in either {@link Integer} or {@link Arrays}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class Ints {
private Ints() {}
@@ -158,8 +160,7 @@ public final class Ints {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- int[] array, int target, int start, int end) {
+ private static int indexOf(int[] array, int target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -212,8 +213,7 @@ public final class Ints {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- int[] array, int target, int start, int end) {
+ private static int lastIndexOf(int[] array, int target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -283,8 +283,8 @@ public final class Ints {
return result;
}
- private static final class IntConverter
- extends Converter<String, Integer> implements Serializable {
+ private static final class IntConverter extends Converter<String, Integer>
+ implements Serializable {
static final IntConverter INSTANCE = new IntConverter();
@Override
@@ -305,6 +305,7 @@ public final class Ints {
private Object readResolve() {
return INSTANCE;
}
+
private static final long serialVersionUID = 1;
}
@@ -335,8 +336,7 @@ public final class Ints {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static int[] ensureCapacity(
- int[] array, int minLength, int padding) {
+ public static int[] ensureCapacity(int[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -478,26 +478,30 @@ public final class Ints {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Integer get(int index) {
+ @Override
+ public Integer get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
- return (target instanceof Integer)
- && Ints.indexOf(array, (Integer) target, start, end) != -1;
+ return (target instanceof Integer) && Ints.indexOf(array, (Integer) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Integer) {
int i = Ints.indexOf(array, (Integer) target, start, end);
@@ -508,7 +512,8 @@ public final class Ints {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Integer) {
int i = Ints.lastIndexOf(array, (Integer) target, start, end);
@@ -519,7 +524,8 @@ public final class Ints {
return -1;
}
- @Override public Integer set(int index, Integer element) {
+ @Override
+ public Integer set(int index, Integer element) {
checkElementIndex(index, size());
int oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -527,7 +533,8 @@ public final class Ints {
return oldValue;
}
- @Override public List<Integer> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Integer> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -536,7 +543,8 @@ public final class Ints {
return new IntArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -556,7 +564,8 @@ public final class Ints {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Ints.hashCode(array[i]);
@@ -564,7 +573,8 @@ public final class Ints {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 5);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
@@ -584,23 +594,6 @@ public final class Ints {
private static final long serialVersionUID = 0;
}
- private static final byte[] asciiDigits = new byte[128];
-
- static {
- Arrays.fill(asciiDigits, (byte) -1);
- for (int i = 0; i <= 9; i++) {
- asciiDigits['0' + i] = (byte) i;
- }
- for (int i = 0; i <= 26; i++) {
- asciiDigits['A' + i] = (byte) (10 + i);
- asciiDigits['a' + i] = (byte) (10 + i);
- }
- }
-
- private static int digit(char c) {
- return (c < 128) ? asciiDigits[c] : -1;
- }
-
/**
* Parses the specified string as a signed decimal integer value. The ASCII
* character {@code '-'} (<code>'\u002D'</code>) is recognized as the
@@ -622,6 +615,7 @@ public final class Ints {
* @since 11.0
*/
@Beta
+ @Nullable
@CheckForNull
public static Integer tryParse(String string) {
return tryParse(string, 10);
@@ -648,47 +642,18 @@ public final class Ints {
* or cannot be parsed as an integer value
* @throws IllegalArgumentException if {@code radix < Character.MIN_RADIX} or
* {@code radix > Character.MAX_RADIX}
+ * @since 19.0
*/
- @CheckForNull static Integer tryParse(
+ @Beta
+ @Nullable
+ @CheckForNull
+ public static Integer tryParse(
String string, int radix) {
- if (checkNotNull(string).isEmpty()) {
- return null;
- }
- if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
- throw new IllegalArgumentException(
- "radix must be between MIN_RADIX and MAX_RADIX but was " + radix);
- }
- boolean negative = string.charAt(0) == '-';
- int index = negative ? 1 : 0;
- if (index == string.length()) {
- return null;
- }
- int digit = digit(string.charAt(index++));
- if (digit < 0 || digit >= radix) {
- return null;
- }
- int accum = -digit;
-
- int cap = Integer.MIN_VALUE / radix;
-
- while (index < string.length()) {
- digit = digit(string.charAt(index++));
- if (digit < 0 || digit >= radix || accum < cap) {
- return null;
- }
- accum *= radix;
- if (accum < Integer.MIN_VALUE + digit) {
- return null;
- }
- accum -= digit;
- }
-
- if (negative) {
- return accum;
- } else if (accum == Integer.MIN_VALUE) {
+ Long result = Longs.tryParse(string, radix);
+ if (result == null || result.longValue() != result.intValue()) {
return null;
} else {
- return -accum;
+ return result.intValue();
}
}
}
diff --git a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Shorts.java b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Shorts.java
index 221255b..d776550 100644
--- a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Shorts.java
+++ b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/Shorts.java
@@ -33,17 +33,20 @@ import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
+import javax.annotation.CheckReturnValue;
+
/**
* Static utility methods pertaining to {@code short} primitives, that are not
* already found in either {@link Short} or {@link Arrays}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class Shorts {
private Shorts() {}
@@ -156,8 +159,7 @@ public final class Shorts {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- short[] array, short target, int start, int end) {
+ private static int indexOf(short[] array, short target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -210,8 +212,7 @@ public final class Shorts {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- short[] array, short target, int start, int end) {
+ private static int lastIndexOf(short[] array, short target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -281,8 +282,8 @@ public final class Shorts {
return result;
}
- private static final class ShortConverter
- extends Converter<String, Short> implements Serializable {
+ private static final class ShortConverter extends Converter<String, Short>
+ implements Serializable {
static final ShortConverter INSTANCE = new ShortConverter();
@Override
@@ -303,6 +304,7 @@ public final class Shorts {
private Object readResolve() {
return INSTANCE;
}
+
private static final long serialVersionUID = 1;
}
@@ -333,8 +335,7 @@ public final class Shorts {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static short[] ensureCapacity(
- short[] array, int minLength, int padding) {
+ public static short[] ensureCapacity(short[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -477,26 +478,30 @@ public final class Shorts {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Short get(int index) {
+ @Override
+ public Short get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
- return (target instanceof Short)
- && Shorts.indexOf(array, (Short) target, start, end) != -1;
+ return (target instanceof Short) && Shorts.indexOf(array, (Short) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Short) {
int i = Shorts.indexOf(array, (Short) target, start, end);
@@ -507,7 +512,8 @@ public final class Shorts {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Short) {
int i = Shorts.lastIndexOf(array, (Short) target, start, end);
@@ -518,7 +524,8 @@ public final class Shorts {
return -1;
}
- @Override public Short set(int index, Short element) {
+ @Override
+ public Short set(int index, Short element) {
checkElementIndex(index, size());
short oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -526,7 +533,8 @@ public final class Shorts {
return oldValue;
}
- @Override public List<Short> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Short> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -535,7 +543,8 @@ public final class Shorts {
return new ShortArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(Object object) {
if (object == this) {
return true;
}
@@ -555,7 +564,8 @@ public final class Shorts {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Shorts.hashCode(array[i]);
@@ -563,7 +573,8 @@ public final class Shorts {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 6);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
diff --git a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedInteger.java b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedInteger.java
index 8ddc57d..54f4c15 100644
--- a/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedInteger.java
+++ b/guava-gwt/src-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedInteger.java
@@ -1,11 +1,11 @@
/*
* Copyright (C) 2011 The Guava Authors
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
@@ -29,17 +29,18 @@ import javax.annotation.Nullable;
/**
* A wrapper class for unsigned {@code int} values, supporting arithmetic operations.
- *
+ *
* <p>In some cases, when speed is more important than code readability, it may be faster simply to
* treat primitive {@code int} values as unsigned, using the methods from {@link UnsignedInts}.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">
* unsigned primitive utilities</a>.
- *
+ *
* @author Louis Wasserman
* @since 11.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class UnsignedInteger extends Number implements Comparable<UnsignedInteger> {
public static final UnsignedInteger ZERO = fromIntBits(0);
@@ -62,7 +63,7 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
* otherwise, the result will be equal to {@code 2^32 + bits}.
*
* <p>To represent unsigned decimal constants, consider {@link #valueOf(long)} instead.
- *
+ *
* @since 14.0
*/
public static UnsignedInteger fromIntBits(int bits) {
@@ -74,28 +75,32 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
* if possible. The inverse operation of {@link #longValue()}.
*/
public static UnsignedInteger valueOf(long value) {
- checkArgument((value & INT_MASK) == value,
- "value (%s) is outside the range for an unsigned integer value", value);
+ checkArgument(
+ (value & INT_MASK) == value,
+ "value (%s) is outside the range for an unsigned integer value",
+ value);
return fromIntBits((int) value);
}
/**
* Returns a {@code UnsignedInteger} representing the same value as the specified
* {@link BigInteger}. This is the inverse operation of {@link #bigIntegerValue()}.
- *
+ *
* @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^32}
*/
public static UnsignedInteger valueOf(BigInteger value) {
checkNotNull(value);
- checkArgument(value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
- "value (%s) is outside the range for an unsigned integer value", value);
+ checkArgument(
+ value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
+ "value (%s) is outside the range for an unsigned integer value",
+ value);
return fromIntBits(value.intValue());
}
/**
* Returns an {@code UnsignedInteger} holding the value of the specified {@code String}, parsed
* as an unsigned {@code int} value.
- *
+ *
* @throws NumberFormatException if the string does not contain a parsable unsigned {@code int}
* value
*/
@@ -106,7 +111,7 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
/**
* Returns an {@code UnsignedInteger} holding the value of the specified {@code String}, parsed
* as an unsigned {@code int} value in the specified radix.
- *
+ *
* @throws NumberFormatException if the string does not contain a parsable unsigned {@code int}
* value
*/
@@ -117,10 +122,9 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
/**
* Returns the result of adding this and {@code val}. If the result would have more than 32 bits,
* returns the low 32 bits of the result.
- *
+ *
* @since 14.0
*/
- @CheckReturnValue
public UnsignedInteger plus(UnsignedInteger val) {
return fromIntBits(this.value + checkNotNull(val).value);
}
@@ -128,32 +132,29 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
/**
* Returns the result of subtracting this and {@code val}. If the result would be negative,
* returns the low 32 bits of the result.
- *
+ *
* @since 14.0
*/
- @CheckReturnValue
public UnsignedInteger minus(UnsignedInteger val) {
return fromIntBits(value - checkNotNull(val).value);
}
/**
* Returns the result of dividing this by {@code val}.
- *
+ *
* @throws ArithmeticException if {@code val} is zero
* @since 14.0
*/
- @CheckReturnValue
public UnsignedInteger dividedBy(UnsignedInteger val) {
return fromIntBits(UnsignedInts.divide(value, checkNotNull(val).value));
}
/**
* Returns this mod {@code val}.
- *
+ *
* @throws ArithmeticException if {@code val} is zero
* @since 14.0
*/
- @CheckReturnValue
public UnsignedInteger mod(UnsignedInteger val) {
return fromIntBits(UnsignedInts.remainder(value, checkNotNull(val).value));
}
@@ -161,7 +162,7 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
/**
* Returns the value of this {@code UnsignedInteger} as an {@code int}. This is an inverse
* operation to {@link #fromIntBits}.
- *
+ *
* <p>Note that if this {@code UnsignedInteger} holds a value {@code >= 2^31}, the returned value
* will be equal to {@code this - 2^32}.
*/
diff --git a/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AbstractFuture.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AbstractFuture.java
new file mode 100644
index 0000000..931e3fe
--- /dev/null
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AbstractFuture.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.Nullable;
+
+/**
+ * Emulation for AbstractFuture in GWT.
+ */
+public abstract class AbstractFuture<V> implements ListenableFuture<V> {
+
+ abstract static class TrustedFuture<V> extends AbstractFuture<V> {
+ @Override public final V get() throws InterruptedException, ExecutionException {
+ return super.get();
+ }
+
+ @Override public final V get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return super.get(timeout, unit);
+ }
+
+ @Override public final boolean isDone() {
+ return super.isDone();
+ }
+
+ @Override public final boolean isCancelled() {
+ return super.isCancelled();
+ }
+
+ @Override public final void addListener(Runnable listener, Executor executor) {
+ super.addListener(listener, executor);
+ }
+ }
+
+ private static final Logger log = Logger.getLogger(AbstractFuture.class.getName());
+
+ private State state;
+ private V value;
+ private Future<? extends V> delegate;
+ private Throwable throwable;
+ private boolean mayInterruptIfRunning;
+ private List<Listener> listeners;
+
+ protected AbstractFuture() {
+ state = State.PENDING;
+ listeners = new ArrayList<Listener>();
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ if (!state.permitsPublicUserToTransitionTo(State.CANCELLED)) {
+ return false;
+ }
+
+ this.mayInterruptIfRunning = mayInterruptIfRunning;
+ state = State.CANCELLED;
+ notifyAndClearListeners();
+
+ if (delegate != null) {
+ delegate.cancel(mayInterruptIfRunning);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return state.isCancelled();
+ }
+
+ @Override
+ public boolean isDone() {
+ return state.isDone();
+ }
+
+ @Override
+ public V get() throws InterruptedException, ExecutionException {
+ state.maybeThrowOnGet(throwable);
+ return value;
+ }
+
+ @Override
+ public V get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ checkNotNull(unit);
+ return get();
+ }
+
+ @Override
+ public void addListener(Runnable runnable, Executor executor) {
+ Listener listener = new Listener(runnable, executor);
+ if (isDone()) {
+ listener.execute();
+ } else {
+ listeners.add(listener);
+ }
+ }
+
+ protected boolean setException(Throwable throwable) {
+ checkNotNull(throwable);
+ if (!state.permitsPublicUserToTransitionTo(State.FAILURE)) {
+ return false;
+ }
+
+ forceSetException(throwable);
+ return true;
+ }
+
+ private void forceSetException(Throwable throwable) {
+ this.throwable = throwable;
+ this.state = State.FAILURE;
+ notifyAndClearListeners();
+ }
+
+ protected boolean set(V value) {
+ if (!state.permitsPublicUserToTransitionTo(State.VALUE)) {
+ return false;
+ }
+
+ forceSet(value);
+ return true;
+ }
+
+ private void forceSet(V value) {
+ this.value = value;
+ this.state = State.VALUE;
+ notifyAndClearListeners();
+ }
+
+ protected boolean setFuture(ListenableFuture<? extends V> future) {
+ checkNotNull(future);
+
+ // If this future is already cancelled, cancel the delegate.
+ if (isCancelled()) {
+ future.cancel(mayInterruptIfRunning);
+ }
+
+ if (!state.permitsPublicUserToTransitionTo(State.DELEGATED)) {
+ return false;
+ }
+
+ state = State.DELEGATED;
+ this.delegate = future;
+
+ future.addListener(new SetFuture(future), directExecutor());
+ return true;
+ }
+
+ protected final boolean wasInterrupted() {
+ return mayInterruptIfRunning;
+ }
+
+ private void notifyAndClearListeners() {
+ // TODO(cpovirk): consider clearing this.delegate
+ for (Listener listener : listeners) {
+ listener.execute();
+ }
+ listeners = null;
+ done();
+ }
+
+ void done() {}
+
+ final Throwable trustedGetException() {
+ checkState(state == State.FAILURE);
+ return throwable;
+ }
+
+ final void maybePropagateCancellation(@Nullable Future<?> related) {
+ if (related != null & isCancelled()) {
+ related.cancel(wasInterrupted());
+ }
+ }
+
+ private enum State {
+ PENDING {
+ @Override
+ boolean isDone() {
+ return false;
+ }
+
+ @Override
+ void maybeThrowOnGet(Throwable cause) throws ExecutionException {
+ throw new IllegalStateException("Cannot get() on a pending future.");
+ }
+
+ @Override
+ boolean permitsPublicUserToTransitionTo(State state) {
+ return !state.equals(PENDING);
+ }
+ },
+ DELEGATED {
+ @Override
+ boolean isDone() {
+ return false;
+ }
+
+ @Override
+ void maybeThrowOnGet(Throwable cause) throws ExecutionException {
+ throw new IllegalStateException("Cannot get() on a pending future.");
+ }
+
+ boolean permitsPublicUserToTransitionTo(State state) {
+ return state.equals(CANCELLED);
+ }
+ },
+ VALUE,
+ FAILURE {
+ @Override
+ void maybeThrowOnGet(Throwable cause) throws ExecutionException {
+ throw new ExecutionException(cause);
+ }
+ },
+ CANCELLED {
+ @Override
+ boolean isCancelled() {
+ return true;
+ }
+
+ @Override
+ void maybeThrowOnGet(Throwable cause) throws ExecutionException {
+ // TODO(cpovirk): chain in a CancellationException created at the cancel() call?
+ throw new CancellationException();
+ }
+ };
+
+ boolean isDone() {
+ return true;
+ }
+
+ boolean isCancelled() {
+ return false;
+ }
+
+ void maybeThrowOnGet(Throwable cause) throws ExecutionException {}
+
+ boolean permitsPublicUserToTransitionTo(State state) {
+ return false;
+ }
+ }
+
+ private static final class Listener {
+ final Runnable command;
+ final Executor executor;
+
+ Listener(Runnable command, Executor executor) {
+ this.command = checkNotNull(command);
+ this.executor = checkNotNull(executor);
+ }
+
+ void execute() {
+ try {
+ executor.execute(command);
+ } catch (RuntimeException e) {
+ log.log(Level.SEVERE, "RuntimeException while executing runnable "
+ + command + " with executor " + executor, e);
+ }
+ }
+ }
+
+ private final class SetFuture implements Runnable {
+ final ListenableFuture<? extends V> delegate;
+
+ SetFuture(ListenableFuture<? extends V> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void run() {
+ if (isCancelled()) {
+ return;
+ }
+
+ if (delegate instanceof TrustedFuture) {
+ AbstractFuture<? extends V> other = (AbstractFuture<? extends V>) delegate;
+ value = other.value;
+ throwable = other.throwable;
+ mayInterruptIfRunning = other.mayInterruptIfRunning;
+ state = other.state;
+
+ notifyAndClearListeners();
+ return;
+ }
+
+ try {
+ forceSet(getUninterruptibly(delegate));
+ } catch (ExecutionException exception) {
+ forceSetException(exception.getCause());
+ } catch (CancellationException cancellation) {
+ cancel(false);
+ } catch (Throwable t) {
+ forceSetException(t);
+ }
+ }
+ }
+}
diff --git a/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AggregateFutureState.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AggregateFutureState.java
new file mode 100644
index 0000000..780adc8
--- /dev/null
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AggregateFutureState.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2006 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.collect.Sets.newHashSet;
+
+import java.util.Set;
+
+/**
+ * Emulation of AggregateFutureState.
+ */
+abstract class AggregateFutureState {
+ // Lazily initialized the first time we see an exception; not released until all the input futures
+ // & this future completes. Released when the future releases the reference to the running state
+ private Set<Throwable> seenExceptions = null;
+ private int remaining;
+
+ AggregateFutureState(int remainingFutures) {
+ this.remaining = remainingFutures;
+ }
+
+ final Set<Throwable> getOrInitSeenExceptions() {
+ if (seenExceptions == null) {
+ seenExceptions = newHashSet();
+ addInitialException(seenExceptions);
+ }
+ return seenExceptions;
+ }
+
+ abstract void addInitialException(Set<Throwable> seen);
+
+ final int decrementRemainingAndGet() {
+ return --remaining;
+ }
+}
diff --git a/guava/src/com/google/common/collect/ComputationException.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Callables.java
similarity index 56%
copy from guava/src/com/google/common/collect/ComputationException.java
copy to guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Callables.java
index ac80d6a..0da6387 100644
--- a/guava/src/com/google/common/collect/ComputationException.java
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Callables.java
@@ -14,25 +14,33 @@
* limitations under the License.
*/
-package com.google.common.collect;
+package com.google.common.util.concurrent;
import com.google.common.annotations.GwtCompatible;
+import java.util.concurrent.Callable;
+
import javax.annotation.Nullable;
/**
- * Wraps an exception that occurred during a computation.
+ * Static utility methods pertaining to the {@link Callable} interface.
*
- * @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @author Isaac Shum
+ * @since 1.0
*/
- at GwtCompatible
-public class ComputationException extends RuntimeException {
+ at GwtCompatible(emulated = true)
+public final class Callables {
+ private Callables() {}
+
/**
- * Creates a new instance with the given cause.
+ * Creates a {@code Callable} which immediately returns a preset value each
+ * time it is called.
*/
- public ComputationException(@Nullable Throwable cause) {
- super(cause);
+ public static <T> Callable<T> returning(final @Nullable T value) {
+ return new Callable<T>() {
+ @Override public T call() {
+ return value;
+ }
+ };
}
- private static final long serialVersionUID = 0;
}
diff --git a/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Futures.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Futures.java
new file mode 100644
index 0000000..4b60f95
--- /dev/null
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Futures.java
@@ -0,0 +1,1267 @@
+/*
+ * Copyright (C) 2006 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.Platform.isInstanceOfThrowableClass;
+import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
+/**
+ * Static utility methods pertaining to the {@link Future} interface.
+ *
+ * <p>Many of these methods use the {@link ListenableFuture} API; consult the
+ * Guava User Guide article on <a href=
+ * "https://github.com/google/guava/wiki/ListenableFutureExplained">
+ * {@code ListenableFuture}</a>.
+ *
+ * @author Kevin Bourrillion
+ * @author Nishant Thakkar
+ * @author Sven Mawson
+ * @since 1.0
+ */
+ at Beta
+ at GwtCompatible(emulated = true)
+public final class Futures extends GwtFuturesCatchingSpecialization {
+
+ // A note on memory visibility.
+ // Many of the utilities in this class (transform, withFallback, withTimeout, asList, combine)
+ // have two requirements that significantly complicate their design.
+ // 1. Cancellation should propagate from the returned future to the input future(s).
+ // 2. The returned futures shouldn't unnecessarily 'pin' their inputs after completion.
+ //
+ // A consequence of these requirements is that the delegate futures cannot be stored in
+ // final fields.
+ //
+ // For simplicity the rest of this description will discuss Futures.catching since it is the
+ // simplest instance, though very similar descriptions apply to many other classes in this file.
+ //
+ // In the constructor of AbstractCatchingFuture, the delegate future is assigned to a field
+ // 'inputFuture'. That field is non-final and non-volatile. There are 2 places where the
+ // 'inputFuture' field is read and where we will have to consider visibility of the write
+ // operation in the constructor.
+ //
+ // 1. In the listener that performs the callback. In this case it is fine since inputFuture is
+ // assigned prior to calling addListener, and addListener happens-before any invocation of the
+ // listener. Notably, this means that 'volatile' is unnecessary to make 'inputFuture' visible
+ // to the listener.
+ //
+ // 2. In done() where we may propagate cancellation to the input. In this case it is _not_ fine.
+ // There is currently nothing that enforces that the write to inputFuture in the constructor is
+ // visible to done(). This is because there is no happens before edge between the write and a
+ // (hypothetical) unsafe read by our caller. Note: adding 'volatile' does not fix this issue,
+ // it would just add an edge such that if done() observed non-null, then it would also
+ // definitely observe all earlier writes, but we still have no guarantee that done() would see
+ // the inital write (just stronger guarantees if it does).
+ //
+ // See: http://cs.oswego.edu/pipermail/concurrency-interest/2015-January/013800.html
+ // For a (long) discussion about this specific issue and the general futility of life.
+ //
+ // For the time being we are OK with the problem discussed above since it requires a caller to
+ // introduce a very specific kind of data-race. And given the other operations performed by these
+ // methods that involve volatile read/write operations, in practice there is no issue. Also, the
+ // way in such a visibility issue would surface is most likely as a failure of cancel() to
+ // propagate to the input. Cancellation propagation is fundamentally racy so this is fine.
+ //
+ // Future versions of the JMM may revise safe construction semantics in such a way that we can
+ // safely publish these objects and we won't need this whole discussion.
+ // TODO(user,lukes): consider adding volatile to all these fields since in current known JVMs
+ // that should resolve the issue. This comes at the cost of adding more write barriers to the
+ // implementations.
+
+ private Futures() {}
+
+ private abstract static class ImmediateFuture<V>
+ implements ListenableFuture<V> {
+
+ private static final Logger log =
+ Logger.getLogger(ImmediateFuture.class.getName());
+
+ @Override
+ public void addListener(Runnable listener, Executor executor) {
+ checkNotNull(listener, "Runnable was null.");
+ checkNotNull(executor, "Executor was null.");
+ try {
+ executor.execute(listener);
+ } catch (RuntimeException e) {
+ // ListenableFuture's contract is that it will not throw unchecked
+ // exceptions, so log the bad runnable and/or executor and swallow it.
+ log.log(Level.SEVERE, "RuntimeException while executing runnable "
+ + listener + " with executor " + executor, e);
+ }
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return false;
+ }
+
+ @Override
+ public abstract V get() throws ExecutionException;
+
+ @Override
+ public V get(long timeout, TimeUnit unit) throws ExecutionException {
+ checkNotNull(unit);
+ return get();
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+
+ @Override
+ public boolean isDone() {
+ return true;
+ }
+ }
+
+ private static class ImmediateSuccessfulFuture<V> extends ImmediateFuture<V> {
+ static final ImmediateSuccessfulFuture<Object> NULL =
+ new ImmediateSuccessfulFuture<Object>(null);
+
+ @Nullable private final V value;
+
+ ImmediateSuccessfulFuture(@Nullable V value) {
+ this.value = value;
+ }
+
+ @Override
+ public V get() {
+ return value;
+ }
+ }
+
+ private static class ImmediateFailedFuture<V> extends ImmediateFuture<V> {
+
+ private final Throwable thrown;
+
+ ImmediateFailedFuture(Throwable thrown) {
+ this.thrown = thrown;
+ }
+
+ @Override
+ public V get() throws ExecutionException {
+ throw new ExecutionException(thrown);
+ }
+ }
+
+ /**
+ * Creates a {@code ListenableFuture} which has its value set immediately upon
+ * construction. The getters just return the value. This {@code Future} can't
+ * be canceled or timed out and its {@code isDone()} method always returns
+ * {@code true}.
+ */
+ @CheckReturnValue
+ public static <V> ListenableFuture<V> immediateFuture(@Nullable V value) {
+ if (value == null) {
+ // This cast is safe because null is assignable to V for all V (i.e. it is covariant)
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ ListenableFuture<V> typedNull = (ListenableFuture) ImmediateSuccessfulFuture.NULL;
+ return typedNull;
+ }
+ return new ImmediateSuccessfulFuture<V>(value);
+ }
+
+ /**
+ * Returns a {@code ListenableFuture} which has an exception set immediately
+ * upon construction.
+ *
+ * <p>The returned {@code Future} can't be cancelled, and its {@code isDone()}
+ * method always returns {@code true}. Calling {@code get()} will immediately
+ * throw the provided {@code Throwable} wrapped in an {@code
+ * ExecutionException}.
+ */
+ @CheckReturnValue
+ public static <V> ListenableFuture<V> immediateFailedFuture(
+ Throwable throwable) {
+ checkNotNull(throwable);
+ return new ImmediateFailedFuture<V>(throwable);
+ }
+
+ /**
+ * Returns a {@code Future} whose result is taken from the given primary
+ * {@code input} or, if the primary input fails, from the {@code Future}
+ * provided by the {@code fallback}. {@link FutureFallback#create} is not
+ * invoked until the primary input has failed, so if the primary input
+ * succeeds, it is never invoked. If, during the invocation of {@code
+ * fallback}, an exception is thrown, this exception is used as the result of
+ * the output {@code Future}.
+ *
+ * <p>Below is an example of a fallback that returns a default value if an
+ * exception occurs:
+ *
+ * <pre> {@code
+ * ListenableFuture<Integer> fetchCounterFuture = ...;
+ *
+ * // Falling back to a zero counter in case an exception happens when
+ * // processing the RPC to fetch counters.
+ * ListenableFuture<Integer> faultTolerantFuture = Futures.withFallback(
+ * fetchCounterFuture, new FutureFallback<Integer>() {
+ * public ListenableFuture<Integer> create(Throwable t) {
+ * // Returning "0" as the default for the counter when the
+ * // exception happens.
+ * return immediateFuture(0);
+ * }
+ * });}</pre>
+ *
+ * <p>The fallback can also choose to propagate the original exception when
+ * desired:
+ *
+ * <pre> {@code
+ * ListenableFuture<Integer> fetchCounterFuture = ...;
+ *
+ * // Falling back to a zero counter only in case the exception was a
+ * // TimeoutException.
+ * ListenableFuture<Integer> faultTolerantFuture = Futures.withFallback(
+ * fetchCounterFuture, new FutureFallback<Integer>() {
+ * public ListenableFuture<Integer> create(Throwable t) {
+ * if (t instanceof TimeoutException) {
+ * return immediateFuture(0);
+ * }
+ * return immediateFailedFuture(t);
+ * }
+ * });}</pre>
+ *
+ * <p>This overload, which does not accept an executor, uses {@code
+ * directExecutor}, a dangerous choice in some cases. See the discussion in
+ * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation. The documentation's warnings about "lightweight listeners"
+ * refer here to the work done during {@code FutureFallback.create}, not to
+ * any work done to complete the returned {@code Future}.
+ *
+ * @param input the primary input {@code Future}
+ * @param fallback the {@link FutureFallback} implementation to be called if
+ * {@code input} fails
+ * @since 14.0
+ * @deprecated Use {@link #catchingAsync(ListenableFuture, Class,
+ * AsyncFunction) catchingAsync(input, Throwable.class,
+ * fallbackImplementedAsAnAsyncFunction)}, usually replacing {@code
+ * Throwable.class} with the specific type you want to handle. This method
+ * will be removed in Guava release 20.0.
+ */
+ @Deprecated
+ @CheckReturnValue
+ public static <V> ListenableFuture<V> withFallback(
+ ListenableFuture<? extends V> input,
+ FutureFallback<? extends V> fallback) {
+ return withFallback(input, fallback, directExecutor());
+ }
+
+ /**
+ * Returns a {@code Future} whose result is taken from the given primary
+ * {@code input} or, if the primary input fails, from the {@code Future}
+ * provided by the {@code fallback}. {@link FutureFallback#create} is not
+ * invoked until the primary input has failed, so if the primary input
+ * succeeds, it is never invoked. If, during the invocation of {@code
+ * fallback}, an exception is thrown, this exception is used as the result of
+ * the output {@code Future}.
+ *
+ * <p>Below is an example of a fallback that returns a default value if an
+ * exception occurs:
+ *
+ * <pre> {@code
+ * ListenableFuture<Integer> fetchCounterFuture = ...;
+ *
+ * // Falling back to a zero counter in case an exception happens when
+ * // processing the RPC to fetch counters.
+ * ListenableFuture<Integer> faultTolerantFuture = Futures.withFallback(
+ * fetchCounterFuture, new FutureFallback<Integer>() {
+ * public ListenableFuture<Integer> create(Throwable t) {
+ * // Returning "0" as the default for the counter when the
+ * // exception happens.
+ * return immediateFuture(0);
+ * }
+ * }, directExecutor());}</pre>
+ *
+ * <p>The fallback can also choose to propagate the original exception when
+ * desired:
+ *
+ * <pre> {@code
+ * ListenableFuture<Integer> fetchCounterFuture = ...;
+ *
+ * // Falling back to a zero counter only in case the exception was a
+ * // TimeoutException.
+ * ListenableFuture<Integer> faultTolerantFuture = Futures.withFallback(
+ * fetchCounterFuture, new FutureFallback<Integer>() {
+ * public ListenableFuture<Integer> create(Throwable t) {
+ * if (t instanceof TimeoutException) {
+ * return immediateFuture(0);
+ * }
+ * return immediateFailedFuture(t);
+ * }
+ * }, directExecutor());}</pre>
+ *
+ * <p>When selecting an executor, note that {@code directExecutor} is
+ * dangerous in some cases. See the discussion in the {@link
+ * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+ * The documentation's warnings about "lightweight listeners" refer here to
+ * the work done during {@code FutureFallback.create}, not to any work done to
+ * complete the returned {@code Future}.
+ *
+ * @param input the primary input {@code Future}
+ * @param fallback the {@link FutureFallback} implementation to be called if
+ * {@code input} fails
+ * @param executor the executor that runs {@code fallback} if {@code input}
+ * fails
+ * @since 14.0
+ * @deprecated Use {@link #catchingAsync(ListenableFuture, Class,
+ * AsyncFunction, Executor) catchingAsync(input, Throwable.class,
+ * fallbackImplementedAsAnAsyncFunction, executor)}, usually replacing
+ * {@code Throwable.class} with the specific type you want to handle. This method
+ * will be removed in Guava release 20.0.
+ */
+ @Deprecated
+ @CheckReturnValue
+ public static <V> ListenableFuture<V> withFallback(
+ ListenableFuture<? extends V> input,
+ FutureFallback<? extends V> fallback, Executor executor) {
+ return catchingAsync(
+ input, Throwable.class, asAsyncFunction(fallback), executor);
+ }
+
+ @Deprecated
+ static <V> AsyncFunction<Throwable, V> asAsyncFunction(final FutureFallback<V> fallback) {
+ checkNotNull(fallback);
+ return new AsyncFunction<Throwable, V>() {
+ @Override
+ public ListenableFuture<V> apply(Throwable t) throws Exception {
+ return checkNotNull(fallback.create(t), "FutureFallback.create returned null instead of a "
+ + "Future. Did you mean to return immediateFuture(null)?");
+ }
+ };
+ }
+
+ private abstract static class AbstractCatchingFuture<V, X extends Throwable, F>
+ extends AbstractFuture.TrustedFuture<V> implements Runnable {
+ @Nullable ListenableFuture<? extends V> inputFuture;
+ @Nullable Class<X> exceptionType;
+ @Nullable F fallback;
+
+ AbstractCatchingFuture(
+ ListenableFuture<? extends V> inputFuture, Class<X> exceptionType, F fallback) {
+ this.inputFuture = checkNotNull(inputFuture);
+ this.exceptionType = checkNotNull(exceptionType);
+ this.fallback = checkNotNull(fallback);
+ }
+
+ @Override public final void run() {
+ ListenableFuture<? extends V> localInputFuture = inputFuture;
+ Class<X> localExceptionType = exceptionType;
+ F localFallback = fallback;
+ if (localInputFuture == null | localExceptionType == null | localFallback == null
+ | isCancelled()) {
+ return;
+ }
+ inputFuture = null;
+ exceptionType = null;
+ fallback = null;
+
+ Throwable throwable;
+ try {
+ set(getUninterruptibly(localInputFuture));
+ return;
+ } catch (ExecutionException e) {
+ throwable = e.getCause();
+ } catch (Throwable e) { // this includes cancellation exception
+ throwable = e;
+ }
+ try {
+ if (isInstanceOfThrowableClass(throwable, localExceptionType)) {
+ @SuppressWarnings("unchecked") // verified safe by isInstance
+ X castThrowable = (X) throwable;
+ doFallback(localFallback, castThrowable);
+ } else {
+ setException(throwable);
+ }
+ } catch (Throwable e) {
+ setException(e);
+ }
+ }
+
+ /** Template method for subtypes to actually run the fallback. */
+ abstract void doFallback(F fallback, X throwable) throws Exception;
+
+ @Override final void done() {
+ maybePropagateCancellation(inputFuture);
+ this.inputFuture = null;
+ this.exceptionType = null;
+ this.fallback = null;
+ }
+ }
+
+ /**
+ * A {@link AbstractCatchingFuture} that delegates to an {@link AsyncFunction}
+ * and {@link #setFuture(ListenableFuture)} to implement {@link #doFallback}
+ */
+ static final class AsyncCatchingFuture<V, X extends Throwable>
+ extends AbstractCatchingFuture<V, X, AsyncFunction<? super X, ? extends V>> {
+
+ AsyncCatchingFuture(ListenableFuture<? extends V> input, Class<X> exceptionType,
+ AsyncFunction<? super X, ? extends V> fallback) {
+ super(input, exceptionType, fallback);
+ }
+
+ @Override void doFallback(
+ AsyncFunction<? super X, ? extends V> fallback, X cause) throws Exception {
+ ListenableFuture<? extends V> replacement = fallback.apply(cause);
+ checkNotNull(replacement, "AsyncFunction.apply returned null instead of a Future. "
+ + "Did you mean to return immediateFuture(null)?");
+ setFuture(replacement);
+ }
+ }
+
+ /**
+ * A {@link AbstractCatchingFuture} that delegates to a {@link Function}
+ * and {@link #set(Object)} to implement {@link #doFallback}
+ */
+ static final class CatchingFuture<V, X extends Throwable>
+ extends AbstractCatchingFuture<V, X, Function<? super X, ? extends V>> {
+ CatchingFuture(ListenableFuture<? extends V> input, Class<X> exceptionType,
+ Function<? super X, ? extends V> fallback) {
+ super(input, exceptionType, fallback);
+ }
+
+ @Override void doFallback(Function<? super X, ? extends V> fallback, X cause) throws Exception {
+ V replacement = fallback.apply(cause);
+ set(replacement);
+ }
+ }
+
+ /**
+ * Future that delegates to another but will finish early (via a {@link
+ * TimeoutException} wrapped in an {@link ExecutionException}) if the
+ * specified duration expires.
+ * The delegate future is interrupted and cancelled if it times out.
+ */
+ private static final class TimeoutFuture<V> extends AbstractFuture.TrustedFuture<V> {
+ // Memory visibility of these fields.
+ // There are two cases to consider.
+ // 1. visibility of the writes to these fields to Fire.run
+ // The initial write to delegateRef is made definitely visible via the semantics of
+ // addListener/SES.schedule. The later racy write in cancel() is not guaranteed to be
+ // observed, however that is fine since the correctness is based on the atomic state in
+ // our base class.
+ // The initial write to timer is never definitely visible to Fire.run since it is assigned
+ // after SES.schedule is called. Therefore Fire.run has to check for null. However, it
+ // should be visible if Fire.run is called by delegate.addListener since addListener is
+ // called after the assignment to timer, and importantly this is the main situation in which
+ // we need to be able to see the write.
+ // 2. visibility of the writes to cancel
+ // Since these fields are non-final that means that TimeoutFuture is not being 'safely
+ // published', thus a motivated caller may be able to expose the reference to another thread
+ // that would then call cancel() and be unable to cancel the delegate.
+ // There are a number of ways to solve this, none of which are very pretty, and it is
+ // currently believed to be a purely theoretical problem (since the other actions should
+ // supply sufficient write-barriers).
+
+ @Nullable ListenableFuture<V> delegateRef;
+ @Nullable Future<?> timer;
+
+ TimeoutFuture(ListenableFuture<V> delegate) {
+ this.delegateRef = Preconditions.checkNotNull(delegate);
+ }
+
+ /** A runnable that is called when the delegate or the timer completes. */
+ private static final class Fire<V> implements Runnable {
+ @Nullable TimeoutFuture<V> timeoutFutureRef;
+
+ Fire(TimeoutFuture<V> timeoutFuture) {
+ this.timeoutFutureRef = timeoutFuture;
+ }
+
+ @Override public void run() {
+ // If either of these reads return null then we must be after a successful cancel
+ // or another call to this method.
+ TimeoutFuture<V> timeoutFuture = timeoutFutureRef;
+ if (timeoutFuture == null) {
+ return;
+ }
+ ListenableFuture<V> delegate = timeoutFuture.delegateRef;
+ if (delegate == null) {
+ return;
+ }
+
+ /*
+ * If we're about to complete the TimeoutFuture, we want to release our reference to it.
+ * Otherwise, we'll pin it (and its result) in memory until the timeout task is GCed. (The
+ * need to clear our reference to the TimeoutFuture is the reason we use a *static* nested
+ * class with a manual reference back to the "containing" class.)
+ *
+ * This has the nice-ish side effect of limiting reentrancy: run() calls
+ * timeoutFuture.setException() calls run(). That reentrancy would already be harmless,
+ * since timeoutFuture can be set (and delegate cancelled) only once. (And "set only once"
+ * is important for other reasons: run() can still be invoked concurrently in different
+ * threads, even with the above null checks.)
+ */
+ timeoutFutureRef = null;
+ if (delegate.isDone()) {
+ timeoutFuture.setFuture(delegate);
+ } else {
+ try {
+ // TODO(lukes): this stack trace is particularly useless (all it does is point at the
+ // scheduledexecutorservice thread), consider eliminating it altogether?
+ timeoutFuture.setException(new TimeoutException("Future timed out: " + delegate));
+ } finally {
+ delegate.cancel(true);
+ }
+ }
+ }
+ }
+
+ @Override void done() {
+ maybePropagateCancellation(delegateRef);
+
+ Future<?> localTimer = timer;
+ // Try to cancel the timer as an optimization
+ // timer may be null if this call to run was by the timer task since there is no
+ // happens-before edge between the assignment to timer and an execution of the timer task.
+ if (localTimer != null) {
+ localTimer.cancel(false);
+ }
+
+ delegateRef = null;
+ timer = null;
+ }
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is asynchronously
+ * derived from the result of the given {@code Future}. More precisely, the
+ * returned {@code Future} takes its result from a {@code Future} produced by
+ * applying the given {@code AsyncFunction} to the result of the original
+ * {@code Future}. Example:
+ *
+ * <pre> {@code
+ * ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+ * AsyncFunction<RowKey, QueryResult> queryFunction =
+ * new AsyncFunction<RowKey, QueryResult>() {
+ * public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+ * return dataService.read(rowKey);
+ * }
+ * };
+ * ListenableFuture<QueryResult> queryFuture =
+ * transform(rowKeyFuture, queryFunction);}</pre>
+ *
+ * <p>This overload, which does not accept an executor, uses {@code
+ * directExecutor}, a dangerous choice in some cases. See the discussion in
+ * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation. The documentation's warnings about "lightweight listeners"
+ * refer here to the work done during {@code AsyncFunction.apply}, not to any
+ * work done to complete the returned {@code Future}.
+ *
+ * <p>The returned {@code Future} attempts to keep its cancellation state in
+ * sync with that of the input future and that of the future returned by the
+ * function. That is, if the returned {@code Future} is cancelled, it will
+ * attempt to cancel the other two, and if either of the other two is
+ * cancelled, the returned {@code Future} will receive a callback in which it
+ * will attempt to cancel itself.
+ *
+ * @param input The future to transform
+ * @param function A function to transform the result of the input future
+ * to the result of the output future
+ * @return A future that holds result of the function (if the input succeeded)
+ * or the original input's failure (if not)
+ * @since 11.0
+ * @deprecated These {@code AsyncFunction} overloads of {@code transform} are
+ * being renamed to {@code transformAsync}. (The {@code Function}
+ * overloads are keeping the "transform" name.) This method will be removed in Guava release
+ * 20.0.
+ */
+ @Deprecated
+ public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
+ AsyncFunction<? super I, ? extends O> function) {
+ return transformAsync(input, function);
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is asynchronously
+ * derived from the result of the given {@code Future}. More precisely, the
+ * returned {@code Future} takes its result from a {@code Future} produced by
+ * applying the given {@code AsyncFunction} to the result of the original
+ * {@code Future}. Example:
+ *
+ * <pre> {@code
+ * ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+ * AsyncFunction<RowKey, QueryResult> queryFunction =
+ * new AsyncFunction<RowKey, QueryResult>() {
+ * public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+ * return dataService.read(rowKey);
+ * }
+ * };
+ * ListenableFuture<QueryResult> queryFuture =
+ * transform(rowKeyFuture, queryFunction, executor);}</pre>
+ *
+ * <p>When selecting an executor, note that {@code directExecutor} is
+ * dangerous in some cases. See the discussion in the {@link
+ * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+ * The documentation's warnings about "lightweight listeners" refer here to
+ * the work done during {@code AsyncFunction.apply}, not to any work done to
+ * complete the returned {@code Future}.
+ *
+ * <p>The returned {@code Future} attempts to keep its cancellation state in
+ * sync with that of the input future and that of the future returned by the
+ * chain function. That is, if the returned {@code Future} is cancelled, it
+ * will attempt to cancel the other two, and if either of the other two is
+ * cancelled, the returned {@code Future} will receive a callback in which it
+ * will attempt to cancel itself.
+ *
+ * @param input The future to transform
+ * @param function A function to transform the result of the input future
+ * to the result of the output future
+ * @param executor Executor to run the function in.
+ * @return A future that holds result of the function (if the input succeeded)
+ * or the original input's failure (if not)
+ * @since 11.0
+ * @deprecated These {@code AsyncFunction} overloads of {@code transform} are
+ * being renamed to {@code transformAsync}. (The {@code Function}
+ * overloads are keeping the "transform" name.) This method will be removed in Guava release
+ * 20.0.
+ */
+ @Deprecated
+ public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
+ AsyncFunction<? super I, ? extends O> function,
+ Executor executor) {
+ return transformAsync(input, function, executor);
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is asynchronously derived from the result
+ * of the given {@code Future}. More precisely, the returned {@code Future} takes its result from
+ * a {@code Future} produced by applying the given {@code AsyncFunction} to the result of the
+ * original {@code Future}. Example:
+ *
+ * <pre> {@code
+ * ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+ * AsyncFunction<RowKey, QueryResult> queryFunction =
+ * new AsyncFunction<RowKey, QueryResult>() {
+ * public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+ * return dataService.read(rowKey);
+ * }
+ * };
+ * ListenableFuture<QueryResult> queryFuture =
+ * transformAsync(rowKeyFuture, queryFunction);}</pre>
+ *
+ * <p>This overload, which does not accept an executor, uses {@code directExecutor}, a dangerous
+ * choice in some cases. See the discussion in the {@link ListenableFuture#addListener
+ * ListenableFuture.addListener} documentation. The documentation's warnings about "lightweight
+ * listeners" refer here to the work done during {@code AsyncFunction.apply}, not to any work done
+ * to complete the returned {@code Future}.
+ *
+ * <p>The returned {@code Future} attempts to keep its cancellation state in sync with that of the
+ * input future and that of the future returned by the function. That is, if the returned {@code
+ * Future} is cancelled, it will attempt to cancel the other two, and if either of the other two
+ * is cancelled, the returned {@code Future} will receive a callback in which it will attempt to
+ * cancel itself.
+ *
+ * @param input The future to transform
+ * @param function A function to transform the result of the input future to the result of the
+ * output future
+ * @return A future that holds result of the function (if the input succeeded) or the original
+ * input's failure (if not)
+ * @since 19.0 (in 11.0 as {@code transform})
+ */
+ public static <I, O> ListenableFuture<O> transformAsync(
+ ListenableFuture<I> input, AsyncFunction<? super I, ? extends O> function) {
+ AsyncChainingFuture<I, O> output = new AsyncChainingFuture<I, O>(input, function);
+ input.addListener(output, directExecutor());
+ return output;
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is asynchronously derived from the result
+ * of the given {@code Future}. More precisely, the returned {@code Future} takes its result from
+ * a {@code Future} produced by applying the given {@code AsyncFunction} to the result of the
+ * original {@code Future}. Example:
+ *
+ * <pre> {@code
+ * ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+ * AsyncFunction<RowKey, QueryResult> queryFunction =
+ * new AsyncFunction<RowKey, QueryResult>() {
+ * public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+ * return dataService.read(rowKey);
+ * }
+ * };
+ * ListenableFuture<QueryResult> queryFuture =
+ * transformAsync(rowKeyFuture, queryFunction, executor);}</pre>
+ *
+ * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
+ * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation. The documentation's warnings about "lightweight listeners" refer here to the
+ * work done during {@code AsyncFunction.apply}, not to any work done to complete the returned
+ * {@code Future}.
+ *
+ * <p>The returned {@code Future} attempts to keep its cancellation state in sync with that of the
+ * input future and that of the future returned by the chain function. That is, if the returned
+ * {@code Future} is cancelled, it will attempt to cancel the other two, and if either of the
+ * other two is cancelled, the returned {@code Future} will receive a callback in which it will
+ * attempt to cancel itself.
+ *
+ * @param input The future to transform
+ * @param function A function to transform the result of the input future to the result of the
+ * output future
+ * @param executor Executor to run the function in.
+ * @return A future that holds result of the function (if the input succeeded) or the original
+ * input's failure (if not)
+ * @since 19.0 (in 11.0 as {@code transform})
+ */
+ public static <I, O> ListenableFuture<O> transformAsync(ListenableFuture<I> input,
+ AsyncFunction<? super I, ? extends O> function, Executor executor) {
+ checkNotNull(executor);
+ AsyncChainingFuture<I, O> output = new AsyncChainingFuture<I, O>(input, function);
+ input.addListener(output, rejectionPropagatingExecutor(executor, output));
+ return output;
+ }
+
+ /**
+ * Returns an Executor that will propagate {@link RejectedExecutionException} from the delegate
+ * executor to the given {@code future}.
+ *
+ * <p>Note, the returned executor can only be used once.
+ */
+ private static Executor rejectionPropagatingExecutor(
+ final Executor delegate, final AbstractFuture<?> future) {
+ checkNotNull(delegate);
+ if (delegate == directExecutor()) {
+ // directExecutor() cannot throw RejectedExecutionException
+ return delegate;
+ }
+ return new Executor() {
+ volatile boolean thrownFromDelegate = true;
+ @Override public void execute(final Runnable command) {
+ try {
+ delegate.execute(new Runnable() {
+ @Override public void run() {
+ thrownFromDelegate = false;
+ command.run();
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ if (thrownFromDelegate) {
+ // wrap exception?
+ future.setException(e);
+ }
+ // otherwise it must have been thrown from a transitive call and the delegate runnable
+ // should have handled it.
+ }
+ }
+ };
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is the product of
+ * applying the given {@code Function} to the result of the given {@code
+ * Future}. Example:
+ *
+ * <pre> {@code
+ * ListenableFuture<QueryResult> queryFuture = ...;
+ * Function<QueryResult, List<Row>> rowsFunction =
+ * new Function<QueryResult, List<Row>>() {
+ * public List<Row> apply(QueryResult queryResult) {
+ * return queryResult.getRows();
+ * }
+ * };
+ * ListenableFuture<List<Row>> rowsFuture =
+ * transform(queryFuture, rowsFunction);}</pre>
+ *
+ * <p>This overload, which does not accept an executor, uses {@code
+ * directExecutor}, a dangerous choice in some cases. See the discussion in
+ * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation. The documentation's warnings about "lightweight listeners"
+ * refer here to the work done during {@code Function.apply}.
+ *
+ * <p>The returned {@code Future} attempts to keep its cancellation state in
+ * sync with that of the input future. That is, if the returned {@code Future}
+ * is cancelled, it will attempt to cancel the input, and if the input is
+ * cancelled, the returned {@code Future} will receive a callback in which it
+ * will attempt to cancel itself.
+ *
+ * <p>An example use of this method is to convert a serializable object
+ * returned from an RPC into a POJO.
+ *
+ * @param input The future to transform
+ * @param function A Function to transform the results of the provided future
+ * to the results of the returned future. This will be run in the thread
+ * that notifies input it is complete.
+ * @return A future that holds result of the transformation.
+ * @since 9.0 (in 1.0 as {@code compose})
+ */
+ public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
+ final Function<? super I, ? extends O> function) {
+ checkNotNull(function);
+ ChainingFuture<I, O> output = new ChainingFuture<I, O>(input, function);
+ input.addListener(output, directExecutor());
+ return output;
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is the product of
+ * applying the given {@code Function} to the result of the given {@code
+ * Future}. Example:
+ *
+ * <pre> {@code
+ * ListenableFuture<QueryResult> queryFuture = ...;
+ * Function<QueryResult, List<Row>> rowsFunction =
+ * new Function<QueryResult, List<Row>>() {
+ * public List<Row> apply(QueryResult queryResult) {
+ * return queryResult.getRows();
+ * }
+ * };
+ * ListenableFuture<List<Row>> rowsFuture =
+ * transform(queryFuture, rowsFunction, executor);}</pre>
+ *
+ * <p>When selecting an executor, note that {@code directExecutor} is
+ * dangerous in some cases. See the discussion in the {@link
+ * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+ * The documentation's warnings about "lightweight listeners" refer here to
+ * the work done during {@code Function.apply}.
+ *
+ * <p>The returned {@code Future} attempts to keep its cancellation state in
+ * sync with that of the input future. That is, if the returned {@code Future}
+ * is cancelled, it will attempt to cancel the input, and if the input is
+ * cancelled, the returned {@code Future} will receive a callback in which it
+ * will attempt to cancel itself.
+ *
+ * <p>An example use of this method is to convert a serializable object
+ * returned from an RPC into a POJO.
+ *
+ * @param input The future to transform
+ * @param function A Function to transform the results of the provided future
+ * to the results of the returned future.
+ * @param executor Executor to run the function in.
+ * @return A future that holds result of the transformation.
+ * @since 9.0 (in 2.0 as {@code compose})
+ */
+ public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
+ final Function<? super I, ? extends O> function, Executor executor) {
+ checkNotNull(function);
+ ChainingFuture<I, O> output = new ChainingFuture<I, O>(input, function);
+ input.addListener(output, rejectionPropagatingExecutor(executor, output));
+ return output;
+ }
+
+ /**
+ * An implementation of {@code ListenableFuture} that also implements
+ * {@code Runnable} so that it can be used to nest ListenableFutures.
+ * Once the passed-in {@code ListenableFuture} is complete, it calls the
+ * passed-in {@code Function} to generate the result.
+ *
+ * <p>For historical reasons, this class has a special case in its exception
+ * handling: If the given {@code AsyncFunction} throws an {@code
+ * UndeclaredThrowableException}, {@code ChainingListenableFuture} unwraps it
+ * and uses its <i>cause</i> as the output future's exception, rather than
+ * using the {@code UndeclaredThrowableException} itself as it would for other
+ * exception types. The reason for this is that {@code Futures.transform} used
+ * to require a {@code Function}, whose {@code apply} method is not allowed to
+ * throw checked exceptions. Nowadays, {@code Futures.transform} has an
+ * overload that accepts an {@code AsyncFunction}, whose {@code apply} method
+ * <i>is</i> allowed to throw checked exception. Users who wish to throw
+ * checked exceptions should use that overload instead, and <a
+ * href="http://code.google.com/p/guava-libraries/issues/detail?id=1548">we
+ * should remove the {@code UndeclaredThrowableException} special case</a>.
+ */
+ private abstract static class AbstractChainingFuture<I, O, F>
+ extends AbstractFuture.TrustedFuture<O> implements Runnable {
+ // In theory, this field might not be visible to a cancel() call in certain circumstances. For
+ // details, see the comments on the fields of TimeoutFuture.
+ @Nullable ListenableFuture<? extends I> inputFuture;
+ @Nullable F function;
+
+ AbstractChainingFuture(ListenableFuture<? extends I> inputFuture, F function) {
+ this.inputFuture = checkNotNull(inputFuture);
+ this.function = checkNotNull(function);
+ }
+
+ @Override
+ public final void run() {
+ try {
+ ListenableFuture<? extends I> localInputFuture = inputFuture;
+ F localFunction = function;
+ if (isCancelled() | localInputFuture == null | localFunction == null) {
+ return;
+ }
+ inputFuture = null;
+ function = null;
+
+ I sourceResult;
+ try {
+ sourceResult = getUninterruptibly(localInputFuture);
+ } catch (CancellationException e) {
+ // Cancel this future and return.
+ // At this point, inputFuture is cancelled and outputFuture doesn't
+ // exist, so the value of mayInterruptIfRunning is irrelevant.
+ cancel(false);
+ return;
+ } catch (ExecutionException e) {
+ // Set the cause of the exception as this future's exception
+ setException(e.getCause());
+ return;
+ }
+ doTransform(localFunction, sourceResult);
+ } catch (UndeclaredThrowableException e) {
+ // Set the cause of the exception as this future's exception
+ setException(e.getCause());
+ } catch (Throwable t) {
+ // This exception is irrelevant in this thread, but useful for the
+ // client
+ setException(t);
+ }
+ }
+
+ /** Template method for subtypes to actually run the transform. */
+ abstract void doTransform(F function, I result) throws Exception;
+
+ @Override final void done() {
+ maybePropagateCancellation(inputFuture);
+ this.inputFuture = null;
+ this.function = null;
+ }
+ }
+
+ /**
+ * A {@link AbstractChainingFuture} that delegates to an {@link AsyncFunction} and
+ * {@link #setFuture(ListenableFuture)} to implement {@link #doTransform}.
+ */
+ private static final class AsyncChainingFuture<I, O>
+ extends AbstractChainingFuture<I, O, AsyncFunction<? super I, ? extends O>> {
+ AsyncChainingFuture(ListenableFuture<? extends I> inputFuture,
+ AsyncFunction<? super I, ? extends O> function) {
+ super(inputFuture, function);
+ }
+
+ @Override
+ void doTransform(AsyncFunction<? super I, ? extends O> function, I input) throws Exception {
+ ListenableFuture<? extends O> outputFuture = function.apply(input);
+ checkNotNull(outputFuture, "AsyncFunction.apply returned null instead of a Future. "
+ + "Did you mean to return immediateFuture(null)?");
+ setFuture(outputFuture);
+ }
+ }
+
+ /**
+ * A {@link AbstractChainingFuture} that delegates to a {@link Function} and
+ * {@link #set(Object)} to implement {@link #doTransform}.
+ */
+ private static final class ChainingFuture<I, O>
+ extends AbstractChainingFuture<I, O, Function<? super I, ? extends O>> {
+
+ ChainingFuture(ListenableFuture<? extends I> inputFuture,
+ Function<? super I, ? extends O> function) {
+ super(inputFuture, function);
+ }
+
+ @Override
+ void doTransform(Function<? super I, ? extends O> function, I input) {
+ // TODO(lukes): move the UndeclaredThrowable catch block here?
+ set(function.apply(input));
+ }
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is the product of
+ * calling {@code get()} on the {@code Future} nested within the given {@code
+ * Future}, effectively chaining the futures one after the other. Example:
+ *
+ * <pre> {@code
+ * SettableFuture<ListenableFuture<String>> nested = SettableFuture.create();
+ * ListenableFuture<String> dereferenced = dereference(nested);}</pre>
+ *
+ * <p>This call has the same cancellation and execution semantics as {@link
+ * #transform(ListenableFuture, AsyncFunction)}, in that the returned {@code
+ * Future} attempts to keep its cancellation state in sync with both the
+ * input {@code Future} and the nested {@code Future}. The transformation
+ * is very lightweight and therefore takes place in the same thread (either
+ * the thread that called {@code dereference}, or the thread in which the
+ * dereferenced future completes).
+ *
+ * @param nested The nested future to transform.
+ * @return A future that holds result of the inner future.
+ * @since 13.0
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ @CheckReturnValue
+ public static <V> ListenableFuture<V> dereference(
+ ListenableFuture<? extends ListenableFuture<? extends V>> nested) {
+ return transformAsync((ListenableFuture) nested, (AsyncFunction) DEREFERENCER);
+ }
+
+ /**
+ * Helper {@code Function} for {@link #dereference}.
+ */
+ private static final AsyncFunction<ListenableFuture<Object>, Object> DEREFERENCER =
+ new AsyncFunction<ListenableFuture<Object>, Object>() {
+ @Override public ListenableFuture<Object> apply(ListenableFuture<Object> input) {
+ return input;
+ }
+ };
+
+ /**
+ * Creates a new {@code ListenableFuture} whose value is a list containing the
+ * values of all its input futures, if all succeed. If any input fails, the
+ * returned future fails immediately.
+ *
+ * <p>The list of results is in the same order as the input list.
+ *
+ * <p>Canceling this future will attempt to cancel all the component futures,
+ * and if any of the provided futures fails or is canceled, this one is,
+ * too.
+ *
+ * @param futures futures to combine
+ * @return a future that provides a list of the results of the component
+ * futures
+ * @since 10.0
+ */
+ @Beta
+ @SafeVarargs
+ @CheckReturnValue
+ public static <V> ListenableFuture<List<V>> allAsList(
+ ListenableFuture<? extends V>... futures) {
+ return new ListFuture<V>(ImmutableList.copyOf(futures), true);
+ }
+
+ /**
+ * Creates a new {@code ListenableFuture} whose value is a list containing the
+ * values of all its input futures, if all succeed. If any input fails, the
+ * returned future fails immediately.
+ *
+ * <p>The list of results is in the same order as the input list.
+ *
+ * <p>Canceling this future will attempt to cancel all the component futures,
+ * and if any of the provided futures fails or is canceled, this one is,
+ * too.
+ *
+ * @param futures futures to combine
+ * @return a future that provides a list of the results of the component
+ * futures
+ * @since 10.0
+ */
+ @Beta
+ @CheckReturnValue
+ public static <V> ListenableFuture<List<V>> allAsList(
+ Iterable<? extends ListenableFuture<? extends V>> futures) {
+ return new ListFuture<V>(ImmutableList.copyOf(futures), true);
+ }
+
+ /**
+ * Creates a new {@code ListenableFuture} whose value is a list containing the
+ * values of all its successful input futures. The list of results is in the
+ * same order as the input list, and if any of the provided futures fails or
+ * is canceled, its corresponding position will contain {@code null} (which is
+ * indistinguishable from the future having a successful value of
+ * {@code null}).
+ *
+ * <p>Canceling this future will attempt to cancel all the component futures.
+ *
+ * @param futures futures to combine
+ * @return a future that provides a list of the results of the component
+ * futures
+ * @since 10.0
+ */
+ @Beta
+ @SafeVarargs
+ @CheckReturnValue
+ public static <V> ListenableFuture<List<V>> successfulAsList(
+ ListenableFuture<? extends V>... futures) {
+ return new ListFuture<V>(ImmutableList.copyOf(futures), false);
+ }
+
+ /**
+ * Creates a new {@code ListenableFuture} whose value is a list containing the
+ * values of all its successful input futures. The list of results is in the
+ * same order as the input list, and if any of the provided futures fails or
+ * is canceled, its corresponding position will contain {@code null} (which is
+ * indistinguishable from the future having a successful value of
+ * {@code null}).
+ *
+ * <p>Canceling this future will attempt to cancel all the component futures.
+ *
+ * @param futures futures to combine
+ * @return a future that provides a list of the results of the component
+ * futures
+ * @since 10.0
+ */
+ @Beta
+ @CheckReturnValue
+ public static <V> ListenableFuture<List<V>> successfulAsList(
+ Iterable<? extends ListenableFuture<? extends V>> futures) {
+ return new ListFuture<V>(ImmutableList.copyOf(futures), false);
+ }
+
+ /**
+ * Registers separate success and failure callbacks to be run when the {@code
+ * Future}'s computation is {@linkplain java.util.concurrent.Future#isDone()
+ * complete} or, if the computation is already complete, immediately.
+ *
+ * <p>There is no guaranteed ordering of execution of callbacks, but any
+ * callback added through this method is guaranteed to be called once the
+ * computation is complete.
+ *
+ * Example: <pre> {@code
+ * ListenableFuture<QueryResult> future = ...;
+ * addCallback(future,
+ * new FutureCallback<QueryResult> {
+ * public void onSuccess(QueryResult result) {
+ * storeInCache(result);
+ * }
+ * public void onFailure(Throwable t) {
+ * reportError(t);
+ * }
+ * });}</pre>
+ *
+ * <p>This overload, which does not accept an executor, uses {@code
+ * directExecutor}, a dangerous choice in some cases. See the discussion in
+ * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation.
+ *
+ * <p>For a more general interface to attach a completion listener to a
+ * {@code Future}, see {@link ListenableFuture#addListener addListener}.
+ *
+ * @param future The future attach the callback to.
+ * @param callback The callback to invoke when {@code future} is completed.
+ * @since 10.0
+ */
+ public static <V> void addCallback(ListenableFuture<V> future,
+ FutureCallback<? super V> callback) {
+ addCallback(future, callback, directExecutor());
+ }
+
+ /**
+ * Registers separate success and failure callbacks to be run when the {@code
+ * Future}'s computation is {@linkplain java.util.concurrent.Future#isDone()
+ * complete} or, if the computation is already complete, immediately.
+ *
+ * <p>The callback is run in {@code executor}.
+ * There is no guaranteed ordering of execution of callbacks, but any
+ * callback added through this method is guaranteed to be called once the
+ * computation is complete.
+ *
+ * Example: <pre> {@code
+ * ListenableFuture<QueryResult> future = ...;
+ * Executor e = ...
+ * addCallback(future,
+ * new FutureCallback<QueryResult> {
+ * public void onSuccess(QueryResult result) {
+ * storeInCache(result);
+ * }
+ * public void onFailure(Throwable t) {
+ * reportError(t);
+ * }
+ * }, e);}</pre>
+ *
+ * <p>When selecting an executor, note that {@code directExecutor} is
+ * dangerous in some cases. See the discussion in the {@link
+ * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+ *
+ * <p>For a more general interface to attach a completion listener to a
+ * {@code Future}, see {@link ListenableFuture#addListener addListener}.
+ *
+ * @param future The future attach the callback to.
+ * @param callback The callback to invoke when {@code future} is completed.
+ * @param executor The executor to run {@code callback} when the future
+ * completes.
+ * @since 10.0
+ */
+ public static <V> void addCallback(final ListenableFuture<V> future,
+ final FutureCallback<? super V> callback, Executor executor) {
+ Preconditions.checkNotNull(callback);
+ Runnable callbackListener = new Runnable() {
+ @Override
+ public void run() {
+ final V value;
+ try {
+ // TODO(user): (Before Guava release), validate that this
+ // is the thing for IE.
+ value = getUninterruptibly(future);
+ } catch (ExecutionException e) {
+ callback.onFailure(e.getCause());
+ return;
+ } catch (RuntimeException e) {
+ callback.onFailure(e);
+ return;
+ } catch (Error e) {
+ callback.onFailure(e);
+ return;
+ }
+ callback.onSuccess(value);
+ }
+ };
+ future.addListener(callbackListener, executor);
+ }
+
+ /*
+ * Arguably we don't need a timed getUnchecked because any operation slow
+ * enough to require a timeout is heavyweight enough to throw a checked
+ * exception and therefore be inappropriate to use with getUnchecked. Further,
+ * it's not clear that converting the checked TimeoutException to a
+ * RuntimeException -- especially to an UncheckedExecutionException, since it
+ * wasn't thrown by the computation -- makes sense, and if we don't convert
+ * it, the user still has to write a try-catch block.
+ *
+ * If you think you would use this method, let us know. You might also also
+ * look into the Fork-Join framework:
+ * http://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html
+ */
+
+ /** Used for {@link #allAsList} and {@link #successfulAsList}. */
+ private static final class ListFuture<V> extends CollectionFuture<V, List<V>> {
+ ListFuture(ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
+ boolean allMustSucceed) {
+ init(new ListFutureRunningState(futures, allMustSucceed));
+ }
+
+ private final class ListFutureRunningState extends CollectionFutureRunningState {
+ ListFutureRunningState(ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
+ boolean allMustSucceed) {
+ super(futures, allMustSucceed);
+ }
+
+ @Override
+ public List<V> combine(List<Optional<V>> values) {
+ List<V> result = Lists.newArrayList();
+ for (Optional<V> element : values) {
+ result.add(element != null ? element.orNull() : null);
+ }
+ return Collections.unmodifiableList(result);
+ }
+ }
+ }
+}
diff --git a/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/GwtFuturesCatchingSpecialization.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/GwtFuturesCatchingSpecialization.java
new file mode 100644
index 0000000..e156427
--- /dev/null
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/GwtFuturesCatchingSpecialization.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2006 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.Futures.AsyncCatchingFuture;
+import com.google.common.util.concurrent.Futures.CatchingFuture;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Hidden superclass of {@link Futures} that provides us a place to declare special GWT versions of
+ * the {@link Futures#catching(ListenableFuture, Class, com.google.common.base.Function)
+ * Futures.catching} family of methods. Those versions have slightly different signatures.
+ */
+abstract class GwtFuturesCatchingSpecialization {
+ /*
+ * In the GWT versions of the methods (below), every exceptionType parameter is required to be
+ * Class<Throwable>. To handle only certain kinds of exceptions under GWT, you'll need to write
+ * your own instanceof tests.
+ */
+
+ public static <V> ListenableFuture<V> catching(
+ ListenableFuture<? extends V> input,
+ Class<Throwable> exceptionType,
+ Function<? super Throwable, ? extends V> fallback) {
+ return catching(input, exceptionType, fallback, directExecutor());
+ }
+
+ public static <V> ListenableFuture<V> catching(
+ ListenableFuture<? extends V> input,
+ Class<Throwable> exceptionType,
+ Function<? super Throwable, ? extends V> fallback,
+ Executor executor) {
+ CatchingFuture future = new CatchingFuture<V, Throwable>(input, exceptionType, fallback);
+ input.addListener(future, executor);
+ return future;
+ }
+
+ public static <V> ListenableFuture<V> catchingAsync(
+ ListenableFuture<? extends V> input,
+ Class<Throwable> exceptionType,
+ AsyncFunction<? super Throwable, ? extends V> fallback) {
+ return catchingAsync(input, exceptionType, fallback, directExecutor());
+ }
+
+ public static <V> ListenableFuture<V> catchingAsync(
+ ListenableFuture<? extends V> input,
+ Class<Throwable> exceptionType,
+ AsyncFunction<? super Throwable, ? extends V> fallback,
+ Executor executor) {
+ AsyncCatchingFuture<V, Throwable> future =
+ new AsyncCatchingFuture<V, Throwable>(input, exceptionType, fallback);
+ input.addListener(future, executor);
+ return future;
+ }
+}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/InterruptibleTask.java
similarity index 62%
copy from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
copy to guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/InterruptibleTask.java
index ff45a39..d5b4209 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/InterruptibleTask.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,19 @@
* limitations under the License.
*/
-package com.google.common.collect;
-
-import java.util.Comparator;
+package com.google.common.util.concurrent;
/**
- * GWT emulation of {@link EmptyImmutableSortedSet}.
- *
- * @author Hayward Chan
+ * Emulation for InterruptibleTask in GWT.
*/
-class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
- EmptyImmutableSortedSet(Comparator<? super E> comparator) {
- super(Sets.newTreeSet(comparator));
+abstract class InterruptibleTask implements Runnable {
+ @Override public void run() {
+ runInterruptibly();
}
+
+ abstract void runInterruptibly();
+
+ abstract boolean wasInterrupted();
+
+ final void interruptTask() {}
}
diff --git a/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/MoreExecutors.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/MoreExecutors.java
new file mode 100644
index 0000000..3042fff
--- /dev/null
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/MoreExecutors.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Factory and utility methods for {@link java.util.concurrent.Executor}, {@link
+ * ExecutorService}, and {@link ThreadFactory}.
+ *
+ * @author Eric Fellheimer
+ * @author Kyle Littlefield
+ * @author Justin Mahoney
+ * @since 3.0
+ */
+ at GwtCompatible(emulated = true)
+public final class MoreExecutors {
+ private MoreExecutors() {}
+
+ // See sameThreadExecutor javadoc for behavioral notes.
+
+ /**
+ * Returns an {@link Executor} that runs each task in the thread that invokes
+ * {@link Executor#execute execute}, as in {@link CallerRunsPolicy}.
+ *
+ * <p>This instance is equivalent to: <pre> {@code
+ * final class DirectExecutor implements Executor {
+ * public void execute(Runnable r) {
+ * r.run();
+ * }
+ * }}</pre>
+ *
+ * <p>This should be preferred to {@link #newDirectExecutorService()} because the implementing the
+ * {@link ExecutorService} subinterface necessitates significant performance overhead.
+ *
+ * @since 18.0
+ */
+ public static Executor directExecutor() {
+ return DirectExecutor.INSTANCE;
+ }
+
+ /** See {@link #directExecutor} for behavioral notes. */
+ private enum DirectExecutor implements Executor {
+ INSTANCE;
+ @Override public void execute(Runnable command) {
+ command.run();
+ }
+
+ @Override public String toString() {
+ return "MoreExecutors.directExecutor()";
+ }
+ }
+
+ /*
+ * This following method is a modified version of one found in
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/test/tck/AbstractExecutorServiceTest.java?revision=1.30
+ * which contained the following notice:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+ // TODO(lukes): provide overloads for ListeningExecutorService? ListeningScheduledExecutorService?
+ // TODO(lukes): provide overloads that take constant strings? Function<Runnable, String>s to
+ // calculate names?
+}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Platform.java
similarity index 56%
copy from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
copy to guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Platform.java
index ff45a39..fc75d67 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Platform.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,19 @@
* limitations under the License.
*/
-package com.google.common.collect;
-
-import java.util.Comparator;
+package com.google.common.util.concurrent;
/**
- * GWT emulation of {@link EmptyImmutableSortedSet}.
- *
- * @author Hayward Chan
+ * Methods factored out so that they can be emulated differently in GWT.
*/
-class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
- EmptyImmutableSortedSet(Comparator<? super E> comparator) {
- super(Sets.newTreeSet(comparator));
+final class Platform {
+ static boolean isInstanceOfThrowableClass(Throwable t, Class<? extends Throwable> expectedClass) {
+ /*
+ * This method is used only by CatchingFuture, and CatchingFuture accepts only Throwable.class
+ * under GWT.
+ */
+ return true;
}
+
+ private Platform() {}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableBiMap.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Uninterruptibles.java
similarity index 51%
copy from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableBiMap.java
copy to guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Uninterruptibles.java
index 1520d58..86eacb0 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableBiMap.java
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/Uninterruptibles.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,23 +14,25 @@
* limitations under the License.
*/
-package com.google.common.collect;
+package com.google.common.util.concurrent;
-import java.util.Collections;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
/**
- * GWT emulation of {@link EmptyImmutableBiMap}.
- *
- * @author Hayward Chan
+ * Emulation of Uninterruptibles in GWT.
*/
- at SuppressWarnings("serial")
-final class EmptyImmutableBiMap extends ImmutableBiMap<Object, Object> {
- static final EmptyImmutableBiMap INSTANCE = new EmptyImmutableBiMap();
+public final class Uninterruptibles {
- private EmptyImmutableBiMap() {
- super(Collections.emptyMap());
+ private Uninterruptibles() {
}
- @Override public ImmutableBiMap<Object, Object> inverse() {
- return this;
+
+ public static <V> V getUninterruptibly(Future<V> future) throws ExecutionException {
+ try {
+ return future.get();
+ } catch (InterruptedException e) {
+ // Should never be thrown in GWT but play it safe
+ throw new IllegalStateException(e);
+ }
}
}
diff --git a/guava-gwt/src-super/java/lang/Lang.gwt.xml b/guava-gwt/src-super/java/lang/Lang.gwt.xml
new file mode 100644
index 0000000..bd7134f
--- /dev/null
+++ b/guava-gwt/src-super/java/lang/Lang.gwt.xml
@@ -0,0 +1 @@
+<module><super-source path="super"/></module>
\ No newline at end of file
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSortedMap.java b/guava-gwt/src-super/java/lang/super/java/lang/InterruptedException.java
similarity index 59%
rename from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSortedMap.java
rename to guava-gwt/src-super/java/lang/super/java/lang/InterruptedException.java
index 2e36f39..3592c60 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/RegularImmutableSortedMap.java
+++ b/guava-gwt/src-super/java/lang/super/java/lang/InterruptedException.java
@@ -14,18 +14,19 @@
* limitations under the License.
*/
-package com.google.common.collect;
-
-import java.util.Comparator;
-import java.util.SortedMap;
+package java.lang;
/**
- * GWT emulated version of {@link RegularImmutableSortedMap}.
+ * Minimal emulation of {@link java.lang.InterruptedException}, that should
+ * only be used in method signatures. New GWT code should not reference this
+ * class at all. It is here only to ease the GWTification of common code.
*
- * @author Chris Povirk
+ * @author Tom O'Neill
*/
-final class RegularImmutableSortedMap<K, V> extends ImmutableSortedMap<K, V> {
- RegularImmutableSortedMap(SortedMap<K, V> delegate, Comparator<? super K> comparator) {
- super(delegate, comparator);
+public class InterruptedException extends Exception {
+ public InterruptedException() {}
+
+ public InterruptedException(String message) {
+ super(message);
}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableBiMap.java b/guava-gwt/src-super/java/lang/super/java/lang/reflect/UndeclaredThrowableException.java
similarity index 53%
rename from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableBiMap.java
rename to guava-gwt/src-super/java/lang/super/java/lang/reflect/UndeclaredThrowableException.java
index 1520d58..a7daad8 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableBiMap.java
+++ b/guava-gwt/src-super/java/lang/super/java/lang/reflect/UndeclaredThrowableException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,23 +14,21 @@
* limitations under the License.
*/
-package com.google.common.collect;
-
-import java.util.Collections;
+package java.lang.reflect;
/**
- * GWT emulation of {@link EmptyImmutableBiMap}.
- *
- * @author Hayward Chan
+ * GWT emulation of UndeclaredThrowableException.
*/
- at SuppressWarnings("serial")
-final class EmptyImmutableBiMap extends ImmutableBiMap<Object, Object> {
- static final EmptyImmutableBiMap INSTANCE = new EmptyImmutableBiMap();
+public class UndeclaredThrowableException extends RuntimeException {
+ public UndeclaredThrowableException(Throwable undeclaredThrowable) {
+ super(undeclaredThrowable);
+ }
- private EmptyImmutableBiMap() {
- super(Collections.emptyMap());
+ public UndeclaredThrowableException(Throwable undeclaredThrowable, String message) {
+ super(message, undeclaredThrowable);
}
- @Override public ImmutableBiMap<Object, Object> inverse() {
- return this;
+
+ public Throwable getUndeclaredThrowable() {
+ return getCause();
}
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSet.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/CancellationException.java
similarity index 59%
rename from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSet.java
rename to guava-gwt/src-super/java/util/super/java/util/concurrent/CancellationException.java
index ae3b3f3..24636e3 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSet.java
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/CancellationException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,19 +14,16 @@
* limitations under the License.
*/
-package com.google.common.collect;
-
-import java.util.Collections;
+package java.util.concurrent;
/**
- * GWT emulation of {@link EmptyImmutableSet}.
- *
- * @author Hayward Chan
+ * Emulation of CancellationException.
*/
-final class EmptyImmutableSet extends ForwardingImmutableSet<Object> {
- private EmptyImmutableSet() {
- super(Collections.emptySet());
- }
+public class CancellationException extends IllegalStateException {
- static final EmptyImmutableSet INSTANCE = new EmptyImmutableSet();
+ public CancellationException() {}
+
+ public CancellationException(String message) {
+ super(message);
+ }
}
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/CountDownLatch.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/CountDownLatch.java
new file mode 100644
index 0000000..b353296
--- /dev/null
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/CountDownLatch.java
@@ -0,0 +1,55 @@
+/*
+ * This file is a modified version of
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/CountDownLatch.java?revision=1.43
+ * which contained the following notice:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+/**
+ * Emulation of CountDownLatch in GWT. Since GWT environment is single threaded, attempting to block
+ * on the latch by calling {@link #await()} or {@link #await(long, TimeUnit)} when it is not ready
+ * is considered illegal because it would lead to a deadlock. Both methods will throw {@link
+ * IllegalStateException} to avoid the deadlock.
+ */
+public class CountDownLatch {
+
+ private int count;
+
+ public CountDownLatch(int count) {
+ if (count < 0) {
+ throw new IllegalArgumentException("count < 0");
+ }
+ this.count = count;
+ }
+
+ public void await() throws InterruptedException {
+ if (count > 0) {
+ throw new IllegalStateException("May not block. Count is " + count);
+ }
+ }
+
+ public boolean await(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ await();
+ return true;
+ }
+
+ public void countDown() {
+ if (count > 0) {
+ count--;
+ }
+ }
+
+ public long getCount() {
+ return count;
+ }
+
+ public String toString() {
+ return super.toString() + "[Count = " + count + "]";
+ }
+}
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/Delayed.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/Delayed.java
new file mode 100644
index 0000000..4bfca00
--- /dev/null
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/Delayed.java
@@ -0,0 +1,18 @@
+/*
+ * This file is a modified version of
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/CountDownLatch.java?revision=1.43
+ * which contained the following notice:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+/**
+ * Emulation of Delayed.
+ */
+public interface Delayed extends Comparable<Delayed> {
+ long getDelay(TimeUnit unit);
+}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/Executor.java
similarity index 61%
copy from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
copy to guava-gwt/src-super/java/util/super/java/util/concurrent/Executor.java
index ff45a39..35fc246 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/Executor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,11 @@
* limitations under the License.
*/
-package com.google.common.collect;
-
-import java.util.Comparator;
+package java.util.concurrent;
/**
- * GWT emulation of {@link EmptyImmutableSortedSet}.
- *
- * @author Hayward Chan
+ * Emulation of Executor.
*/
-class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
- EmptyImmutableSortedSet(Comparator<? super E> comparator) {
- super(Sets.newTreeSet(comparator));
- }
-}
+public interface Executor {
+ void execute(Runnable command);
+}
\ No newline at end of file
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/Executors.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/Executors.java
new file mode 100644
index 0000000..09a3e8d
--- /dev/null
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/Executors.java
@@ -0,0 +1,50 @@
+/*
+ * This file is a modified version of
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/Executors.java?revision=1.90
+ * which contained the following notice:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+/**
+ * Emulation of executors.
+ */
+public class Executors {
+
+ public static <T> Callable<T> callable(Runnable task, T result) {
+ if (task == null) {
+ throw new NullPointerException();
+ }
+ return new RunnableAdapter<T>(task, result);
+ }
+
+ public static Callable<Object> callable(Runnable task) {
+ if (task == null) {
+ throw new NullPointerException();
+ }
+ return new RunnableAdapter<Object>(task, null);
+ }
+
+ static final class RunnableAdapter<T> implements Callable<T> {
+
+ final Runnable task;
+ final T result;
+
+ RunnableAdapter(Runnable task, T result) {
+ this.task = task;
+ this.result = result;
+ }
+
+ public T call() {
+ task.run();
+ return result;
+ }
+ }
+
+ private Executors() {
+ }
+}
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/Future.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/Future.java
new file mode 100644
index 0000000..db07080
--- /dev/null
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/Future.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.concurrent;
+
+/**
+ * Emulation of Future. Since GWT environment is single threaded, attempting to block on the future
+ * by calling {@link #get()} or {@link #get(long, TimeUnit)} when the it is not yet done is
+ * considered illegal because it would lead to a deadlock. Future implementations must throw
+ * {@link IllegalStateException} to avoid a deadlock.
+ */
+public interface Future<V> {
+ boolean cancel(boolean mayInterruptIfRunning);
+
+ boolean isCancelled();
+
+ boolean isDone();
+
+ V get() throws InterruptedException, ExecutionException;
+
+ V get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException;
+}
diff --git a/guava/src/com/google/common/collect/SortedMultisetBridge.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/RejectedExecutionException.java
similarity index 55%
copy from guava/src/com/google/common/collect/SortedMultisetBridge.java
copy to guava-gwt/src-super/java/util/super/java/util/concurrent/RejectedExecutionException.java
index 669b54d..ec7c2da 100644
--- a/guava/src/com/google/common/collect/SortedMultisetBridge.java
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/RejectedExecutionException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,18 +14,24 @@
* limitations under the License.
*/
-package com.google.common.collect;
-
-import java.util.SortedSet;
+package java.util.concurrent;
/**
- * Superinterface of {@link SortedMultiset} to introduce a bridge method for
- * {@code elementSet()}, to ensure binary compatibility with older Guava versions
- * that specified {@code elementSet()} to return {@code SortedSet}.
- *
- * @author Louis Wasserman
+ * GWT emulation of RejectedExecutionException.
*/
-interface SortedMultisetBridge<E> extends Multiset<E> {
- @Override
- SortedSet<E> elementSet();
+public class RejectedExecutionException extends RuntimeException {
+ public RejectedExecutionException() {
+ }
+
+ public RejectedExecutionException(String message) {
+ super(message);
+ }
+
+ public RejectedExecutionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public RejectedExecutionException(Throwable cause) {
+ super(cause);
+ }
}
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/RunnableFuture.java
similarity index 61%
copy from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
copy to guava-gwt/src-super/java/util/super/java/util/concurrent/RunnableFuture.java
index ff45a39..08e2660 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/RunnableFuture.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,10 @@
* limitations under the License.
*/
-package com.google.common.collect;
-
-import java.util.Comparator;
+package java.util.concurrent;
/**
- * GWT emulation of {@link EmptyImmutableSortedSet}.
- *
- * @author Hayward Chan
+ * Emulation of RunnableFuture.
*/
-class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
- EmptyImmutableSortedSet(Comparator<? super E> comparator) {
- super(Sets.newTreeSet(comparator));
- }
+public interface RunnableFuture<V> extends Runnable, Future<V> {
}
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/ScheduledFuture.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/ScheduledFuture.java
new file mode 100644
index 0000000..616acab
--- /dev/null
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/ScheduledFuture.java
@@ -0,0 +1,19 @@
+/*
+ * This file is a modified version of
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/CountDownLatch.java?revision=1.43
+ * which contained the following notice:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+/**
+ * Emulation of ScheduleFuture.
+ *
+ * @param <V> value type returned by the future.
+ */
+public interface ScheduledFuture<V> extends Delayed, Future<V> {
+}
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/TimeUnit.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/TimeUnit.java
index 52f3fb4..ba891b3 100644
--- a/guava-gwt/src-super/java/util/super/java/util/concurrent/TimeUnit.java
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/TimeUnit.java
@@ -17,77 +17,77 @@ package java.util.concurrent;
public enum TimeUnit {
NANOSECONDS {
public long toNanos(long d) { return d; }
- public long toMicros(long d) { return d/(C1/C0); }
- public long toMillis(long d) { return d/(C2/C0); }
- public long toSeconds(long d) { return d/(C3/C0); }
- public long toMinutes(long d) { return d/(C4/C0); }
- public long toHours(long d) { return d/(C5/C0); }
- public long toDays(long d) { return d/(C6/C0); }
+ public long toMicros(long d) { return d / C1_C0; }
+ public long toMillis(long d) { return d / C2_C0; }
+ public long toSeconds(long d) { return d / C3_C0; }
+ public long toMinutes(long d) { return d / C4_C0; }
+ public long toHours(long d) { return d / C5_C0; }
+ public long toDays(long d) { return d / C6_C0; }
public long convert(long d, TimeUnit u) { return u.toNanos(d); }
int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
},
MICROSECONDS {
- public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); }
+ public long toNanos(long d) { return x(d, C1_C0, MAX_C1_C0); }
public long toMicros(long d) { return d; }
- public long toMillis(long d) { return d/(C2/C1); }
- public long toSeconds(long d) { return d/(C3/C1); }
- public long toMinutes(long d) { return d/(C4/C1); }
- public long toHours(long d) { return d/(C5/C1); }
- public long toDays(long d) { return d/(C6/C1); }
+ public long toMillis(long d) { return d / C2_C1; }
+ public long toSeconds(long d) { return d / C3_C1; }
+ public long toMinutes(long d) { return d / C4_C1; }
+ public long toHours(long d) { return d / C5_C1; }
+ public long toDays(long d) { return d / C6_C1; }
public long convert(long d, TimeUnit u) { return u.toMicros(d); }
int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
},
MILLISECONDS {
- public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); }
- public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); }
+ public long toNanos(long d) { return x(d, C2_C0, MAX_C2_C0); }
+ public long toMicros(long d) { return x(d, C2_C1, MAX_C2_C1); }
public long toMillis(long d) { return d; }
- public long toSeconds(long d) { return d/(C3/C2); }
- public long toMinutes(long d) { return d/(C4/C2); }
- public long toHours(long d) { return d/(C5/C2); }
- public long toDays(long d) { return d/(C6/C2); }
+ public long toSeconds(long d) { return d / C3_C2; }
+ public long toMinutes(long d) { return d / C4_C2; }
+ public long toHours(long d) { return d / C5_C2; }
+ public long toDays(long d) { return d / C6_C2; }
public long convert(long d, TimeUnit u) { return u.toMillis(d); }
int excessNanos(long d, long m) { return 0; }
},
SECONDS {
- public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); }
- public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); }
- public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); }
+ public long toNanos(long d) { return x(d, C3_C0, MAX_C3_C0); }
+ public long toMicros(long d) { return x(d, C3_C1, MAX_C3_C1); }
+ public long toMillis(long d) { return x(d, C3_C2, MAX_C3_C2); }
public long toSeconds(long d) { return d; }
- public long toMinutes(long d) { return d/(C4/C3); }
- public long toHours(long d) { return d/(C5/C3); }
- public long toDays(long d) { return d/(C6/C3); }
+ public long toMinutes(long d) { return d / C4_C3; }
+ public long toHours(long d) { return d / C5_C3; }
+ public long toDays(long d) { return d / C6_C3; }
public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
int excessNanos(long d, long m) { return 0; }
},
MINUTES {
- public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); }
- public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); }
- public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); }
- public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
+ public long toNanos(long d) { return x(d, C4_C0, MAX_C4_C0); }
+ public long toMicros(long d) { return x(d, C4_C1, MAX_C4_C1); }
+ public long toMillis(long d) { return x(d, C4_C2, MAX_C4_C2); }
+ public long toSeconds(long d) { return x(d, C4_C3, MAX_C4_C3); }
public long toMinutes(long d) { return d; }
- public long toHours(long d) { return d/(C5/C4); }
- public long toDays(long d) { return d/(C6/C4); }
+ public long toHours(long d) { return d / C5_C4; }
+ public long toDays(long d) { return d / C6_C4; }
public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
int excessNanos(long d, long m) { return 0; }
},
HOURS {
- public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); }
- public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); }
- public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); }
- public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
- public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
+ public long toNanos(long d) { return x(d, C5_C0, MAX_C5_C0); }
+ public long toMicros(long d) { return x(d, C5_C1, MAX_C5_C1); }
+ public long toMillis(long d) { return x(d, C5_C2, MAX_C5_C2); }
+ public long toSeconds(long d) { return x(d, C5_C3, MAX_C5_C3); }
+ public long toMinutes(long d) { return x(d, C5_C4, MAX_C5_C4); }
public long toHours(long d) { return d; }
- public long toDays(long d) { return d/(C6/C5); }
+ public long toDays(long d) { return d / C6_C5; }
public long convert(long d, TimeUnit u) { return u.toHours(d); }
int excessNanos(long d, long m) { return 0; }
},
DAYS {
- public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); }
- public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); }
- public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); }
- public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
- public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
- public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); }
+ public long toNanos(long d) { return x(d, C6_C0, MAX_C6_C0); }
+ public long toMicros(long d) { return x(d, C6_C1, MAX_C6_C1); }
+ public long toMillis(long d) { return x(d, C6_C2, MAX_C6_C2); }
+ public long toSeconds(long d) { return x(d, C6_C3, MAX_C6_C3); }
+ public long toMinutes(long d) { return x(d, C6_C4, MAX_C6_C4); }
+ public long toHours(long d) { return x(d, C6_C5, MAX_C6_C5); }
public long toDays(long d) { return d; }
public long convert(long d, TimeUnit u) { return u.toDays(d); }
int excessNanos(long d, long m) { return 0; }
@@ -103,7 +103,61 @@ public enum TimeUnit {
static final long C6 = C5 * 24L;
static final long MAX = Long.MAX_VALUE;
+
+ static final long C6_C0 = C6 / C0;
+ static final long C6_C1 = C6 / C1;
+ static final long C6_C2 = C6 / C2;
+ static final long C6_C3 = C6 / C3;
+ static final long C6_C4 = C6 / C4;
+ static final long C6_C5 = C6 / C5;
+ static final long C5_C0 = C5 / C0;
+ static final long C5_C1 = C5 / C1;
+ static final long C5_C2 = C5 / C2;
+ static final long C5_C3 = C5 / C3;
+ static final long C5_C4 = C5 / C4;
+
+ static final long C4_C0 = C4 / C0;
+ static final long C4_C1 = C4 / C1;
+ static final long C4_C2 = C4 / C2;
+ static final long C4_C3 = C4 / C3;
+
+ static final long C3_C0 = C3 / C0;
+ static final long C3_C1 = C3 / C1;
+ static final long C3_C2 = C3 / C2;
+
+ static final long C2_C0 = C2 / C0;
+ static final long C2_C1 = C2 / C1;
+
+ static final long C1_C0 = C1 / C0;
+
+ static final long MAX_C6_C0 = MAX / C6_C0;
+ static final long MAX_C6_C1 = MAX / C6_C1;
+ static final long MAX_C6_C2 = MAX / C6_C2;
+ static final long MAX_C6_C3 = MAX / C6_C3;
+ static final long MAX_C6_C4 = MAX / C6_C4;
+ static final long MAX_C6_C5 = MAX / C6_C5;
+
+ static final long MAX_C5_C0 = MAX / C5_C0;
+ static final long MAX_C5_C1 = MAX / C5_C1;
+ static final long MAX_C5_C2 = MAX / C5_C2;
+ static final long MAX_C5_C3 = MAX / C5_C3;
+ static final long MAX_C5_C4 = MAX / C5_C4;
+
+ static final long MAX_C4_C0 = MAX / C4_C0;
+ static final long MAX_C4_C1 = MAX / C4_C1;
+ static final long MAX_C4_C2 = MAX / C4_C2;
+ static final long MAX_C4_C3 = MAX / C4_C3;
+
+ static final long MAX_C3_C0 = MAX / C3_C0;
+ static final long MAX_C3_C1 = MAX / C3_C1;
+ static final long MAX_C3_C2 = MAX / C3_C2;
+
+ static final long MAX_C2_C0 = MAX / C2_C0;
+ static final long MAX_C2_C1 = MAX / C2_C1;
+
+ static final long MAX_C1_C0 = MAX / C1_C0;
+
static long x(long d, long m, long over) {
if (d > over) return Long.MAX_VALUE;
if (d < -over) return Long.MIN_VALUE;
diff --git a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/TimeoutException.java
similarity index 62%
rename from guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
rename to guava-gwt/src-super/java/util/super/java/util/concurrent/TimeoutException.java
index ff45a39..63723f6 100644
--- a/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/EmptyImmutableSortedSet.java
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/TimeoutException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,15 @@
* limitations under the License.
*/
-package com.google.common.collect;
-
-import java.util.Comparator;
+package java.util.concurrent;
/**
- * GWT emulation of {@link EmptyImmutableSortedSet}.
- *
- * @author Hayward Chan
+ * Emulation of TimeoutException.
*/
-class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
- EmptyImmutableSortedSet(Comparator<? super E> comparator) {
- super(Sets.newTreeSet(comparator));
+public class TimeoutException extends Exception {
+ public TimeoutException() {}
+
+ public TimeoutException(String message) {
+ super(message);
}
}
diff --git a/guava-gwt/src-super/java/util/super/java/util/concurrent/atomic/AtomicBoolean.java b/guava-gwt/src-super/java/util/super/java/util/concurrent/atomic/AtomicBoolean.java
new file mode 100644
index 0000000..a871204
--- /dev/null
+++ b/guava-gwt/src-super/java/util/super/java/util/concurrent/atomic/AtomicBoolean.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ /**
+ * Atomically sets the value to the given updated value
+ * if the current value {@code ==} the expected value.
+ *
+ * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+ * and does not provide ordering guarantees, so is only rarely an
+ * appropriate alternative to {@code compareAndSet}.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+
+package java.util.concurrent.atomic;
+
+/**
+ * GWT emulation of AtomicBoolean.
+ */
+public class AtomicBoolean implements java.io.Serializable {
+ private boolean value;
+
+ public AtomicBoolean(boolean initialValue) {
+ value = initialValue;
+ }
+
+ public AtomicBoolean() {
+ }
+
+ public final boolean get() {
+ return value;
+ }
+
+ public final boolean compareAndSet(boolean expect, boolean update) {
+ if (get() == expect) {
+ set(update);
+ return true;
+ }
+
+ return false;
+ }
+
+ public boolean weakCompareAndSet(boolean expect, boolean update) {
+ return compareAndSet(expect, update);
+ }
+
+ public final void set(boolean newValue) {
+ value = newValue;
+ }
+
+ public final void lazySet(boolean newValue) {
+ set(newValue);
+ }
+
+ public final boolean getAndSet(boolean newValue) {
+ boolean current = get();
+ set(newValue);
+ return current;
+ }
+
+ public String toString() {
+ return Boolean.toString(get());
+ }
+}
diff --git a/guava-gwt/src/com/google/common/annotations/Annotations.gwt.xml b/guava-gwt/src/com/google/common/annotations/Annotations.gwt.xml
index 7338d55..dde2a98 100644
--- a/guava-gwt/src/com/google/common/annotations/Annotations.gwt.xml
+++ b/guava-gwt/src/com/google/common/annotations/Annotations.gwt.xml
@@ -13,7 +13,7 @@
<!-- We used to set this only for packages that had manual supersource. That worked everywhere that I know of except for one place: when running the GWT util.concurrent tests under Guava. The problem is that GWT responds poorly to two .gwt.xml files in the same Java package: http://goo.gl/CO7dLB The summary is that it ignores one file in favor of the other. util.concurrent, like nearly all our packages, has two .gwt.xml files: one for prod and one for tests. util.concurrent, unlike our [...]
<super-source path="super"/>
-
+
<inherits name="com.google.gwt.core.Core"/>
</module>
diff --git a/guava-gwt/src/com/google/common/base/Base.gwt.xml b/guava-gwt/src/com/google/common/base/Base.gwt.xml
index 6041565..955a3c1 100644
--- a/guava-gwt/src/com/google/common/base/Base.gwt.xml
+++ b/guava-gwt/src/com/google/common/base/Base.gwt.xml
@@ -21,7 +21,7 @@
<inherits name="java.nio.charset.Charset"/>
<inherits name="java.util.Util"/>
-
+
<inherits name="com.google.gwt.core.Core"/>
</module>
diff --git a/guava-gwt/src/com/google/common/base/GwtSerializationDependencies.java b/guava-gwt/src/com/google/common/base/GwtSerializationDependencies.java
index 0ddac1f..9b93ee9 100644
--- a/guava-gwt/src/com/google/common/base/GwtSerializationDependencies.java
+++ b/guava-gwt/src/com/google/common/base/GwtSerializationDependencies.java
@@ -42,48 +42,58 @@ final class GwtSerializationDependencies {
super();
}
- @Override public boolean isPresent() {
+ @Override
+ public boolean isPresent() {
throw new AssertionError();
}
- @Override public T get() {
+ @Override
+ public T get() {
throw new AssertionError();
}
- @Override public T or(T defaultValue) {
+ @Override
+ public T or(T defaultValue) {
throw new AssertionError();
}
- @Override public Optional<T> or(Optional<? extends T> secondChoice) {
+ @Override
+ public Optional<T> or(Optional<? extends T> secondChoice) {
throw new AssertionError();
}
- @Override public T or(Supplier<? extends T> supplier) {
+ @Override
+ public T or(Supplier<? extends T> supplier) {
throw new AssertionError();
}
- @Override public T orNull() {
+ @Override
+ public T orNull() {
throw new AssertionError();
}
- @Override public Set<T> asSet() {
+ @Override
+ public Set<T> asSet() {
throw new AssertionError();
}
- @Override public <V> Optional<V> transform(
- Function<? super T, V> function) {
+ @Override
+ public <V> Optional<V> transform(Function<? super T, V> function) {
throw new AssertionError();
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
throw new AssertionError();
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
throw new AssertionError();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
throw new AssertionError();
}
}
diff --git a/guava-gwt/src/com/google/common/base/PairwiseEquivalence_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/base/PairwiseEquivalence_CustomFieldSerializer.java
index 531550c..0a34f93 100644
--- a/guava-gwt/src/com/google/common/base/PairwiseEquivalence_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/base/PairwiseEquivalence_CustomFieldSerializer.java
@@ -29,8 +29,8 @@ public class PairwiseEquivalence_CustomFieldSerializer {
private PairwiseEquivalence_CustomFieldSerializer() {}
- public static void deserialize(SerializationStreamReader reader,
- PairwiseEquivalence<?> instance) {}
+ public static void deserialize(
+ SerializationStreamReader reader, PairwiseEquivalence<?> instance) {}
public static PairwiseEquivalence<?> instantiate(SerializationStreamReader reader)
throws SerializationException {
diff --git a/guava-gwt/src/com/google/common/collect/AllEqualOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/AllEqualOrdering_CustomFieldSerializer.java
index 4b9d370..ab46c9e 100644
--- a/guava-gwt/src/com/google/common/collect/AllEqualOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/AllEqualOrdering_CustomFieldSerializer.java
@@ -25,13 +25,11 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
* @author Chris Povirk
*/
public class AllEqualOrdering_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader, AllEqualOrdering instance) {
- }
+ public static void deserialize(SerializationStreamReader reader, AllEqualOrdering instance) {}
public static AllEqualOrdering instantiate(SerializationStreamReader reader) {
return AllEqualOrdering.INSTANCE;
}
- public static void serialize(SerializationStreamWriter writer, AllEqualOrdering instance) {
- }
+ public static void serialize(SerializationStreamWriter writer, AllEqualOrdering instance) {}
}
diff --git a/guava-gwt/src/com/google/common/collect/ArrayListMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ArrayListMultimap_CustomFieldSerializer.java
index 129562d..a58ca25 100644
--- a/guava-gwt/src/com/google/common/collect/ArrayListMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ArrayListMultimap_CustomFieldSerializer.java
@@ -22,24 +22,21 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of {@link ArrayListMultimap}.
- *
+ *
* @author Chris Povirk
*/
public class ArrayListMultimap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader in,
- ArrayListMultimap<?, ?> out) {
- }
+ public static void deserialize(SerializationStreamReader in, ArrayListMultimap<?, ?> out) {}
- public static ArrayListMultimap<Object, Object> instantiate(
- SerializationStreamReader in) throws SerializationException {
+ public static ArrayListMultimap<Object, Object> instantiate(SerializationStreamReader in)
+ throws SerializationException {
return (ArrayListMultimap<Object, Object>)
- Multimap_CustomFieldSerializerBase.populate(
- in, ArrayListMultimap.create());
+ Multimap_CustomFieldSerializerBase.populate(in, ArrayListMultimap.create());
}
- public static void serialize(SerializationStreamWriter out,
- ArrayListMultimap<?, ?> multimap) throws SerializationException {
+ public static void serialize(SerializationStreamWriter out, ArrayListMultimap<?, ?> multimap)
+ throws SerializationException {
Multimap_CustomFieldSerializerBase.serialize(out, multimap);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/ByFunctionOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ByFunctionOrdering_CustomFieldSerializer.java
index d42648c..c79b569 100644
--- a/guava-gwt/src/com/google/common/collect/ByFunctionOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ByFunctionOrdering_CustomFieldSerializer.java
@@ -23,25 +23,23 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of {@link ByFunctionOrdering}.
- *
+ *
* @author Chris Povirk
*/
public class ByFunctionOrdering_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- ByFunctionOrdering<?, ?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, ByFunctionOrdering<?, ?> instance) {}
@SuppressWarnings("unchecked") // deserialization is unsafe
- public static ByFunctionOrdering<Object, Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static ByFunctionOrdering<Object, Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
return new ByFunctionOrdering<Object, Object>(
- (Function<Object, Object>) reader.readObject(),
- (Ordering<Object>) reader.readObject());
+ (Function<Object, Object>) reader.readObject(), (Ordering<Object>) reader.readObject());
}
- public static void serialize(SerializationStreamWriter writer,
- ByFunctionOrdering<?, ?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, ByFunctionOrdering<?, ?> instance)
+ throws SerializationException {
writer.writeObject(instance.function);
writer.writeObject(instance.ordering);
}
diff --git a/guava-gwt/src/com/google/common/collect/Collect.gwt.xml b/guava-gwt/src/com/google/common/collect/Collect.gwt.xml
index 8b98acd..38316f9 100644
--- a/guava-gwt/src/com/google/common/collect/Collect.gwt.xml
+++ b/guava-gwt/src/com/google/common/collect/Collect.gwt.xml
@@ -23,9 +23,11 @@
<inherits name="com.google.common.math.Math"/>
<inherits name="com.google.common.primitives.Primitives"/>
-
+
+ <inherits name="java.lang.Lang"/>
+
<inherits name="java.util.Util"/>
-
+
<inherits name="com.google.gwt.core.Core"/>
</module>
diff --git a/guava-gwt/src/com/google/common/collect/ComparatorOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ComparatorOrdering_CustomFieldSerializer.java
index 4b0cc11..7d2e313 100644
--- a/guava-gwt/src/com/google/common/collect/ComparatorOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ComparatorOrdering_CustomFieldSerializer.java
@@ -24,24 +24,22 @@ import java.util.Comparator;
/**
* This class implements the GWT serialization of {@link ComparatorOrdering}.
- *
+ *
* @author Chris Povirk
*/
public class ComparatorOrdering_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- ComparatorOrdering<?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, ComparatorOrdering<?> instance) {}
@SuppressWarnings("unchecked") // deserialization is unsafe
- public static ComparatorOrdering<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
- return new ComparatorOrdering<Object>(
- (Comparator<Object>) reader.readObject());
+ public static ComparatorOrdering<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
+ return new ComparatorOrdering<Object>((Comparator<Object>) reader.readObject());
}
- public static void serialize(SerializationStreamWriter writer,
- ComparatorOrdering<?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, ComparatorOrdering<?> instance)
+ throws SerializationException {
writer.writeObject(instance.comparator);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/CompoundOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/CompoundOrdering_CustomFieldSerializer.java
index 2cfd6dc..23cef62 100644
--- a/guava-gwt/src/com/google/common/collect/CompoundOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/CompoundOrdering_CustomFieldSerializer.java
@@ -24,24 +24,21 @@ import java.util.Comparator;
/**
* This class implements the GWT serialization of {@link CompoundOrdering}.
- *
+ *
* @author Chris Povirk
*/
public class CompoundOrdering_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- CompoundOrdering<?> instance) {
- }
+ public static void deserialize(SerializationStreamReader reader, CompoundOrdering<?> instance) {}
@SuppressWarnings("unchecked") // deserialization is unsafe
- public static CompoundOrdering<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
- return new CompoundOrdering<Object>(
- (ImmutableList<Comparator<Object>>) reader.readObject());
+ public static CompoundOrdering<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
+ return new CompoundOrdering<Object>((ImmutableList<Comparator<Object>>) reader.readObject());
}
- public static void serialize(SerializationStreamWriter writer,
- CompoundOrdering<?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, CompoundOrdering<?> instance)
+ throws SerializationException {
writer.writeObject(instance.comparators);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/DenseImmutableTable_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/DenseImmutableTable_CustomFieldSerializer.java
index 2bc219b..c02db5b 100644
--- a/guava-gwt/src/com/google/common/collect/DenseImmutableTable_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/DenseImmutableTable_CustomFieldSerializer.java
@@ -25,8 +25,7 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
*/
public class DenseImmutableTable_CustomFieldSerializer {
public static void deserialize(
- SerializationStreamReader reader, DenseImmutableTable<?, ?, ?> instance) {
- }
+ SerializationStreamReader reader, DenseImmutableTable<?, ?, ?> instance) {}
public static DenseImmutableTable<Object, Object, Object> instantiate(
SerializationStreamReader reader) throws SerializationException {
diff --git a/guava-gwt/src/com/google/common/collect/EmptyImmutableBiMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/EmptyImmutableBiMap_CustomFieldSerializer.java
deleted file mode 100644
index c2d7a05..0000000
--- a/guava-gwt/src/com/google/common/collect/EmptyImmutableBiMap_CustomFieldSerializer.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2009 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.collect;
-
-import com.google.gwt.user.client.rpc.SerializationStreamReader;
-import com.google.gwt.user.client.rpc.SerializationStreamWriter;
-
-/**
- * This class implements the GWT serialization of
- * {@link EmptyImmutableBiMap}.
- *
- * @author Chris Povirk
- */
-public class EmptyImmutableBiMap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader, EmptyImmutableBiMap instance) {
- }
-
- public static EmptyImmutableBiMap instantiate(SerializationStreamReader reader) {
- return EmptyImmutableBiMap.INSTANCE;
- }
-
- public static void serialize(SerializationStreamWriter writer, EmptyImmutableBiMap instance) {
- }
-}
diff --git a/guava-gwt/src/com/google/common/collect/EmptyImmutableListMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/EmptyImmutableListMultimap_CustomFieldSerializer.java
index 8b1173e..23d706f 100644
--- a/guava-gwt/src/com/google/common/collect/EmptyImmutableListMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/EmptyImmutableListMultimap_CustomFieldSerializer.java
@@ -22,21 +22,18 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of
* {@link EmptyImmutableListMultimap}.
- *
+ *
* @author Chris Povirk
*/
public class EmptyImmutableListMultimap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- EmptyImmutableListMultimap instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, EmptyImmutableListMultimap instance) {}
- public static EmptyImmutableListMultimap instantiate(
- SerializationStreamReader reader) {
+ public static EmptyImmutableListMultimap instantiate(SerializationStreamReader reader) {
return EmptyImmutableListMultimap.INSTANCE;
}
- public static void serialize(SerializationStreamWriter writer,
- EmptyImmutableListMultimap instance) {
- }
+ public static void serialize(
+ SerializationStreamWriter writer, EmptyImmutableListMultimap instance) {}
}
diff --git a/guava-gwt/src/com/google/common/collect/EmptyImmutableSetMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/EmptyImmutableSetMultimap_CustomFieldSerializer.java
index 905abfb..f08d80c 100644
--- a/guava-gwt/src/com/google/common/collect/EmptyImmutableSetMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/EmptyImmutableSetMultimap_CustomFieldSerializer.java
@@ -22,21 +22,18 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of
* {@link EmptyImmutableSetMultimap}.
- *
+ *
* @author Chris Povirk
*/
public class EmptyImmutableSetMultimap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- EmptyImmutableSetMultimap instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, EmptyImmutableSetMultimap instance) {}
- public static EmptyImmutableSetMultimap instantiate(
- SerializationStreamReader reader) {
+ public static EmptyImmutableSetMultimap instantiate(SerializationStreamReader reader) {
return EmptyImmutableSetMultimap.INSTANCE;
}
- public static void serialize(SerializationStreamWriter writer,
- EmptyImmutableSetMultimap instance) {
- }
+ public static void serialize(
+ SerializationStreamWriter writer, EmptyImmutableSetMultimap instance) {}
}
diff --git a/guava-gwt/src/com/google/common/collect/EmptyImmutableSet_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/EmptyImmutableSet_CustomFieldSerializer.java
deleted file mode 100644
index b52dac9..0000000
--- a/guava-gwt/src/com/google/common/collect/EmptyImmutableSet_CustomFieldSerializer.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2009 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.collect;
-
-import com.google.gwt.user.client.rpc.SerializationStreamReader;
-import com.google.gwt.user.client.rpc.SerializationStreamWriter;
-
-/**
- * This class implements the GWT serialization of {@link EmptyImmutableSet}.
- *
- * @author Chris Povirk
- */
-public class EmptyImmutableSet_CustomFieldSerializer {
-
- public static void deserialize(SerializationStreamReader reader,
- EmptyImmutableSet instance) {
- }
-
- public static EmptyImmutableSet instantiate(
- SerializationStreamReader reader) {
- return EmptyImmutableSet.INSTANCE;
- }
-
- public static void serialize(SerializationStreamWriter writer,
- EmptyImmutableSet instance) {
- }
-}
diff --git a/guava-gwt/src/com/google/common/collect/EmptyImmutableSortedMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/EmptyImmutableSortedMap_CustomFieldSerializer.java
deleted file mode 100644
index a47f6a0..0000000
--- a/guava-gwt/src/com/google/common/collect/EmptyImmutableSortedMap_CustomFieldSerializer.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2009 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.collect;
-
-import com.google.gwt.user.client.rpc.SerializationException;
-import com.google.gwt.user.client.rpc.SerializationStreamReader;
-import com.google.gwt.user.client.rpc.SerializationStreamWriter;
-
-/**
- * This class implements the GWT serialization of {@link EmptyImmutableSortedMap}.
- *
- * @author Chris Povirk
- */
-public class EmptyImmutableSortedMap_CustomFieldSerializer {
- public static void deserialize(
- SerializationStreamReader reader, EmptyImmutableSortedMap<?, ?> instance) {
- }
-
- public static EmptyImmutableSortedMap<?, ?> instantiate(
- SerializationStreamReader reader) throws SerializationException {
- return (EmptyImmutableSortedMap<?, ?>)
- ImmutableSortedMap_CustomFieldSerializerBase.instantiate(reader);
- }
-
- public static void serialize(
- SerializationStreamWriter writer, EmptyImmutableSortedMap<?, ?> instance)
- throws SerializationException {
- ImmutableSortedMap_CustomFieldSerializerBase.serialize(writer, instance);
- }
-}
diff --git a/guava-gwt/src/com/google/common/collect/EmptyImmutableSortedSet_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/EmptyImmutableSortedSet_CustomFieldSerializer.java
deleted file mode 100644
index 3857616..0000000
--- a/guava-gwt/src/com/google/common/collect/EmptyImmutableSortedSet_CustomFieldSerializer.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2009 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.collect;
-
-import com.google.gwt.user.client.rpc.SerializationException;
-import com.google.gwt.user.client.rpc.SerializationStreamReader;
-import com.google.gwt.user.client.rpc.SerializationStreamWriter;
-
-import java.util.Comparator;
-
-/**
- * This class implements the GWT serialization of
- * {@link EmptyImmutableSortedSet}.
- *
- * @author Chris Povirk
- */
-public class EmptyImmutableSortedSet_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- EmptyImmutableSortedSet<?> instance) {
- }
-
- public static EmptyImmutableSortedSet<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
- /*
- * Nothing we can do, but we're already assuming the serialized form is
- * correctly typed, anyway.
- */
- @SuppressWarnings("unchecked")
- Comparator<Object> comparator = (Comparator<Object>) reader.readObject();
-
- /*
- * For this custom field serializer to be invoked, the set must have been
- * EmptyImmutableSortedSet before it's serialized. Since
- * EmptyImmutableSortedSet always has no elements, ImmutableSortedSet.copyOf
- * always return an EmptyImmutableSortedSet back.
- */
- return (EmptyImmutableSortedSet<Object>)
- ImmutableSortedSet.orderedBy(comparator).build();
- }
-
- public static void serialize(SerializationStreamWriter writer,
- EmptyImmutableSortedSet<?> instance) throws SerializationException {
- writer.writeObject(instance.comparator());
- }
-}
diff --git a/guava-gwt/src/com/google/common/collect/ExplicitOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ExplicitOrdering_CustomFieldSerializer.java
index 89ebdf2..ffbbe49 100644
--- a/guava-gwt/src/com/google/common/collect/ExplicitOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ExplicitOrdering_CustomFieldSerializer.java
@@ -22,24 +22,21 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of {@link ExplicitOrdering}.
- *
+ *
* @author Chris Povirk
*/
public class ExplicitOrdering_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- ExplicitOrdering<?> instance) {
- }
+ public static void deserialize(SerializationStreamReader reader, ExplicitOrdering<?> instance) {}
@SuppressWarnings("unchecked") // deserialization is unsafe
- public static ExplicitOrdering<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
- return new ExplicitOrdering<Object>(
- (ImmutableMap<Object, Integer>) reader.readObject());
+ public static ExplicitOrdering<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
+ return new ExplicitOrdering<Object>((ImmutableMap<Object, Integer>) reader.readObject());
}
- public static void serialize(SerializationStreamWriter writer,
- ExplicitOrdering<?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, ExplicitOrdering<?> instance)
+ throws SerializationException {
writer.writeObject(instance.rankMap);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/GwtSerializationDependencies.java b/guava-gwt/src/com/google/common/collect/GwtSerializationDependencies.java
index 92a59fb..baaf753 100644
--- a/guava-gwt/src/com/google/common/collect/GwtSerializationDependencies.java
+++ b/guava-gwt/src/com/google/common/collect/GwtSerializationDependencies.java
@@ -60,8 +60,7 @@ import java.util.TreeMap;
final class GwtSerializationDependencies {
private GwtSerializationDependencies() {}
- static final class ImmutableListMultimapDependencies<K, V>
- extends ImmutableListMultimap<K, V> {
+ static final class ImmutableListMultimapDependencies<K, V> extends ImmutableListMultimap<K, V> {
K key;
V value;
@@ -74,8 +73,7 @@ final class GwtSerializationDependencies {
// ImmutableMultimap is covered by ImmutableSetMultimap/ImmutableListMultimap.
- static final class ImmutableSetMultimapDependencies<K, V>
- extends ImmutableSetMultimap<K, V> {
+ static final class ImmutableSetMultimapDependencies<K, V> extends ImmutableSetMultimap<K, V> {
K key;
V value;
@@ -88,16 +86,14 @@ final class GwtSerializationDependencies {
* We support an interface declared in terms of LinkedListMultimap because it
* supports entry ordering not supported by other implementations.
*/
- static final class LinkedListMultimapDependencies<K, V>
- extends LinkedListMultimap<K, V> {
+ static final class LinkedListMultimapDependencies<K, V> extends LinkedListMultimap<K, V> {
K key;
V value;
LinkedListMultimapDependencies() {}
}
- static final class HashBasedTableDependencies<R, C, V>
- extends HashBasedTable<R, C, V> {
+ static final class HashBasedTableDependencies<R, C, V> extends HashBasedTable<R, C, V> {
HashMap<R, HashMap<C, V>> data;
HashBasedTableDependencies() {
@@ -105,8 +101,7 @@ final class GwtSerializationDependencies {
}
}
- static final class TreeBasedTableDependencies<R, C, V>
- extends TreeBasedTable<R, C, V> {
+ static final class TreeBasedTableDependencies<R, C, V> extends TreeBasedTable<R, C, V> {
TreeMap<R, TreeMap<C, V>> data;
TreeBasedTableDependencies() {
@@ -120,8 +115,8 @@ final class GwtSerializationDependencies {
* need for GWT to believe that this dummy class is serializable, or else it
* won't generate serialization code for R, C, and V.
*/
- static final class ImmutableTableDependencies<R, C, V>
- extends SingletonImmutableTable<R, C, V> implements Serializable {
+ static final class ImmutableTableDependencies<R, C, V> extends SingletonImmutableTable<R, C, V>
+ implements Serializable {
R rowKey;
C columnKey;
V value;
@@ -131,8 +126,7 @@ final class GwtSerializationDependencies {
}
}
- static final class TreeMultimapDependencies<K, V>
- extends TreeMultimap<K, V> {
+ static final class TreeMultimapDependencies<K, V> extends TreeMultimap<K, V> {
Comparator<? super K> keyComparator;
Comparator<? super V> valueComparator;
K key;
diff --git a/guava-gwt/src/com/google/common/collect/HashBasedTable_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/HashBasedTable_CustomFieldSerializer.java
index 26f3e13..4ce2b43 100644
--- a/guava-gwt/src/com/google/common/collect/HashBasedTable_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/HashBasedTable_CustomFieldSerializer.java
@@ -24,8 +24,7 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
* @author Hayward Chan
*/
public class HashBasedTable_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader, HashBasedTable<?, ?, ?> table) {
- }
+ public static void deserialize(SerializationStreamReader reader, HashBasedTable<?, ?, ?> table) {}
public static HashBasedTable<Object, Object, Object> instantiate(SerializationStreamReader reader)
throws SerializationException {
diff --git a/guava-gwt/src/com/google/common/collect/HashMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/HashMultimap_CustomFieldSerializer.java
index 85611b1..d3ee4ee 100644
--- a/guava-gwt/src/com/google/common/collect/HashMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/HashMultimap_CustomFieldSerializer.java
@@ -22,24 +22,22 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of {@link HashMultimap}.
- *
+ *
* @author Jord Sonneveld
- *
+ *
*/
public class HashMultimap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader in,
- HashMultimap<?, ?> out) {
- }
+ public static void deserialize(SerializationStreamReader in, HashMultimap<?, ?> out) {}
- public static HashMultimap<Object, Object> instantiate(
- SerializationStreamReader in) throws SerializationException {
+ public static HashMultimap<Object, Object> instantiate(SerializationStreamReader in)
+ throws SerializationException {
return (HashMultimap<Object, Object>)
Multimap_CustomFieldSerializerBase.populate(in, HashMultimap.create());
}
- public static void serialize(SerializationStreamWriter out,
- HashMultimap<?, ?> multimap) throws SerializationException {
+ public static void serialize(SerializationStreamWriter out, HashMultimap<?, ?> multimap)
+ throws SerializationException {
Multimap_CustomFieldSerializerBase.serialize(out, multimap);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/HashMultiset_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/HashMultiset_CustomFieldSerializer.java
index ff18183..1244e1e 100644
--- a/guava-gwt/src/com/google/common/collect/HashMultiset_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/HashMultiset_CustomFieldSerializer.java
@@ -27,18 +27,16 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
*/
public class HashMultiset_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- HashMultiset<?> instance) {
- }
+ public static void deserialize(SerializationStreamReader reader, HashMultiset<?> instance) {}
- public static HashMultiset<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
- return (HashMultiset<Object>) Multiset_CustomFieldSerializerBase.populate(
- reader, HashMultiset.create());
+ public static HashMultiset<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
+ return (HashMultiset<Object>)
+ Multiset_CustomFieldSerializerBase.populate(reader, HashMultiset.create());
}
- public static void serialize(SerializationStreamWriter writer,
- HashMultiset<?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, HashMultiset<?> instance)
+ throws SerializationException {
Multiset_CustomFieldSerializerBase.serialize(writer, instance);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/ImmutableEntry_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ImmutableEntry_CustomFieldSerializer.java
index 821c33a..927a120 100644
--- a/guava-gwt/src/com/google/common/collect/ImmutableEntry_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ImmutableEntry_CustomFieldSerializer.java
@@ -28,19 +28,17 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
*/
public class ImmutableEntry_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- ImmutableEntry<?, ?> instance) {
- }
+ public static void deserialize(SerializationStreamReader reader, ImmutableEntry<?, ?> instance) {}
- public static ImmutableEntry<Object, Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static ImmutableEntry<Object, Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
Object key = reader.readObject();
Object value = reader.readObject();
return new ImmutableEntry<Object, Object>(key, value);
}
- public static void serialize(SerializationStreamWriter writer,
- ImmutableEntry<?, ?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, ImmutableEntry<?, ?> instance)
+ throws SerializationException {
writer.writeObject(instance.getKey());
writer.writeObject(instance.getValue());
}
diff --git a/guava-gwt/src/com/google/common/collect/ImmutableEnumMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ImmutableEnumMap_CustomFieldSerializer.java
index 868cb74..636364a 100644
--- a/guava-gwt/src/com/google/common/collect/ImmutableEnumMap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ImmutableEnumMap_CustomFieldSerializer.java
@@ -30,9 +30,8 @@ import java.util.Map;
*/
public class ImmutableEnumMap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- ImmutableEnumMap<?, ?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, ImmutableEnumMap<?, ?> instance) {}
public static <K extends Enum<K>, V> ImmutableEnumMap<?, ?> instantiate(
SerializationStreamReader reader) throws SerializationException {
@@ -46,9 +45,8 @@ public class ImmutableEnumMap_CustomFieldSerializer {
return (ImmutableEnumMap<?, ?>) Maps.immutableEnumMap(deserialized);
}
- public static void serialize(SerializationStreamWriter writer,
- ImmutableEnumMap<?, ?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, ImmutableEnumMap<?, ?> instance)
+ throws SerializationException {
Map_CustomFieldSerializerBase.serialize(writer, instance);
}
-
}
diff --git a/guava-gwt/src/com/google/common/collect/ImmutableEnumSet_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ImmutableEnumSet_CustomFieldSerializer.java
index 8b5a66d..e494a8f 100644
--- a/guava-gwt/src/com/google/common/collect/ImmutableEnumSet_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ImmutableEnumSet_CustomFieldSerializer.java
@@ -30,9 +30,7 @@ import java.util.List;
*/
public class ImmutableEnumSet_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- ImmutableEnumSet<?> instance) {
- }
+ public static void deserialize(SerializationStreamReader reader, ImmutableEnumSet<?> instance) {}
public static <E extends Enum<E>> ImmutableEnumSet<?> instantiate(
SerializationStreamReader reader) throws SerializationException {
@@ -46,9 +44,8 @@ public class ImmutableEnumSet_CustomFieldSerializer {
return (ImmutableEnumSet<?>) Sets.immutableEnumSet(deserialized);
}
- public static void serialize(SerializationStreamWriter writer,
- ImmutableEnumSet<?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, ImmutableEnumSet<?> instance)
+ throws SerializationException {
Collection_CustomFieldSerializerBase.serialize(writer, instance);
}
-
}
diff --git a/guava-gwt/src/com/google/common/collect/ImmutableListMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ImmutableListMultimap_CustomFieldSerializer.java
index 528ca3d..68a6176 100644
--- a/guava-gwt/src/com/google/common/collect/ImmutableListMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ImmutableListMultimap_CustomFieldSerializer.java
@@ -27,19 +27,18 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
*/
public class ImmutableListMultimap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- ImmutableListMultimap<?, ?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, ImmutableListMultimap<?, ?> instance) {}
- public static ImmutableListMultimap<Object, Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static ImmutableListMultimap<Object, Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
return (ImmutableListMultimap<Object, Object>)
- Multimap_CustomFieldSerializerBase.instantiate(
- reader, ImmutableListMultimap.builder());
+ Multimap_CustomFieldSerializerBase.instantiate(reader, ImmutableListMultimap.builder());
}
- public static void serialize(SerializationStreamWriter writer,
- ImmutableListMultimap<?, ?> instance) throws SerializationException {
+ public static void serialize(
+ SerializationStreamWriter writer, ImmutableListMultimap<?, ?> instance)
+ throws SerializationException {
Multimap_CustomFieldSerializerBase.serialize(writer, instance);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/ImmutableSetMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ImmutableSetMultimap_CustomFieldSerializer.java
index 4799c72..980c11b 100644
--- a/guava-gwt/src/com/google/common/collect/ImmutableSetMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ImmutableSetMultimap_CustomFieldSerializer.java
@@ -29,14 +29,13 @@ import java.util.Comparator;
*/
public class ImmutableSetMultimap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- ImmutableSetMultimap<?, ?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, ImmutableSetMultimap<?, ?> instance) {}
// Serialization type safety is at the caller's mercy.
@SuppressWarnings("unchecked")
- public static ImmutableSetMultimap<Object, Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static ImmutableSetMultimap<Object, Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
Comparator<Object> valueComparator = (Comparator<Object>) reader.readObject();
ImmutableSetMultimap.Builder<Object, Object> builder = ImmutableSetMultimap.builder();
if (valueComparator != null) {
@@ -46,8 +45,9 @@ public class ImmutableSetMultimap_CustomFieldSerializer {
Multimap_CustomFieldSerializerBase.instantiate(reader, builder);
}
- public static void serialize(SerializationStreamWriter writer,
- ImmutableSetMultimap<?, ?> instance) throws SerializationException {
+ public static void serialize(
+ SerializationStreamWriter writer, ImmutableSetMultimap<?, ?> instance)
+ throws SerializationException {
writer.writeObject(instance.valueComparator());
Multimap_CustomFieldSerializerBase.serialize(writer, instance);
}
diff --git a/guava-gwt/src/com/google/common/collect/ImmutableSortedMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ImmutableSortedMap_CustomFieldSerializer.java
index 70cf908..215ffa6 100644
--- a/guava-gwt/src/com/google/common/collect/ImmutableSortedMap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ImmutableSortedMap_CustomFieldSerializer.java
@@ -16,6 +16,10 @@
package com.google.common.collect;
+import com.google.gwt.user.client.rpc.SerializationException;
+import com.google.gwt.user.client.rpc.SerializationStreamReader;
+import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+
/**
* Even though {@link ImmutableSortedMap} cannot be instantiated, we still need a custom field
* serializer. TODO(cpovirk): why? Does it help if ensure that the GWT and non-GWT classes have the
@@ -23,4 +27,17 @@ package com.google.common.collect;
*
* @author Chris Povirk
*/
-public final class ImmutableSortedMap_CustomFieldSerializer {}
+public final class ImmutableSortedMap_CustomFieldSerializer {
+ public static void deserialize(
+ SerializationStreamReader reader, ImmutableSortedMap<?, ?> instance) {}
+
+ public static ImmutableSortedMap<?, ?> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
+ return ImmutableSortedMap_CustomFieldSerializerBase.instantiate(reader);
+ }
+
+ public static void serialize(SerializationStreamWriter writer, ImmutableSortedMap<?, ?> instance)
+ throws SerializationException {
+ ImmutableSortedMap_CustomFieldSerializerBase.serialize(writer, instance);
+ }
+}
diff --git a/guava-gwt/src/com/google/common/collect/LexicographicalOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/LexicographicalOrdering_CustomFieldSerializer.java
index 597207d..94d490b 100644
--- a/guava-gwt/src/com/google/common/collect/LexicographicalOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/LexicographicalOrdering_CustomFieldSerializer.java
@@ -23,24 +23,23 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of {@link
* LexicographicalOrdering}.
- *
+ *
* @author Chris Povirk
*/
public class LexicographicalOrdering_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- LexicographicalOrdering<?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, LexicographicalOrdering<?> instance) {}
@SuppressWarnings("unchecked") // deserialization is unsafe
- public static LexicographicalOrdering<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
- return new LexicographicalOrdering<Object>(
- (Ordering<Object>) reader.readObject());
+ public static LexicographicalOrdering<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
+ return new LexicographicalOrdering<Object>((Ordering<Object>) reader.readObject());
}
- public static void serialize(SerializationStreamWriter writer,
- LexicographicalOrdering<?> instance) throws SerializationException {
+ public static void serialize(
+ SerializationStreamWriter writer, LexicographicalOrdering<?> instance)
+ throws SerializationException {
writer.writeObject(instance.elementOrder);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/LinkedHashMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/LinkedHashMultimap_CustomFieldSerializer.java
index a0a9163..6aa24e9 100644
--- a/guava-gwt/src/com/google/common/collect/LinkedHashMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/LinkedHashMultimap_CustomFieldSerializer.java
@@ -31,18 +31,14 @@ import java.util.Map;
*/
public class LinkedHashMultimap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader in,
- LinkedHashMultimap<?, ?> out) {
- }
+ public static void deserialize(SerializationStreamReader in, LinkedHashMultimap<?, ?> out) {}
- public static LinkedHashMultimap<Object, Object> instantiate(
- SerializationStreamReader stream) throws SerializationException {
+ public static LinkedHashMultimap<Object, Object> instantiate(SerializationStreamReader stream)
+ throws SerializationException {
LinkedHashMultimap<Object, Object> multimap = LinkedHashMultimap.create();
- multimap.valueSetCapacity = stream.readInt();
int distinctKeys = stream.readInt();
- Map<Object, Collection<Object>> map =
- new LinkedHashMap<Object, Collection<Object>>(Maps.capacity(distinctKeys));
+ Map<Object, Collection<Object>> map = new LinkedHashMap<Object, Collection<Object>>();
for (int i = 0; i < distinctKeys; i++) {
Object key = stream.readObject();
map.put(key, multimap.createCollection(key));
@@ -58,9 +54,8 @@ public class LinkedHashMultimap_CustomFieldSerializer {
return multimap;
}
- public static void serialize(SerializationStreamWriter stream,
- LinkedHashMultimap<?, ?> multimap) throws SerializationException {
- stream.writeInt(multimap.valueSetCapacity);
+ public static void serialize(SerializationStreamWriter stream, LinkedHashMultimap<?, ?> multimap)
+ throws SerializationException {
stream.writeInt(multimap.keySet().size());
for (Object key : multimap.keySet()) {
stream.writeObject(key);
diff --git a/guava-gwt/src/com/google/common/collect/LinkedHashMultiset_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/LinkedHashMultiset_CustomFieldSerializer.java
index 77cc126..934bc69 100644
--- a/guava-gwt/src/com/google/common/collect/LinkedHashMultiset_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/LinkedHashMultiset_CustomFieldSerializer.java
@@ -27,19 +27,17 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
*/
public class LinkedHashMultiset_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- LinkedHashMultiset<?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, LinkedHashMultiset<?> instance) {}
- public static LinkedHashMultiset<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static LinkedHashMultiset<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
return (LinkedHashMultiset<Object>)
- Multiset_CustomFieldSerializerBase.populate(
- reader, LinkedHashMultiset.create());
+ Multiset_CustomFieldSerializerBase.populate(reader, LinkedHashMultiset.create());
}
- public static void serialize(SerializationStreamWriter writer,
- LinkedHashMultiset<?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, LinkedHashMultiset<?> instance)
+ throws SerializationException {
Multiset_CustomFieldSerializerBase.serialize(writer, instance);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/LinkedListMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/LinkedListMultimap_CustomFieldSerializer.java
index 28d3327..736076c 100644
--- a/guava-gwt/src/com/google/common/collect/LinkedListMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/LinkedListMultimap_CustomFieldSerializer.java
@@ -24,17 +24,15 @@ import java.util.Map;
/**
* This class implements the GWT serialization of {@link LinkedListMultimap}.
- *
+ *
* @author Chris Povirk
*/
public class LinkedListMultimap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader in,
- LinkedListMultimap<?, ?> out) {
- }
+ public static void deserialize(SerializationStreamReader in, LinkedListMultimap<?, ?> out) {}
- public static LinkedListMultimap<Object, Object> instantiate(
- SerializationStreamReader in) throws SerializationException {
+ public static LinkedListMultimap<Object, Object> instantiate(SerializationStreamReader in)
+ throws SerializationException {
LinkedListMultimap<Object, Object> multimap = LinkedListMultimap.create();
int size = in.readInt();
for (int i = 0; i < size; i++) {
@@ -45,8 +43,8 @@ public class LinkedListMultimap_CustomFieldSerializer {
return multimap;
}
- public static void serialize(SerializationStreamWriter out,
- LinkedListMultimap<?, ?> multimap) throws SerializationException {
+ public static void serialize(SerializationStreamWriter out, LinkedListMultimap<?, ?> multimap)
+ throws SerializationException {
out.writeInt(multimap.size());
for (Map.Entry<?, ?> entry : multimap.entries()) {
out.writeObject(entry.getKey());
diff --git a/guava-gwt/src/com/google/common/collect/Multimap_CustomFieldSerializerBase.java b/guava-gwt/src/com/google/common/collect/Multimap_CustomFieldSerializerBase.java
index 5e60a45..4992830 100644
--- a/guava-gwt/src/com/google/common/collect/Multimap_CustomFieldSerializerBase.java
+++ b/guava-gwt/src/com/google/common/collect/Multimap_CustomFieldSerializerBase.java
@@ -35,8 +35,7 @@ import java.util.Map;
public final class Multimap_CustomFieldSerializerBase {
static ImmutableMultimap<Object, Object> instantiate(
- SerializationStreamReader reader,
- ImmutableMultimap.Builder<Object, Object> builder)
+ SerializationStreamReader reader, ImmutableMultimap.Builder<Object, Object> builder)
throws SerializationException {
int keyCount = reader.readInt();
for (int i = 0; i < keyCount; ++i) {
@@ -65,12 +64,10 @@ public final class Multimap_CustomFieldSerializerBase {
return multimap;
}
- public static void serialize(
- SerializationStreamWriter writer, Multimap<?, ?> instance)
+ public static void serialize(SerializationStreamWriter writer, Multimap<?, ?> instance)
throws SerializationException {
writer.writeInt(instance.asMap().size());
- for (Map.Entry<?, ? extends Collection<?>> entry
- : instance.asMap().entrySet()) {
+ for (Map.Entry<?, ? extends Collection<?>> entry : instance.asMap().entrySet()) {
writer.writeObject(entry.getKey());
writer.writeInt(entry.getValue().size());
for (Object value : entry.getValue()) {
diff --git a/guava-gwt/src/com/google/common/collect/Multiset_CustomFieldSerializerBase.java b/guava-gwt/src/com/google/common/collect/Multiset_CustomFieldSerializerBase.java
index 7c44bba..f740a60 100644
--- a/guava-gwt/src/com/google/common/collect/Multiset_CustomFieldSerializerBase.java
+++ b/guava-gwt/src/com/google/common/collect/Multiset_CustomFieldSerializerBase.java
@@ -25,13 +25,12 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
* field serializers. Serializers should delegate to
* {@link #serialize(SerializationStreamWriter, Multiset)} and
* {@link #populate(SerializationStreamReader, Multiset)}.
- *
+ *
* @author Chris Povirk
*/
final class Multiset_CustomFieldSerializerBase {
- static Multiset<Object> populate(
- SerializationStreamReader reader, Multiset<Object> multiset)
+ static Multiset<Object> populate(SerializationStreamReader reader, Multiset<Object> multiset)
throws SerializationException {
int distinctElements = reader.readInt();
for (int i = 0; i < distinctElements; i++) {
@@ -50,7 +49,7 @@ final class Multiset_CustomFieldSerializerBase {
writer.writeObject(entry.getElement());
writer.writeInt(entry.getCount());
}
- }
+ }
private Multiset_CustomFieldSerializerBase() {}
}
diff --git a/guava-gwt/src/com/google/common/collect/NaturalOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/NaturalOrdering_CustomFieldSerializer.java
index 9e57fff..e75655c 100644
--- a/guava-gwt/src/com/google/common/collect/NaturalOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/NaturalOrdering_CustomFieldSerializer.java
@@ -21,21 +21,16 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of {@link NaturalOrdering}.
- *
+ *
* @author Chris Povirk
*/
public class NaturalOrdering_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- NaturalOrdering instance) {
- }
+ public static void deserialize(SerializationStreamReader reader, NaturalOrdering instance) {}
- public static NaturalOrdering instantiate(
- SerializationStreamReader reader) {
+ public static NaturalOrdering instantiate(SerializationStreamReader reader) {
return NaturalOrdering.INSTANCE;
}
- public static void serialize(SerializationStreamWriter writer,
- NaturalOrdering instance) {
- }
+ public static void serialize(SerializationStreamWriter writer, NaturalOrdering instance) {}
}
diff --git a/guava-gwt/src/com/google/common/collect/NullsFirstOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/NullsFirstOrdering_CustomFieldSerializer.java
index d1a0a71..9b27b57 100644
--- a/guava-gwt/src/com/google/common/collect/NullsFirstOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/NullsFirstOrdering_CustomFieldSerializer.java
@@ -22,24 +22,22 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of {@link NullsFirstOrdering}.
- *
+ *
* @author Chris Povirk
*/
public class NullsFirstOrdering_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- NullsFirstOrdering<?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, NullsFirstOrdering<?> instance) {}
@SuppressWarnings("unchecked") // deserialization is unsafe
- public static NullsFirstOrdering<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
- return new NullsFirstOrdering<Object>(
- (Ordering<Object>) reader.readObject());
+ public static NullsFirstOrdering<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
+ return new NullsFirstOrdering<Object>((Ordering<Object>) reader.readObject());
}
- public static void serialize(SerializationStreamWriter writer,
- NullsFirstOrdering<?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, NullsFirstOrdering<?> instance)
+ throws SerializationException {
writer.writeObject(instance.ordering);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/NullsLastOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/NullsLastOrdering_CustomFieldSerializer.java
index 0c306e0..965d75f 100644
--- a/guava-gwt/src/com/google/common/collect/NullsLastOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/NullsLastOrdering_CustomFieldSerializer.java
@@ -22,24 +22,21 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of {@link NullsLastOrdering}.
- *
+ *
* @author Chris Povirk
*/
public class NullsLastOrdering_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- NullsLastOrdering<?> instance) {
- }
+ public static void deserialize(SerializationStreamReader reader, NullsLastOrdering<?> instance) {}
@SuppressWarnings("unchecked") // deserialization is unsafe
- public static NullsLastOrdering<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
- return new NullsLastOrdering<Object>(
- (Ordering<Object>) reader.readObject());
+ public static NullsLastOrdering<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
+ return new NullsLastOrdering<Object>((Ordering<Object>) reader.readObject());
}
- public static void serialize(SerializationStreamWriter writer,
- NullsLastOrdering<?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, NullsLastOrdering<?> instance)
+ throws SerializationException {
writer.writeObject(instance.ordering);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableAsList_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableAsList_CustomFieldSerializer.java
index f41b8cf..7d2d555 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableAsList_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableAsList_CustomFieldSerializer.java
@@ -30,20 +30,19 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
@GwtCompatible(emulated = true)
public class RegularImmutableAsList_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- RegularImmutableAsList<?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, RegularImmutableAsList<?> instance) {}
- public static RegularImmutableAsList<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static RegularImmutableAsList<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
@SuppressWarnings("unchecked") // serialization is necessarily type unsafe
ImmutableCollection<Object> delegateCollection = (ImmutableCollection) reader.readObject();
ImmutableList<?> delegateList = (ImmutableList<?>) reader.readObject();
return new RegularImmutableAsList<Object>(delegateCollection, delegateList);
}
- public static void serialize(SerializationStreamWriter writer,
- RegularImmutableAsList<?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, RegularImmutableAsList<?> instance)
+ throws SerializationException {
writer.writeObject(instance.delegateCollection());
writer.writeObject(instance.delegateList());
}
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableBiMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableBiMap_CustomFieldSerializer.java
index 4d68331..af0d437 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableBiMap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableBiMap_CustomFieldSerializer.java
@@ -27,16 +27,15 @@ import java.util.Map;
/**
* This class implements the GWT serialization of
* {@link RegularImmutableBiMap}.
- *
+ *
* @author Chris Povirk
*/
public class RegularImmutableBiMap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- RegularImmutableBiMap<?, ?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, RegularImmutableBiMap<?, ?> instance) {}
- public static RegularImmutableBiMap<Object, Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static RegularImmutableBiMap<Object, Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
Map<Object, Object> entries = new LinkedHashMap<Object, Object>();
Map_CustomFieldSerializerBase.deserialize(reader, entries);
/*
@@ -45,12 +44,12 @@ public class RegularImmutableBiMap_CustomFieldSerializer {
* always have one or more elements, ImmutableBiMap.copyOf always return a
* RegularImmutableBiMap back.
*/
- return
- (RegularImmutableBiMap<Object, Object>) ImmutableBiMap.copyOf(entries);
+ return (RegularImmutableBiMap<Object, Object>) ImmutableBiMap.copyOf(entries);
}
- public static void serialize(SerializationStreamWriter writer,
- RegularImmutableBiMap<?, ?> instance) throws SerializationException {
+ public static void serialize(
+ SerializationStreamWriter writer, RegularImmutableBiMap<?, ?> instance)
+ throws SerializationException {
Map_CustomFieldSerializerBase.serialize(writer, instance);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableList_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableList_CustomFieldSerializer.java
index 9dd652c..4f70472 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableList_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableList_CustomFieldSerializer.java
@@ -32,12 +32,11 @@ import java.util.List;
*/
public class RegularImmutableList_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- RegularImmutableList<?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, RegularImmutableList<?> instance) {}
- public static RegularImmutableList<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static RegularImmutableList<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
List<Object> elements = new ArrayList<Object>();
Collection_CustomFieldSerializerBase.deserialize(reader, elements);
/*
@@ -49,8 +48,8 @@ public class RegularImmutableList_CustomFieldSerializer {
return (RegularImmutableList<Object>) ImmutableList.copyOf(elements);
}
- public static void serialize(SerializationStreamWriter writer,
- RegularImmutableList<?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, RegularImmutableList<?> instance)
+ throws SerializationException {
Collection_CustomFieldSerializerBase.serialize(writer, instance);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableMap_CustomFieldSerializer.java
index d9e1748..8b466a7 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableMap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableMap_CustomFieldSerializer.java
@@ -31,12 +31,11 @@ import java.util.Map;
*/
public class RegularImmutableMap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- RegularImmutableMap<?, ?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, RegularImmutableMap<?, ?> instance) {}
- public static RegularImmutableMap<Object, Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static RegularImmutableMap<Object, Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
Map<Object, Object> entries = new LinkedHashMap<Object, Object>();
Map_CustomFieldSerializerBase.deserialize(reader, entries);
/*
@@ -48,8 +47,8 @@ public class RegularImmutableMap_CustomFieldSerializer {
return (RegularImmutableMap<Object, Object>) ImmutableMap.copyOf(entries);
}
- public static void serialize(SerializationStreamWriter writer,
- RegularImmutableMap<?, ?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, RegularImmutableMap<?, ?> instance)
+ throws SerializationException {
Map_CustomFieldSerializerBase.serialize(writer, instance);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableMultiset_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableMultiset_CustomFieldSerializer.java
index 3c04929..eec62c4 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableMultiset_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableMultiset_CustomFieldSerializer.java
@@ -25,16 +25,15 @@ import java.util.List;
/**
* This class implements the GWT serialization of {@link RegularImmutableMultiset}.
- *
+ *
* @author Louis Wasserman
*/
public class RegularImmutableMultiset_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- RegularImmutableMultiset<?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, RegularImmutableMultiset<?> instance) {}
- public static RegularImmutableMultiset<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static RegularImmutableMultiset<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
List<Object> elements = Lists.newArrayList();
Collection_CustomFieldSerializerBase.deserialize(reader, elements);
/*
@@ -43,12 +42,12 @@ public class RegularImmutableMultiset_CustomFieldSerializer {
* RegularImmutableMultiset always have one or more elements,
* ImmutableMultiset.copyOf always return a RegularImmutableMultiset back.
*/
- return (RegularImmutableMultiset<Object>) ImmutableMultiset
- .copyOf(elements);
+ return (RegularImmutableMultiset<Object>) ImmutableMultiset.copyOf(elements);
}
- public static void serialize(SerializationStreamWriter writer,
- RegularImmutableMultiset<?> instance) throws SerializationException {
+ public static void serialize(
+ SerializationStreamWriter writer, RegularImmutableMultiset<?> instance)
+ throws SerializationException {
Collection_CustomFieldSerializerBase.serialize(writer, instance);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableSet_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableSet_CustomFieldSerializer.java
index 5908935..dc8f88b 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableSet_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableSet_CustomFieldSerializer.java
@@ -30,12 +30,11 @@ import java.util.List;
*/
public class RegularImmutableSet_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- RegularImmutableSet<?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, RegularImmutableSet<?> instance) {}
- public static RegularImmutableSet<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static RegularImmutableSet<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
List<Object> elements = Lists.newArrayList();
Collection_CustomFieldSerializerBase.deserialize(reader, elements);
/*
@@ -47,8 +46,8 @@ public class RegularImmutableSet_CustomFieldSerializer {
return (RegularImmutableSet<Object>) ImmutableSet.copyOf(elements);
}
- public static void serialize(SerializationStreamWriter writer,
- RegularImmutableSet<?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, RegularImmutableSet<?> instance)
+ throws SerializationException {
Collection_CustomFieldSerializerBase.serialize(writer, instance);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableSortedMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableSortedMap_CustomFieldSerializer.java
deleted file mode 100644
index 9f64e37..0000000
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableSortedMap_CustomFieldSerializer.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2009 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.collect;
-
-import com.google.gwt.user.client.rpc.SerializationException;
-import com.google.gwt.user.client.rpc.SerializationStreamReader;
-import com.google.gwt.user.client.rpc.SerializationStreamWriter;
-
-/**
- * This class implements the GWT serialization of {@link RegularImmutableSortedMap}.
- *
- * @author Chris Povirk
- */
-public class RegularImmutableSortedMap_CustomFieldSerializer {
- public static void deserialize(
- SerializationStreamReader reader, RegularImmutableSortedMap<?, ?> instance) {
- }
-
- public static RegularImmutableSortedMap<?, ?> instantiate(
- SerializationStreamReader reader) throws SerializationException {
- return (RegularImmutableSortedMap<?, ?>)
- ImmutableSortedMap_CustomFieldSerializerBase.instantiate(reader);
- }
-
- public static void serialize(
- SerializationStreamWriter writer, RegularImmutableSortedMap<?, ?> instance)
- throws SerializationException {
- ImmutableSortedMap_CustomFieldSerializerBase.serialize(writer, instance);
- }
-}
diff --git a/guava-gwt/src/com/google/common/collect/RegularImmutableSortedSet_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/RegularImmutableSortedSet_CustomFieldSerializer.java
index d3018c3..b489737 100644
--- a/guava-gwt/src/com/google/common/collect/RegularImmutableSortedSet_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/RegularImmutableSortedSet_CustomFieldSerializer.java
@@ -28,16 +28,15 @@ import java.util.List;
/**
* This class implements the GWT serialization of
* {@link RegularImmutableSortedSet}.
- *
+ *
* @author Chris Povirk
*/
public class RegularImmutableSortedSet_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- RegularImmutableSortedSet<?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, RegularImmutableSortedSet<?> instance) {}
- public static RegularImmutableSortedSet<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static RegularImmutableSortedSet<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
/*
* Nothing we can do, but we're already assuming the serialized form is
* correctly typed, anyway.
@@ -53,12 +52,12 @@ public class RegularImmutableSortedSet_CustomFieldSerializer {
* RegularImmutableSortedSet always have one or more elements,
* ImmutableSortedSet.copyOf always return a RegularImmutableSortedSet back.
*/
- return (RegularImmutableSortedSet<Object>)
- ImmutableSortedSet.copyOf(comparator, elements);
+ return (RegularImmutableSortedSet<Object>) ImmutableSortedSet.copyOf(comparator, elements);
}
- public static void serialize(SerializationStreamWriter writer,
- RegularImmutableSortedSet<?> instance) throws SerializationException {
+ public static void serialize(
+ SerializationStreamWriter writer, RegularImmutableSortedSet<?> instance)
+ throws SerializationException {
writer.writeObject(instance.comparator());
Collection_CustomFieldSerializerBase.serialize(writer, instance);
diff --git a/guava-gwt/src/com/google/common/collect/ReverseNaturalOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ReverseNaturalOrdering_CustomFieldSerializer.java
index b3744f5..fab8648 100644
--- a/guava-gwt/src/com/google/common/collect/ReverseNaturalOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ReverseNaturalOrdering_CustomFieldSerializer.java
@@ -22,21 +22,17 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of
* {@link ReverseNaturalOrdering}.
- *
+ *
* @author Chris Povirk
*/
public class ReverseNaturalOrdering_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- ReverseNaturalOrdering instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, ReverseNaturalOrdering instance) {}
- public static ReverseNaturalOrdering instantiate(
- SerializationStreamReader reader) {
+ public static ReverseNaturalOrdering instantiate(SerializationStreamReader reader) {
return ReverseNaturalOrdering.INSTANCE;
}
- public static void serialize(SerializationStreamWriter writer,
- ReverseNaturalOrdering instance) {
- }
+ public static void serialize(SerializationStreamWriter writer, ReverseNaturalOrdering instance) {}
}
diff --git a/guava-gwt/src/com/google/common/collect/ReverseOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/ReverseOrdering_CustomFieldSerializer.java
index 67711bd..9cf4a6e 100644
--- a/guava-gwt/src/com/google/common/collect/ReverseOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/ReverseOrdering_CustomFieldSerializer.java
@@ -22,24 +22,21 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of {@link ReverseOrdering}.
- *
+ *
* @author Chris Povirk
*/
public class ReverseOrdering_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- ReverseOrdering<?> instance) {
- }
+ public static void deserialize(SerializationStreamReader reader, ReverseOrdering<?> instance) {}
@SuppressWarnings("unchecked") // deserialization is unsafe
- public static ReverseOrdering<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
- return new ReverseOrdering<Object>(
- (Ordering<Object>) reader.readObject());
+ public static ReverseOrdering<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
+ return new ReverseOrdering<Object>((Ordering<Object>) reader.readObject());
}
- public static void serialize(SerializationStreamWriter writer,
- ReverseOrdering<?> instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, ReverseOrdering<?> instance)
+ throws SerializationException {
writer.writeObject(instance.forwardOrder);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/SingletonImmutableBiMap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/SingletonImmutableBiMap_CustomFieldSerializer.java
index 7b87633..c5a8c7c 100644
--- a/guava-gwt/src/com/google/common/collect/SingletonImmutableBiMap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/SingletonImmutableBiMap_CustomFieldSerializer.java
@@ -29,9 +29,8 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
*/
public class SingletonImmutableBiMap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- SingletonImmutableBiMap<?, ?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, SingletonImmutableBiMap<?, ?> instance) {}
public static SingletonImmutableBiMap<Object, Object> instantiate(
SerializationStreamReader reader) throws SerializationException {
@@ -39,9 +38,10 @@ public class SingletonImmutableBiMap_CustomFieldSerializer {
Object value = checkNotNull(reader.readObject());
return new SingletonImmutableBiMap<Object, Object>(key, value);
}
-
- public static void serialize(SerializationStreamWriter writer,
- SingletonImmutableBiMap<?, ?> instance) throws SerializationException {
+
+ public static void serialize(
+ SerializationStreamWriter writer, SingletonImmutableBiMap<?, ?> instance)
+ throws SerializationException {
writer.writeObject(instance.singleKey);
writer.writeObject(instance.singleValue);
}
diff --git a/guava-gwt/src/com/google/common/collect/SingletonImmutableList_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/SingletonImmutableList_CustomFieldSerializer.java
index 712e275..ef1a2cf 100644
--- a/guava-gwt/src/com/google/common/collect/SingletonImmutableList_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/SingletonImmutableList_CustomFieldSerializer.java
@@ -28,18 +28,17 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
*/
public class SingletonImmutableList_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- SingletonImmutableList<?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, SingletonImmutableList<?> instance) {}
- public static SingletonImmutableList<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static SingletonImmutableList<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
Object element = reader.readObject();
return new SingletonImmutableList<Object>(element);
}
-
- public static void serialize(SerializationStreamWriter writer,
- SingletonImmutableList<?> instance) throws SerializationException {
+
+ public static void serialize(SerializationStreamWriter writer, SingletonImmutableList<?> instance)
+ throws SerializationException {
writer.writeObject(instance.element);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/SingletonImmutableSet_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/SingletonImmutableSet_CustomFieldSerializer.java
index bfa9d42..b389fdd 100644
--- a/guava-gwt/src/com/google/common/collect/SingletonImmutableSet_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/SingletonImmutableSet_CustomFieldSerializer.java
@@ -27,18 +27,17 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
*/
public class SingletonImmutableSet_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- SingletonImmutableSet<?> instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, SingletonImmutableSet<?> instance) {}
- public static SingletonImmutableSet<Object> instantiate(
- SerializationStreamReader reader) throws SerializationException {
+ public static SingletonImmutableSet<Object> instantiate(SerializationStreamReader reader)
+ throws SerializationException {
Object element = reader.readObject();
return new SingletonImmutableSet<Object>(element);
}
-
- public static void serialize(SerializationStreamWriter writer,
- SingletonImmutableSet<?> instance) throws SerializationException {
+
+ public static void serialize(SerializationStreamWriter writer, SingletonImmutableSet<?> instance)
+ throws SerializationException {
writer.writeObject(instance.element);
}
}
diff --git a/guava-gwt/src/com/google/common/collect/SingletonImmutableTable_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/SingletonImmutableTable_CustomFieldSerializer.java
index a156247..9bc44ac 100644
--- a/guava-gwt/src/com/google/common/collect/SingletonImmutableTable_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/SingletonImmutableTable_CustomFieldSerializer.java
@@ -25,8 +25,7 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
*/
public class SingletonImmutableTable_CustomFieldSerializer {
public static void deserialize(
- SerializationStreamReader reader, SingletonImmutableTable<?, ?, ?> instance) {
- }
+ SerializationStreamReader reader, SingletonImmutableTable<?, ?, ?> instance) {}
public static SingletonImmutableTable<Object, Object, Object> instantiate(
SerializationStreamReader reader) throws SerializationException {
diff --git a/guava-gwt/src/com/google/common/collect/SparseImmutableTable_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/SparseImmutableTable_CustomFieldSerializer.java
index 94f6a13..571ddd1 100644
--- a/guava-gwt/src/com/google/common/collect/SparseImmutableTable_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/SparseImmutableTable_CustomFieldSerializer.java
@@ -25,8 +25,7 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
*/
public class SparseImmutableTable_CustomFieldSerializer {
public static void deserialize(
- SerializationStreamReader reader, SparseImmutableTable<?, ?, ?> instance) {
- }
+ SerializationStreamReader reader, SparseImmutableTable<?, ?, ?> instance) {}
public static SparseImmutableTable<Object, Object, Object> instantiate(
SerializationStreamReader reader) throws SerializationException {
diff --git a/guava-gwt/src/com/google/common/collect/TreeBasedTable_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/TreeBasedTable_CustomFieldSerializer.java
index 332b453..5a211ea 100644
--- a/guava-gwt/src/com/google/common/collect/TreeBasedTable_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/TreeBasedTable_CustomFieldSerializer.java
@@ -26,17 +26,14 @@ import java.util.Comparator;
* @author Hayward Chan
*/
public class TreeBasedTable_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader, TreeBasedTable<?, ?, ?> table) {
- }
+ public static void deserialize(SerializationStreamReader reader, TreeBasedTable<?, ?, ?> table) {}
public static TreeBasedTable<Object, Object, Object> instantiate(SerializationStreamReader reader)
throws SerializationException {
@SuppressWarnings("unchecked") // The comparator isn't used statically.
- Comparator<Object> rowComparator
- = (Comparator<Object>) reader.readObject();
+ Comparator<Object> rowComparator = (Comparator<Object>) reader.readObject();
@SuppressWarnings("unchecked") // The comparator isn't used statically.
- Comparator<Object> columnComparator
- = (Comparator<Object>) reader.readObject();
+ Comparator<Object> columnComparator = (Comparator<Object>) reader.readObject();
TreeBasedTable<Object, Object, Object> table =
TreeBasedTable.create(rowComparator, columnComparator);
diff --git a/guava-gwt/src/com/google/common/collect/TreeMultimap_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/TreeMultimap_CustomFieldSerializer.java
index 22db170..a9b0be4 100644
--- a/guava-gwt/src/com/google/common/collect/TreeMultimap_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/TreeMultimap_CustomFieldSerializer.java
@@ -29,13 +29,11 @@ import java.util.Comparator;
*/
public class TreeMultimap_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader in,
- TreeMultimap<?, ?> out) {
- }
+ public static void deserialize(SerializationStreamReader in, TreeMultimap<?, ?> out) {}
@SuppressWarnings("unchecked")
- public static TreeMultimap<Object, Object> instantiate(
- SerializationStreamReader in) throws SerializationException {
+ public static TreeMultimap<Object, Object> instantiate(SerializationStreamReader in)
+ throws SerializationException {
Comparator<Object> keyComparator = (Comparator<Object>) in.readObject();
Comparator<Object> valueComparator = (Comparator<Object>) in.readObject();
@@ -44,8 +42,8 @@ public class TreeMultimap_CustomFieldSerializer {
in, TreeMultimap.create(keyComparator, valueComparator));
}
- public static void serialize(SerializationStreamWriter out,
- TreeMultimap<?, ?> multimap) throws SerializationException {
+ public static void serialize(SerializationStreamWriter out, TreeMultimap<?, ?> multimap)
+ throws SerializationException {
out.writeObject(multimap.keyComparator());
out.writeObject(multimap.valueComparator());
Multimap_CustomFieldSerializerBase.serialize(out, multimap);
diff --git a/guava-gwt/src/com/google/common/collect/UsingToStringOrdering_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/collect/UsingToStringOrdering_CustomFieldSerializer.java
index dacf0c2..54a9e15 100644
--- a/guava-gwt/src/com/google/common/collect/UsingToStringOrdering_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/collect/UsingToStringOrdering_CustomFieldSerializer.java
@@ -21,21 +21,17 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
/**
* This class implements the GWT serialization of {@link UsingToStringOrdering}.
- *
+ *
* @author Chris Povirk
*/
public class UsingToStringOrdering_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- UsingToStringOrdering instance) {
- }
+ public static void deserialize(
+ SerializationStreamReader reader, UsingToStringOrdering instance) {}
- public static UsingToStringOrdering instantiate(
- SerializationStreamReader reader) {
+ public static UsingToStringOrdering instantiate(SerializationStreamReader reader) {
return UsingToStringOrdering.INSTANCE;
}
- public static void serialize(SerializationStreamWriter writer,
- UsingToStringOrdering instance) {
- }
+ public static void serialize(SerializationStreamWriter writer, UsingToStringOrdering instance) {}
}
diff --git a/guava-gwt/src/com/google/common/net/Net.gwt.xml b/guava-gwt/src/com/google/common/net/Net.gwt.xml
index 12a73fe..4d0a3c4 100644
--- a/guava-gwt/src/com/google/common/net/Net.gwt.xml
+++ b/guava-gwt/src/com/google/common/net/Net.gwt.xml
@@ -27,7 +27,7 @@
<inherits name="java.nio.charset.Charset"/>
<inherits name="com.google.thirdparty.publicsuffix.PublicSuffixPatterns"/>
-
+
<inherits name="com.google.gwt.core.Core"/>
</module>
diff --git a/guava-gwt/src/com/google/common/primitives/UnsignedLong_CustomFieldSerializer.java b/guava-gwt/src/com/google/common/primitives/UnsignedLong_CustomFieldSerializer.java
index 732730e..7908c64 100644
--- a/guava-gwt/src/com/google/common/primitives/UnsignedLong_CustomFieldSerializer.java
+++ b/guava-gwt/src/com/google/common/primitives/UnsignedLong_CustomFieldSerializer.java
@@ -18,22 +18,24 @@ import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+import javax.annotation.CheckReturnValue;
+
/**
* This class implements the GWT serialization of {@code UnsignedLong}.
*
* @author Louis Wasserman
*/
+ at CheckReturnValue
public class UnsignedLong_CustomFieldSerializer {
- public static void deserialize(SerializationStreamReader reader,
- UnsignedLong instance) {}
+ public static void deserialize(SerializationStreamReader reader, UnsignedLong instance) {}
public static UnsignedLong instantiate(SerializationStreamReader reader)
throws SerializationException {
return UnsignedLong.fromLongBits(reader.readLong());
}
- public static void serialize(SerializationStreamWriter writer,
- UnsignedLong instance) throws SerializationException {
+ public static void serialize(SerializationStreamWriter writer, UnsignedLong instance)
+ throws SerializationException {
writer.writeLong(instance.longValue());
}
}
diff --git a/guava-gwt/src/com/google/common/util/concurrent/Concurrent.gwt.xml b/guava-gwt/src/com/google/common/util/concurrent/Concurrent.gwt.xml
index e3ce2b7..7c2932c 100644
--- a/guava-gwt/src/com/google/common/util/concurrent/Concurrent.gwt.xml
+++ b/guava-gwt/src/com/google/common/util/concurrent/Concurrent.gwt.xml
@@ -19,7 +19,9 @@
<inherits name="com.google.common.base.Base"/>
<inherits name="com.google.common.collect.Collect"/>
-
+
+ <inherits name="java.util.Util"/>
+
<inherits name="com.google.gwt.core.Core"/>
</module>
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/CharMatcherTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/CharMatcherTest.java
index 55b659f..2099a1d 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/CharMatcherTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/CharMatcherTest.java
@@ -16,14 +16,14 @@
package com.google.common.base;
-import static com.google.common.base.CharMatcher.BREAKING_WHITESPACE;
-import static com.google.common.base.CharMatcher.WHITESPACE;
import static com.google.common.base.CharMatcher.anyOf;
+import static com.google.common.base.CharMatcher.breakingWhitespace;
import static com.google.common.base.CharMatcher.forPredicate;
import static com.google.common.base.CharMatcher.inRange;
import static com.google.common.base.CharMatcher.is;
import static com.google.common.base.CharMatcher.isNot;
import static com.google.common.base.CharMatcher.noneOf;
+import static com.google.common.base.CharMatcher.whitespace;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Sets;
@@ -56,14 +56,14 @@ public class CharMatcherTest extends TestCase {
// we're lucky enough that these do pass, it saves us from having to write
// more excruciating tests! Hooray!
- assertSame(CharMatcher.ANY, CharMatcher.NONE.negate());
- assertSame(CharMatcher.NONE, CharMatcher.ANY.negate());
+ assertSame(CharMatcher.any(), CharMatcher.none().negate());
+ assertSame(CharMatcher.none(), CharMatcher.any().negate());
- assertSame(WHATEVER, CharMatcher.ANY.and(WHATEVER));
- assertSame(CharMatcher.ANY, CharMatcher.ANY.or(WHATEVER));
+ assertSame(WHATEVER, CharMatcher.any().and(WHATEVER));
+ assertSame(CharMatcher.any(), CharMatcher.any().or(WHATEVER));
- assertSame(CharMatcher.NONE, CharMatcher.NONE.and(WHATEVER));
- assertSame(WHATEVER, CharMatcher.NONE.or(WHATEVER));
+ assertSame(CharMatcher.none(), CharMatcher.none().and(WHATEVER));
+ assertSame(WHATEVER, CharMatcher.none().or(WHATEVER));
}
// The rest of the behavior of ANY and DEFAULT will be covered in the tests for
@@ -71,8 +71,8 @@ public class CharMatcherTest extends TestCase {
public void testWhitespaceBreakingWhitespaceSubset() throws Exception {
for (int c = 0; c <= Character.MAX_VALUE; c++) {
- if (BREAKING_WHITESPACE.apply((char) c)) {
- assertTrue(Integer.toHexString(c), WHITESPACE.apply((char) c));
+ if (breakingWhitespace().matches((char) c)) {
+ assertTrue(Integer.toHexString(c), whitespace().matches((char) c));
}
}
}
@@ -91,8 +91,8 @@ public class CharMatcherTest extends TestCase {
// do borders on absurd overkill. Better safe than sorry, though?
public void testEmpty() throws Exception {
- doTestEmpty(CharMatcher.ANY);
- doTestEmpty(CharMatcher.NONE);
+ doTestEmpty(CharMatcher.any());
+ doTestEmpty(CharMatcher.none());
doTestEmpty(is('a'));
doTestEmpty(isNot('a'));
doTestEmpty(anyOf(""));
@@ -135,7 +135,7 @@ public class CharMatcherTest extends TestCase {
}
public void testNoMatches() {
- doTestNoMatches(CharMatcher.NONE, "blah");
+ doTestNoMatches(CharMatcher.none(), "blah");
doTestNoMatches(is('a'), "bcde");
doTestNoMatches(isNot('a'), "aaaa");
doTestNoMatches(anyOf(""), "abcd");
@@ -146,10 +146,10 @@ public class CharMatcherTest extends TestCase {
doTestNoMatches(inRange('p', 'x'), "mom");
doTestNoMatches(forPredicate(Predicates.equalTo('c')), "abe");
doTestNoMatches(inRange('A', 'Z').and(inRange('F', 'K').negate()), "F1a");
- doTestNoMatches(CharMatcher.DIGIT, "\tAz()");
- doTestNoMatches(CharMatcher.JAVA_DIGIT, "\tAz()");
- doTestNoMatches(CharMatcher.DIGIT.and(CharMatcher.ASCII), "\tAz()");
- doTestNoMatches(CharMatcher.SINGLE_WIDTH, "\u05bf\u3000");
+ doTestNoMatches(CharMatcher.digit(), "\tAz()");
+ doTestNoMatches(CharMatcher.javaDigit(), "\tAz()");
+ doTestNoMatches(CharMatcher.digit().and(CharMatcher.ascii()), "\tAz()");
+ doTestNoMatches(CharMatcher.singleWidth(), "\u05bf\u3000");
}
private void doTestNoMatches(CharMatcher matcher, String s) {
@@ -164,7 +164,7 @@ public class CharMatcherTest extends TestCase {
}
public void testAllMatches() {
- doTestAllMatches(CharMatcher.ANY, "blah");
+ doTestAllMatches(CharMatcher.any(), "blah");
doTestAllMatches(isNot('a'), "bcde");
doTestAllMatches(is('a'), "aaaa");
doTestAllMatches(noneOf("CharMatcher"), "zxqy");
@@ -173,10 +173,10 @@ public class CharMatcherTest extends TestCase {
doTestAllMatches(anyOf("CharMatcher"), "ChMa");
doTestAllMatches(inRange('m', 'p'), "mom");
doTestAllMatches(forPredicate(Predicates.equalTo('c')), "ccc");
- doTestAllMatches(CharMatcher.DIGIT, "0123456789\u0ED0\u1B59");
- doTestAllMatches(CharMatcher.JAVA_DIGIT, "0123456789");
- doTestAllMatches(CharMatcher.DIGIT.and(CharMatcher.ASCII), "0123456789");
- doTestAllMatches(CharMatcher.SINGLE_WIDTH, "\t0123ABCdef~\u00A0\u2111");
+ doTestAllMatches(CharMatcher.digit(), "0123456789\u0ED0\u1B59");
+ doTestAllMatches(CharMatcher.javaDigit(), "0123456789");
+ doTestAllMatches(CharMatcher.digit().and(CharMatcher.ascii()), "0123456789");
+ doTestAllMatches(CharMatcher.singleWidth(), "\t0123ABCdef~\u00A0\u2111");
}
private void doTestAllMatches(CharMatcher matcher, String s) {
@@ -286,6 +286,7 @@ public class CharMatcherTest extends TestCase {
reallyTestMatchThenNoMatch(matcher.precomputed().negate(), s);
}
+ @SuppressWarnings("deprecation") // intentionally testing apply() method
private void reallyTestOneCharMatch(CharMatcher matcher, String s) {
assertTrue(matcher.matches(s.charAt(0)));
assertTrue(matcher.apply(s.charAt(0)));
@@ -303,6 +304,7 @@ public class CharMatcherTest extends TestCase {
assertEquals(1, matcher.countIn(s));
}
+ @SuppressWarnings("deprecation") // intentionally testing apply() method
private void reallyTestOneCharNoMatch(CharMatcher matcher, String s) {
assertFalse(matcher.matches(s.charAt(0)));
assertFalse(matcher.apply(s.charAt(0)));
@@ -418,14 +420,14 @@ public class CharMatcherTest extends TestCase {
assertSame(inout, anyOf("-").collapseFrom(inout, '_'));
assertSame(inout, anyOf("-#").collapseFrom(inout, '_'));
assertSame(inout, anyOf("-#123").collapseFrom(inout, '_'));
- assertSame(inout, CharMatcher.NONE.collapseFrom(inout, '_'));
+ assertSame(inout, CharMatcher.none().collapseFrom(inout, '_'));
}
public void testCollapse_any() {
- assertEquals("", CharMatcher.ANY.collapseFrom("", '_'));
- assertEquals("_", CharMatcher.ANY.collapseFrom("a", '_'));
- assertEquals("_", CharMatcher.ANY.collapseFrom("ab", '_'));
- assertEquals("_", CharMatcher.ANY.collapseFrom("abcd", '_'));
+ assertEquals("", CharMatcher.any().collapseFrom("", '_'));
+ assertEquals("_", CharMatcher.any().collapseFrom("a", '_'));
+ assertEquals("_", CharMatcher.any().collapseFrom("ab", '_'));
+ assertEquals("_", CharMatcher.any().collapseFrom("abcd", '_'));
}
public void testTrimFrom() {
@@ -583,24 +585,24 @@ public class CharMatcherTest extends TestCase {
// build a precomputed version.
CharMatcher m1 = is('x');
assertSame(m1, m1.precomputed());
- assertSame(m1.toString(), m1.precomputed().toString());
+ assertEquals(m1.toString(), m1.precomputed().toString());
CharMatcher m2 = anyOf("Az");
assertSame(m2, m2.precomputed());
- assertSame(m2.toString(), m2.precomputed().toString());
+ assertEquals(m2.toString(), m2.precomputed().toString());
CharMatcher m3 = inRange('A', 'Z');
assertSame(m3, m3.precomputed());
- assertSame(m3.toString(), m3.precomputed().toString());
+ assertEquals(m3.toString(), m3.precomputed().toString());
- assertSame(CharMatcher.NONE, CharMatcher.NONE.precomputed());
- assertSame(CharMatcher.ANY, CharMatcher.ANY.precomputed());
+ assertSame(CharMatcher.none(), CharMatcher.none().precomputed());
+ assertSame(CharMatcher.any(), CharMatcher.any().precomputed());
}
static void checkExactMatches(CharMatcher m, char[] chars) {
Set<Character> positive = Sets.newHashSetWithExpectedSize(chars.length);
- for (int i = 0; i < chars.length; i++) {
- positive.add(chars[i]);
+ for (char c : chars) {
+ positive.add(c);
}
for (int c = 0; c <= Character.MAX_VALUE; c++) {
assertFalse(positive.contains(new Character((char) c)) ^ m.matches((char) c));
@@ -629,7 +631,7 @@ public class CharMatcherTest extends TestCase {
}
public void testToString() {
- assertToStringWorks("CharMatcher.NONE", CharMatcher.anyOf(""));
+ assertToStringWorks("CharMatcher.none()", CharMatcher.anyOf(""));
assertToStringWorks("CharMatcher.is('\\u0031')", CharMatcher.anyOf("1"));
assertToStringWorks("CharMatcher.isNot('\\u0031')", CharMatcher.isNot('1'));
assertToStringWorks("CharMatcher.anyOf(\"\\u0031\\u0032\")", CharMatcher.anyOf("12"));
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/EnumsTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/EnumsTest.java
index c61855a..963fe73 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/EnumsTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/EnumsTest.java
@@ -16,6 +16,8 @@
package com.google.common.base;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.annotations.GwtCompatible;
import com.google.common.testing.SerializableTester;
@@ -41,27 +43,27 @@ public class EnumsTest extends TestCase {
private enum OtherEnum {}
public void testGetIfPresent() {
- assertEquals(Optional.of(TestEnum.CHEETO), Enums.getIfPresent(TestEnum.class, "CHEETO"));
- assertEquals(Optional.of(TestEnum.HONDA), Enums.getIfPresent(TestEnum.class, "HONDA"));
- assertEquals(Optional.of(TestEnum.POODLE), Enums.getIfPresent(TestEnum.class, "POODLE"));
+ assertThat(Enums.getIfPresent(TestEnum.class, "CHEETO")).hasValue(TestEnum.CHEETO);
+ assertThat(Enums.getIfPresent(TestEnum.class, "HONDA")).hasValue(TestEnum.HONDA);
+ assertThat(Enums.getIfPresent(TestEnum.class, "POODLE")).hasValue(TestEnum.POODLE);
- assertTrue(Enums.getIfPresent(TestEnum.class, "CHEETO").isPresent());
- assertTrue(Enums.getIfPresent(TestEnum.class, "HONDA").isPresent());
- assertTrue(Enums.getIfPresent(TestEnum.class, "POODLE").isPresent());
+ assertThat(Enums.getIfPresent(TestEnum.class, "CHEETO")).isPresent();
+ assertThat(Enums.getIfPresent(TestEnum.class, "HONDA")).isPresent();
+ assertThat(Enums.getIfPresent(TestEnum.class, "POODLE")).isPresent();
- assertEquals(TestEnum.CHEETO, Enums.getIfPresent(TestEnum.class, "CHEETO").get());
- assertEquals(TestEnum.HONDA, Enums.getIfPresent(TestEnum.class, "HONDA").get());
- assertEquals(TestEnum.POODLE, Enums.getIfPresent(TestEnum.class, "POODLE").get());
+ assertThat(Enums.getIfPresent(TestEnum.class, "CHEETO")).hasValue(TestEnum.CHEETO);
+ assertThat(Enums.getIfPresent(TestEnum.class, "HONDA")).hasValue(TestEnum.HONDA);
+ assertThat(Enums.getIfPresent(TestEnum.class, "POODLE")).hasValue(TestEnum.POODLE);
}
public void testGetIfPresent_caseSensitive() {
- assertFalse(Enums.getIfPresent(TestEnum.class, "cHEETO").isPresent());
- assertFalse(Enums.getIfPresent(TestEnum.class, "Honda").isPresent());
- assertFalse(Enums.getIfPresent(TestEnum.class, "poodlE").isPresent());
+ assertThat(Enums.getIfPresent(TestEnum.class, "cHEETO")).isAbsent();
+ assertThat(Enums.getIfPresent(TestEnum.class, "Honda")).isAbsent();
+ assertThat(Enums.getIfPresent(TestEnum.class, "poodlE")).isAbsent();
}
public void testGetIfPresent_whenNoMatchingConstant() {
- assertEquals(Optional.absent(), Enums.getIfPresent(TestEnum.class, "WOMBAT"));
+ assertThat(Enums.getIfPresent(TestEnum.class, "WOMBAT")).isAbsent();
}
// Create a second ClassLoader and use it to get a second version of the TestEnum class.
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/JoinerTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/JoinerTest.java
index 15ba5c8..d6cc3a8 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/JoinerTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/JoinerTest.java
@@ -56,6 +56,7 @@ public class JoinerTest extends TestCase {
private static final Iterable<Integer> ITERABLE_FOUR_NULLS
= Arrays.asList((Integer) null, null, null, null);
+ @SuppressWarnings("CheckReturnValue")
public void testNoSpecialNullBehavior() {
checkNoOutput(J, ITERABLE_);
checkResult(J, ITERABLE_1, "1");
@@ -235,6 +236,7 @@ public class JoinerTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testMap() {
MapJoiner j = Joiner.on(";").withKeyValueSeparator(":");
assertEquals("", j.join(ImmutableMap.of()));
@@ -257,6 +259,7 @@ public class JoinerTest extends TestCase {
assertEquals("1:2;3:4;5:6", sb.toString());
}
+ @SuppressWarnings("CheckReturnValue")
public void testEntries() {
MapJoiner j = Joiner.on(";").withKeyValueSeparator(":");
assertEquals("", j.join(ImmutableMultimap.of().entries()));
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/ObjectsTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/ObjectsTest.java
index 8030f14..a205378 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/ObjectsTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/ObjectsTest.java
@@ -68,6 +68,7 @@ public class ObjectsTest extends TestCase {
assertSame(n1, n2);
}
+ @SuppressWarnings("CheckReturnValue")
public void testFirstNonNull_throwsNullPointerException() throws Exception {
try {
Objects.firstNonNull(null, null);
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/OptionalTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/OptionalTest.java
index 6d78535..5c6947b 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/OptionalTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/OptionalTest.java
@@ -44,6 +44,7 @@ public final class OptionalTest extends TestCase {
assertEquals("training", Optional.of("training").get());
}
+ @SuppressWarnings("CheckReturnValue")
public void testOf_null() {
try {
Optional.of(null);
@@ -70,6 +71,7 @@ public final class OptionalTest extends TestCase {
assertTrue(Optional.of("training").isPresent());
}
+ @SuppressWarnings("CheckReturnValue")
public void testGet_absent() {
Optional<String> optional = Optional.absent();
try {
@@ -99,6 +101,7 @@ public final class OptionalTest extends TestCase {
assertEquals("fallback", Optional.absent().or(Suppliers.ofInstance("fallback")));
}
+ @SuppressWarnings("CheckReturnValue")
public void testOr_nullSupplier_absent() {
Supplier<Object> nullSupplier = Suppliers.ofInstance(null);
Optional<Object> absentOptional = Optional.absent();
@@ -170,6 +173,7 @@ public final class OptionalTest extends TestCase {
assertEquals(Optional.of("42"), Optional.of(42).transform(Functions.toStringFunction()));
}
+ @SuppressWarnings("CheckReturnValue")
public void testTransform_present_functionReturnsNull() {
try {
Optional.of("a").transform(
@@ -198,6 +202,8 @@ public final class OptionalTest extends TestCase {
public void testEqualsAndHashCode_absent() {
assertEquals(Optional.<String>absent(), Optional.<Integer>absent());
assertEquals(Optional.absent().hashCode(), Optional.absent().hashCode());
+ assertThat(Optional.absent().hashCode())
+ .isNotEqualTo(Optional.of(0).hashCode());
}
public void testEqualsAndHashCode_present() {
@@ -218,7 +224,7 @@ public final class OptionalTest extends TestCase {
public void testPresentInstances_allPresent() {
List<Optional<String>> optionals =
ImmutableList.of(Optional.of("a"), Optional.of("b"), Optional.of("c"));
- assertThat(Optional.presentInstances(optionals)).iteratesAs("a", "b", "c");
+ assertThat(Optional.presentInstances(optionals)).containsExactly("a", "b", "c").inOrder();
}
public void testPresentInstances_allAbsent() {
@@ -230,22 +236,22 @@ public final class OptionalTest extends TestCase {
public void testPresentInstances_somePresent() {
List<Optional<String>> optionals =
ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
- assertThat(Optional.presentInstances(optionals)).iteratesAs("a", "c");
+ assertThat(Optional.presentInstances(optionals)).containsExactly("a", "c").inOrder();
}
public void testPresentInstances_callingIteratorTwice() {
List<Optional<String>> optionals =
ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
Iterable<String> onlyPresent = Optional.presentInstances(optionals);
- assertThat(onlyPresent).iteratesAs("a", "c");
- assertThat(onlyPresent).iteratesAs("a", "c");
+ assertThat(onlyPresent).containsExactly("a", "c").inOrder();
+ assertThat(onlyPresent).containsExactly("a", "c").inOrder();
}
public void testPresentInstances_wildcards() {
List<Optional<? extends Number>> optionals =
ImmutableList.<Optional<? extends Number>>of(Optional.<Double>absent(), Optional.of(2));
Iterable<Number> onlyPresent = Optional.presentInstances(optionals);
- assertThat(onlyPresent).iteratesAs(2);
+ assertThat(onlyPresent).containsExactly(2).inOrder();
}
private static Optional<Integer> getSomeOptionalInt() {
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/PreconditionsTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/PreconditionsTest.java
index e35864a..bb4bc09 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/PreconditionsTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/PreconditionsTest.java
@@ -16,6 +16,8 @@
package com.google.common.base;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.annotations.GwtCompatible;
import junit.framework.AssertionFailedError;
@@ -59,7 +61,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkArgument(false, null);
fail("no exception thrown");
} catch (IllegalArgumentException expected) {
- assertEquals("null", expected.getMessage());
+ assertThat(expected).hasMessage("null");
}
}
@@ -106,7 +108,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkState(false, null);
fail("no exception thrown");
} catch (IllegalStateException expected) {
- assertEquals("null", expected.getMessage());
+ assertThat(expected).hasMessage("null");
}
}
@@ -188,7 +190,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkElementIndex(-1, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("index (-1) must not be negative", expected.getMessage());
+ assertThat(expected).hasMessage("index (-1) must not be negative");
}
}
@@ -197,8 +199,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkElementIndex(1, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("index (1) must be less than size (1)",
- expected.getMessage());
+ assertThat(expected).hasMessage("index (1) must be less than size (1)");
}
}
@@ -207,7 +208,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkElementIndex(-1, 1, "foo");
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("foo (-1) must not be negative", expected.getMessage());
+ assertThat(expected).hasMessage("foo (-1) must not be negative");
}
}
@@ -216,8 +217,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkElementIndex(1, 1, "foo");
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("foo (1) must be less than size (1)",
- expected.getMessage());
+ assertThat(expected).hasMessage("foo (1) must be less than size (1)");
}
}
@@ -242,7 +242,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndex(-1, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("index (-1) must not be negative", expected.getMessage());
+ assertThat(expected).hasMessage("index (-1) must not be negative");
}
}
@@ -251,8 +251,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndex(2, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("index (2) must not be greater than size (1)",
- expected.getMessage());
+ assertThat(expected).hasMessage("index (2) must not be greater than size (1)");
}
}
@@ -261,7 +260,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndex(-1, 1, "foo");
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("foo (-1) must not be negative", expected.getMessage());
+ assertThat(expected).hasMessage("foo (-1) must not be negative");
}
}
@@ -270,8 +269,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndex(2, 1, "foo");
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("foo (2) must not be greater than size (1)",
- expected.getMessage());
+ assertThat(expected).hasMessage("foo (2) must not be greater than size (1)");
}
}
@@ -295,8 +293,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndexes(-1, 1, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("start index (-1) must not be negative",
- expected.getMessage());
+ assertThat(expected).hasMessage("start index (-1) must not be negative");
}
}
@@ -305,8 +302,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndexes(0, 2, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("end index (2) must not be greater than size (1)",
- expected.getMessage());
+ assertThat(expected).hasMessage("end index (2) must not be greater than size (1)");
}
}
@@ -315,8 +311,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndexes(1, 0, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("end index (0) must not be less than start index (1)",
- expected.getMessage());
+ assertThat(expected).hasMessage("end index (0) must not be less than start index (1)");
}
}
@@ -356,10 +351,10 @@ public class PreconditionsTest extends TestCase {
private static final String FORMAT = "I ate %s pies.";
private static void verifySimpleMessage(Exception e) {
- assertEquals("A message", e.getMessage());
+ assertThat(e).hasMessage("A message");
}
private static void verifyComplexMessage(Exception e) {
- assertEquals("I ate 5 pies.", e.getMessage());
+ assertThat(e).hasMessage("I ate 5 pies.");
}
}
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/SplitterTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/SplitterTest.java
index aabd88d..b2891a5 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/SplitterTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/SplitterTest.java
@@ -19,12 +19,10 @@ package com.google.common.base;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import junit.framework.TestCase;
-import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -37,6 +35,7 @@ public class SplitterTest extends TestCase {
private static final Splitter COMMA_SPLITTER = Splitter.on(',');
+ @SuppressWarnings("CheckReturnValue")
public void testSplitNullString() {
try {
COMMA_SPLITTER.split(null);
@@ -48,7 +47,7 @@ public class SplitterTest extends TestCase {
public void testCharacterSimpleSplit() {
String simple = "a,b,c";
Iterable<String> letters = COMMA_SPLITTER.split(simple);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
/**
@@ -62,7 +61,7 @@ public class SplitterTest extends TestCase {
public void testCharacterSimpleSplitToList() {
String simple = "a,b,c";
List<String> letters = COMMA_SPLITTER.splitToList(simple);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
public void testToString() {
@@ -74,72 +73,74 @@ public class SplitterTest extends TestCase {
public void testCharacterSimpleSplitWithNoDelimiter() {
String simple = "a,b,c";
Iterable<String> letters = Splitter.on('.').split(simple);
- assertThat(letters).iteratesAs("a,b,c");
+ assertThat(letters).containsExactly("a,b,c").inOrder();
}
public void testCharacterSplitWithDoubleDelimiter() {
String doubled = "a,,b,c";
Iterable<String> letters = COMMA_SPLITTER.split(doubled);
- assertThat(letters).iteratesAs("a", "", "b", "c");
+ assertThat(letters).containsExactly("a", "", "b", "c").inOrder();
}
public void testCharacterSplitWithDoubleDelimiterAndSpace() {
String doubled = "a,, b,c";
Iterable<String> letters = COMMA_SPLITTER.split(doubled);
- assertThat(letters).iteratesAs("a", "", " b", "c");
+ assertThat(letters).containsExactly("a", "", " b", "c").inOrder();
}
public void testCharacterSplitWithTrailingDelimiter() {
String trailing = "a,b,c,";
Iterable<String> letters = COMMA_SPLITTER.split(trailing);
- assertThat(letters).iteratesAs("a", "b", "c", "");
+ assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
}
public void testCharacterSplitWithLeadingDelimiter() {
String leading = ",a,b,c";
Iterable<String> letters = COMMA_SPLITTER.split(leading);
- assertThat(letters).iteratesAs("", "a", "b", "c");
+ assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
}
public void testCharacterSplitWithMulitpleLetters() {
Iterable<String> testCharacteringMotto = Splitter.on('-').split(
"Testing-rocks-Debugging-sucks");
- assertThat(testCharacteringMotto).iteratesAs(
- "Testing", "rocks", "Debugging", "sucks");
+ assertThat(testCharacteringMotto)
+ .containsExactly("Testing", "rocks", "Debugging", "sucks")
+ .inOrder();
}
public void testCharacterSplitWithMatcherDelimiter() {
Iterable<String> testCharacteringMotto = Splitter
.on(CharMatcher.WHITESPACE)
.split("Testing\nrocks\tDebugging sucks");
- assertThat(testCharacteringMotto).iteratesAs(
- "Testing", "rocks", "Debugging", "sucks");
+ assertThat(testCharacteringMotto)
+ .containsExactly("Testing", "rocks", "Debugging", "sucks")
+ .inOrder();
}
public void testCharacterSplitWithDoubleDelimiterOmitEmptyStrings() {
String doubled = "a..b.c";
Iterable<String> letters = Splitter.on('.')
.omitEmptyStrings().split(doubled);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
public void testCharacterSplitEmptyToken() {
String emptyToken = "a. .c";
Iterable<String> letters = Splitter.on('.').trimResults()
.split(emptyToken);
- assertThat(letters).iteratesAs("a", "", "c");
+ assertThat(letters).containsExactly("a", "", "c").inOrder();
}
public void testCharacterSplitEmptyTokenOmitEmptyStrings() {
String emptyToken = "a. .c";
Iterable<String> letters = Splitter.on('.')
.omitEmptyStrings().trimResults().split(emptyToken);
- assertThat(letters).iteratesAs("a", "c");
+ assertThat(letters).containsExactly("a", "c").inOrder();
}
public void testCharacterSplitOnEmptyString() {
Iterable<String> nothing = Splitter.on('.').split("");
- assertThat(nothing).iteratesAs("");
+ assertThat(nothing).containsExactly("").inOrder();
}
public void testCharacterSplitOnEmptyStringOmitEmptyStrings() {
@@ -148,7 +149,7 @@ public class SplitterTest extends TestCase {
public void testCharacterSplitOnOnlyDelimiter() {
Iterable<String> blankblank = Splitter.on('.').split(".");
- assertThat(blankblank).iteratesAs("", "");
+ assertThat(blankblank).containsExactly("", "").inOrder();
}
public void testCharacterSplitOnOnlyDelimitersOmitEmptyStrings() {
@@ -162,99 +163,102 @@ public class SplitterTest extends TestCase {
Iterable<String> family = COMMA_SPLITTER
.trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
.split(jacksons);
- assertThat(family).iteratesAs(
- "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
+ assertThat(family)
+ .containsExactly("(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)")
+ .inOrder();
}
public void testStringSimpleSplit() {
String simple = "a,b,c";
Iterable<String> letters = Splitter.on(',').split(simple);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
public void testStringSimpleSplitWithNoDelimiter() {
String simple = "a,b,c";
Iterable<String> letters = Splitter.on('.').split(simple);
- assertThat(letters).iteratesAs("a,b,c");
+ assertThat(letters).containsExactly("a,b,c").inOrder();
}
public void testStringSplitWithDoubleDelimiter() {
String doubled = "a,,b,c";
Iterable<String> letters = Splitter.on(',').split(doubled);
- assertThat(letters).iteratesAs("a", "", "b", "c");
+ assertThat(letters).containsExactly("a", "", "b", "c").inOrder();
}
public void testStringSplitWithDoubleDelimiterAndSpace() {
String doubled = "a,, b,c";
Iterable<String> letters = Splitter.on(',').split(doubled);
- assertThat(letters).iteratesAs("a", "", " b", "c");
+ assertThat(letters).containsExactly("a", "", " b", "c").inOrder();
}
public void testStringSplitWithTrailingDelimiter() {
String trailing = "a,b,c,";
Iterable<String> letters = Splitter.on(',').split(trailing);
- assertThat(letters).iteratesAs("a", "b", "c", "");
+ assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
}
public void testStringSplitWithLeadingDelimiter() {
String leading = ",a,b,c";
Iterable<String> letters = Splitter.on(',').split(leading);
- assertThat(letters).iteratesAs("", "a", "b", "c");
+ assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
}
public void testStringSplitWithMultipleLetters() {
Iterable<String> testStringingMotto = Splitter.on('-').split(
"Testing-rocks-Debugging-sucks");
- assertThat(testStringingMotto).iteratesAs(
- "Testing", "rocks", "Debugging", "sucks");
+ assertThat(testStringingMotto)
+ .containsExactly("Testing", "rocks", "Debugging", "sucks")
+ .inOrder();
}
public void testStringSplitWithDoubleDelimiterOmitEmptyStrings() {
String doubled = "a..b.c";
Iterable<String> letters = Splitter.on('.')
.omitEmptyStrings().split(doubled);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
public void testStringSplitEmptyToken() {
String emptyToken = "a. .c";
Iterable<String> letters = Splitter.on('.').trimResults()
.split(emptyToken);
- assertThat(letters).iteratesAs("a", "", "c");
+ assertThat(letters).containsExactly("a", "", "c").inOrder();
}
public void testStringSplitEmptyTokenOmitEmptyStrings() {
String emptyToken = "a. .c";
Iterable<String> letters = Splitter.on('.')
.omitEmptyStrings().trimResults().split(emptyToken);
- assertThat(letters).iteratesAs("a", "c");
+ assertThat(letters).containsExactly("a", "c").inOrder();
}
public void testStringSplitWithLongDelimiter() {
String longDelimiter = "a, b, c";
Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
public void testStringSplitWithLongLeadingDelimiter() {
String longDelimiter = ", a, b, c";
Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
- assertThat(letters).iteratesAs("", "a", "b", "c");
+ assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
}
public void testStringSplitWithLongTrailingDelimiter() {
String longDelimiter = "a, b, c, ";
Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
- assertThat(letters).iteratesAs("a", "b", "c", "");
+ assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
}
public void testStringSplitWithDelimiterSubstringInValue() {
String fourCommasAndFourSpaces = ",,,, ";
Iterable<String> threeCommasThenThreeSpaces = Splitter.on(", ").split(
fourCommasAndFourSpaces);
- assertThat(threeCommasThenThreeSpaces).iteratesAs(",,,", " ");
+ assertThat(threeCommasThenThreeSpaces).containsExactly(",,,", " ").inOrder();
}
+ @SuppressWarnings("CheckReturnValue")
public void testStringSplitWithEmptyString() {
try {
Splitter.on("");
@@ -265,7 +269,7 @@ public class SplitterTest extends TestCase {
public void testStringSplitOnEmptyString() {
Iterable<String> notMuch = Splitter.on('.').split("");
- assertThat(notMuch).iteratesAs("");
+ assertThat(notMuch).containsExactly("").inOrder();
}
public void testStringSplitOnEmptyStringOmitEmptyString() {
@@ -274,7 +278,7 @@ public class SplitterTest extends TestCase {
public void testStringSplitOnOnlyDelimiter() {
Iterable<String> blankblank = Splitter.on('.').split(".");
- assertThat(blankblank).iteratesAs("", "");
+ assertThat(blankblank).containsExactly("", "").inOrder();
}
public void testStringSplitOnOnlyDelimitersOmitEmptyStrings() {
@@ -288,8 +292,9 @@ public class SplitterTest extends TestCase {
Iterable<String> family = Splitter.on(',')
.trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
.split(jacksons);
- assertThat(family).iteratesAs(
- "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
+ assertThat(family)
+ .containsExactly("(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)")
+ .inOrder();
}
// TODO(kevinb): the name of this method suggests it might not actually be testing what it
@@ -341,31 +346,31 @@ public class SplitterTest extends TestCase {
public void testFixedLengthSimpleSplit() {
String simple = "abcde";
Iterable<String> letters = Splitter.fixedLength(2).split(simple);
- assertThat(letters).iteratesAs("ab", "cd", "e");
+ assertThat(letters).containsExactly("ab", "cd", "e").inOrder();
}
public void testFixedLengthSplitEqualChunkLength() {
String simple = "abcdef";
Iterable<String> letters = Splitter.fixedLength(2).split(simple);
- assertThat(letters).iteratesAs("ab", "cd", "ef");
+ assertThat(letters).containsExactly("ab", "cd", "ef").inOrder();
}
public void testFixedLengthSplitOnlyOneChunk() {
String simple = "abc";
Iterable<String> letters = Splitter.fixedLength(3).split(simple);
- assertThat(letters).iteratesAs("abc");
+ assertThat(letters).containsExactly("abc").inOrder();
}
public void testFixedLengthSplitSmallerString() {
String simple = "ab";
Iterable<String> letters = Splitter.fixedLength(3).split(simple);
- assertThat(letters).iteratesAs("ab");
+ assertThat(letters).containsExactly("ab").inOrder();
}
public void testFixedLengthSplitEmptyString() {
String simple = "";
Iterable<String> letters = Splitter.fixedLength(3).split(simple);
- assertThat(letters).iteratesAs("");
+ assertThat(letters).containsExactly("").inOrder();
}
public void testFixedLengthSplitEmptyStringWithOmitEmptyStrings() {
@@ -375,9 +380,10 @@ public class SplitterTest extends TestCase {
public void testFixedLengthSplitIntoChars() {
String simple = "abcd";
Iterable<String> letters = Splitter.fixedLength(1).split(simple);
- assertThat(letters).iteratesAs("a", "b", "c", "d");
+ assertThat(letters).containsExactly("a", "b", "c", "d").inOrder();
}
+ @SuppressWarnings("CheckReturnValue")
public void testFixedLengthSplitZeroChunkLen() {
try {
Splitter.fixedLength(0);
@@ -386,6 +392,7 @@ public class SplitterTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testFixedLengthSplitNegativeChunkLen() {
try {
Splitter.fixedLength(-1);
@@ -397,73 +404,73 @@ public class SplitterTest extends TestCase {
public void testLimitLarge() {
String simple = "abcd";
Iterable<String> letters = Splitter.fixedLength(1).limit(100).split(simple);
- assertThat(letters).iteratesAs("a", "b", "c", "d");
+ assertThat(letters).containsExactly("a", "b", "c", "d").inOrder();
}
public void testLimitOne() {
String simple = "abcd";
Iterable<String> letters = Splitter.fixedLength(1).limit(1).split(simple);
- assertThat(letters).iteratesAs("abcd");
+ assertThat(letters).containsExactly("abcd").inOrder();
}
public void testLimitFixedLength() {
String simple = "abcd";
Iterable<String> letters = Splitter.fixedLength(1).limit(2).split(simple);
- assertThat(letters).iteratesAs("a", "bcd");
+ assertThat(letters).containsExactly("a", "bcd").inOrder();
}
public void testLimitSeparator() {
String simple = "a,b,c,d";
Iterable<String> items = COMMA_SPLITTER.limit(2).split(simple);
- assertThat(items).iteratesAs("a", "b,c,d");
+ assertThat(items).containsExactly("a", "b,c,d").inOrder();
}
public void testLimitExtraSeparators() {
String text = "a,,,b,,c,d";
Iterable<String> items = COMMA_SPLITTER.limit(2).split(text);
- assertThat(items).iteratesAs("a", ",,b,,c,d");
+ assertThat(items).containsExactly("a", ",,b,,c,d").inOrder();
}
public void testLimitExtraSeparatorsOmitEmpty() {
String text = "a,,,b,,c,d";
Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().split(text);
- assertThat(items).iteratesAs("a", "b,,c,d");
+ assertThat(items).containsExactly("a", "b,,c,d").inOrder();
}
public void testLimitExtraSeparatorsOmitEmpty3() {
String text = "a,,,b,,c,d";
Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().split(text);
- assertThat(items).iteratesAs("a", "b", "c,d");
+ assertThat(items).containsExactly("a", "b", "c,d").inOrder();
}
public void testLimitExtraSeparatorsTrim() {
String text = ",,a,, , b ,, c,d ";
Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().trimResults().split(text);
- assertThat(items).iteratesAs("a", "b ,, c,d");
+ assertThat(items).containsExactly("a", "b ,, c,d").inOrder();
}
public void testLimitExtraSeparatorsTrim3() {
String text = ",,a,, , b ,, c,d ";
Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().trimResults().split(text);
- assertThat(items).iteratesAs("a", "b", "c,d");
+ assertThat(items).containsExactly("a", "b", "c,d").inOrder();
}
public void testLimitExtraSeparatorsTrim1() {
String text = ",,a,, , b ,, c,d ";
Iterable<String> items = COMMA_SPLITTER.limit(1).omitEmptyStrings().trimResults().split(text);
- assertThat(items).iteratesAs("a,, , b ,, c,d");
+ assertThat(items).containsExactly("a,, , b ,, c,d").inOrder();
}
public void testLimitExtraSeparatorsTrim1NoOmit() {
String text = ",,a,, , b ,, c,d ";
Iterable<String> items = COMMA_SPLITTER.limit(1).trimResults().split(text);
- assertThat(items).iteratesAs(",,a,, , b ,, c,d");
+ assertThat(items).containsExactly(",,a,, , b ,, c,d").inOrder();
}
public void testLimitExtraSeparatorsTrim1Empty() {
String text = "";
Iterable<String> items = COMMA_SPLITTER.limit(1).split(text);
- assertThat(items).iteratesAs("");
+ assertThat(items).containsExactly("").inOrder();
}
public void testLimitExtraSeparatorsTrim1EmptyOmit() {
@@ -481,19 +488,15 @@ public class SplitterTest extends TestCase {
}
}
- private static <E> List<E> asList(Collection<E> collection) {
- return ImmutableList.copyOf(collection);
- }
-
public void testMapSplitter_trimmedBoth() {
Map<String, String> m = COMMA_SPLITTER
.trimResults()
.withKeyValueSeparator(Splitter.on(':').trimResults())
.split("boy : tom , girl: tina , cat : kitty , dog: tommy ");
ImmutableMap<String, String> expected =
- ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
+ ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
assertThat(m).isEqualTo(expected);
- assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+ assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
}
public void testMapSplitter_trimmedEntries() {
@@ -505,7 +508,7 @@ public class SplitterTest extends TestCase {
ImmutableMap.of("boy ", " tom", "girl", " tina", "cat ", " kitty", "dog", " tommy");
assertThat(m).isEqualTo(expected);
- assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+ assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
}
public void testMapSplitter_trimmedKeyValue() {
@@ -515,7 +518,7 @@ public class SplitterTest extends TestCase {
ImmutableMap<String, String> expected =
ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
assertThat(m).isEqualTo(expected);
- assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+ assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
}
public void testMapSplitter_notTrimmed() {
@@ -524,7 +527,7 @@ public class SplitterTest extends TestCase {
ImmutableMap<String, String> expected =
ImmutableMap.of(" boy", "tom ", " girl", " tina ", " cat ", "kitty ", " dog", " tommy ");
assertThat(m).isEqualTo(expected);
- assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+ assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
}
public void testMapSplitter_CharacterSeparator() {
@@ -537,7 +540,7 @@ public class SplitterTest extends TestCase {
ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
assertThat(m).isEqualTo(expected);
- assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+ assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
}
public void testMapSplitter_multiCharacterSeparator() {
@@ -550,10 +553,10 @@ public class SplitterTest extends TestCase {
ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
assertThat(m).isEqualTo(expected);
- assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+ assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
}
- @SuppressWarnings("ReturnValueIgnored") // testing for exception
+ @SuppressWarnings("CheckReturnValue")
public void testMapSplitter_emptySeparator() {
try {
COMMA_SPLITTER.withKeyValueSeparator("");
@@ -562,6 +565,7 @@ public class SplitterTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testMapSplitter_malformedEntry() {
try {
COMMA_SPLITTER.withKeyValueSeparator("=").split("a=1,b,c=2");
@@ -575,7 +579,7 @@ public class SplitterTest extends TestCase {
.withKeyValueSeparator(":")
.split("boy:tom,girl:tina,cat:kitty,dog:tommy");
- assertThat(m.keySet()).iteratesAs("boy", "girl", "cat", "dog");
+ assertThat(m.keySet()).containsExactly("boy", "girl", "cat", "dog").inOrder();
assertThat(m).isEqualTo(
ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
@@ -584,11 +588,12 @@ public class SplitterTest extends TestCase {
.withKeyValueSeparator(":")
.split("girl:tina,boy:tom,dog:tommy,cat:kitty");
- assertThat(m.keySet()).iteratesAs("girl", "boy", "dog", "cat");
+ assertThat(m.keySet()).containsExactly("girl", "boy", "dog", "cat").inOrder();
assertThat(m).isEqualTo(
ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMapSplitter_duplicateKeys() {
try {
Splitter.on(',').withKeyValueSeparator(":").split("a:1,b:2,a:3");
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StopwatchTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StopwatchTest.java
index b8da84d..55a1593 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StopwatchTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StopwatchTest.java
@@ -167,48 +167,5 @@ public class StopwatchTest extends TestCase {
assertEquals(1, stopwatch.elapsed(MILLISECONDS));
}
- public void testElapsedMillis() {
- stopwatch.start();
- ticker.advance(999999);
- assertEquals(0, stopwatch.elapsed(MILLISECONDS));
- ticker.advance(1);
- assertEquals(1, stopwatch.elapsed(MILLISECONDS));
- }
-
- public void testElapsedMillis_whileRunning() {
- ticker.advance(78000000);
- stopwatch.start();
- assertEquals(0, stopwatch.elapsed(MILLISECONDS));
-
- ticker.advance(345000000);
- assertEquals(345, stopwatch.elapsed(MILLISECONDS));
- }
-
- public void testElapsedMillis_notRunning() {
- ticker.advance(1000000);
- stopwatch.start();
- ticker.advance(4000000);
- stopwatch.stop();
- ticker.advance(9000000);
- assertEquals(4, stopwatch.elapsed(MILLISECONDS));
- }
-
- public void testElapsedMillis_multipleSegments() {
- stopwatch.start();
- ticker.advance(9000000);
- stopwatch.stop();
-
- ticker.advance(16000000);
-
- stopwatch.start();
- assertEquals(9, stopwatch.elapsed(MILLISECONDS));
- ticker.advance(25000000);
- assertEquals(34, stopwatch.elapsed(MILLISECONDS));
-
- stopwatch.stop();
- ticker.advance(36000000);
- assertEquals(34, stopwatch.elapsed(MILLISECONDS));
- }
-
}
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StringsTest.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StringsTest.java
index 96395d8..4a0eddf 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StringsTest.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/StringsTest.java
@@ -66,6 +66,7 @@ public class StringsTest extends TestCase {
}
// TODO: could remove if we got NPT working in GWT somehow
+ @SuppressWarnings("CheckReturnValue")
public void testPadStart_null() {
try {
Strings.padStart(null, 5, '0');
@@ -95,6 +96,7 @@ public class StringsTest extends TestCase {
}
// TODO: could remove if we got NPT working in GWT somehow
+ @SuppressWarnings("CheckReturnValue")
public void testPadEnd_null() {
try {
Strings.padEnd(null, 5, '0');
@@ -103,6 +105,7 @@ public class StringsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testRepeat() {
String input = "20";
assertEquals("", Strings.repeat(input, 0));
@@ -130,6 +133,7 @@ public class StringsTest extends TestCase {
}
// TODO: could remove if we got NPT working in GWT somehow
+ @SuppressWarnings("CheckReturnValue")
public void testRepeat_null() {
try {
Strings.repeat(null, 5);
diff --git a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/Utf8Test.java b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/Utf8Test.java
index 10545bc..95b5c62 100644
--- a/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/Utf8Test.java
+++ b/guava-gwt/test-super/com/google/common/base/super/com/google/common/base/Utf8Test.java
@@ -16,10 +16,22 @@
package com.google.common.base;
+import static com.google.common.truth.Truth.assertThat;
+import static java.lang.Character.MAX_CODE_POINT;
+import static java.lang.Character.MAX_HIGH_SURROGATE;
+import static java.lang.Character.MAX_LOW_SURROGATE;
+import static java.lang.Character.MIN_HIGH_SURROGATE;
+import static java.lang.Character.MIN_LOW_SURROGATE;
+import static java.lang.Character.MIN_SUPPLEMENTARY_CODE_POINT;
+
import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.ImmutableList;
import junit.framework.TestCase;
+import java.util.HashMap;
+import java.util.Random;
+
/**
* Unit tests for {@link Utf8}.
*
@@ -29,6 +41,26 @@ import junit.framework.TestCase;
*/
@GwtCompatible(emulated = true)
public class Utf8Test extends TestCase {
+
+ private static final ImmutableList<String> ILL_FORMED_STRINGS;
+ static {
+ ImmutableList.Builder<String> builder = ImmutableList.builder();
+ char[] surrogates = {
+ MAX_LOW_SURROGATE,
+ MAX_HIGH_SURROGATE,
+ MIN_LOW_SURROGATE,
+ MIN_HIGH_SURROGATE,
+ };
+ for (char surrogate : surrogates) {
+ builder.add(newString(surrogate));
+ builder.add(newString(surrogate, 'n'));
+ builder.add(newString('n', surrogate));
+ builder.add(newString(surrogate, surrogate));
+ }
+ builder.add(newString(MIN_LOW_SURROGATE, MAX_HIGH_SURROGATE));
+ ILL_FORMED_STRINGS = builder.build();
+ }
+
public void testEncodedLength_validStrings() {
assertEquals(0, Utf8.encodedLength(""));
assertEquals(11, Utf8.encodedLength("Hello world"));
@@ -40,29 +72,57 @@ public class Utf8Test extends TestCase {
+ "狹斯丕爾。[2]莎士比亞編寫過好多作品,佢嗰劇作響西洋文學好有影響,"
+ "哈都拕人翻譯做好多話。"));
// A surrogate pair
- assertEquals(4, Utf8.encodedLength(
- newString(Character.MIN_HIGH_SURROGATE, Character.MIN_LOW_SURROGATE)));
+ assertEquals(4, Utf8.encodedLength(newString(MIN_HIGH_SURROGATE, MIN_LOW_SURROGATE)));
+ }
+
+ public void testEncodedLength_validStrings2() {
+ HashMap<Integer, Integer> utf8Lengths = new HashMap<Integer, Integer>();
+ utf8Lengths.put(0x00, 1);
+ utf8Lengths.put(0x7f, 1);
+ utf8Lengths.put(0x80, 2);
+ utf8Lengths.put(0x7ff, 2);
+ utf8Lengths.put(0x800, 3);
+ utf8Lengths.put(MIN_SUPPLEMENTARY_CODE_POINT - 1, 3);
+ utf8Lengths.put(MIN_SUPPLEMENTARY_CODE_POINT, 4);
+ utf8Lengths.put(MAX_CODE_POINT, 4);
+
+ Integer[] codePoints = utf8Lengths.keySet().toArray(new Integer[]{});
+ StringBuilder sb = new StringBuilder();
+ Random rnd = new Random();
+ for (int trial = 0; trial < 100; trial++) {
+ sb.setLength(0);
+ int utf8Length = 0;
+ for (int i = 0; i < 6; i++) {
+ Integer randomCodePoint = codePoints[rnd.nextInt(codePoints.length)];
+ sb.appendCodePoint(randomCodePoint);
+ utf8Length += utf8Lengths.get(randomCodePoint);
+ if (utf8Length != Utf8.encodedLength(sb)) {
+ StringBuilder repro = new StringBuilder();
+ for (int j = 0; j < sb.length(); j++) {
+ repro.append(" " + (int) sb.charAt(j)); // GWT compatible
+ }
+ assertEquals(repro.toString(), utf8Length, Utf8.encodedLength(sb));
+ }
+ }
+ }
}
public void testEncodedLength_invalidStrings() {
- testEncodedLengthFails(newString(Character.MIN_HIGH_SURROGATE), 0);
- testEncodedLengthFails("foobar" + newString(Character.MIN_HIGH_SURROGATE), 6);
- testEncodedLengthFails(newString(Character.MIN_LOW_SURROGATE), 0);
- testEncodedLengthFails("foobar" + newString(Character.MIN_LOW_SURROGATE), 6);
- testEncodedLengthFails(
- newString(
- Character.MIN_HIGH_SURROGATE,
- Character.MIN_HIGH_SURROGATE), 0);
+ testEncodedLengthFails(newString(MIN_HIGH_SURROGATE), 0);
+ testEncodedLengthFails("foobar" + newString(MIN_HIGH_SURROGATE), 6);
+ testEncodedLengthFails(newString(MIN_LOW_SURROGATE), 0);
+ testEncodedLengthFails("foobar" + newString(MIN_LOW_SURROGATE), 6);
+ testEncodedLengthFails(newString(MIN_HIGH_SURROGATE, MIN_HIGH_SURROGATE), 0);
}
+ @SuppressWarnings("CheckReturnValue")
private static void testEncodedLengthFails(String invalidString,
int invalidCodePointIndex) {
try {
Utf8.encodedLength(invalidString);
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("Unpaired surrogate at index " + invalidCodePointIndex,
- expected.getMessage());
+ assertThat(expected).hasMessage("Unpaired surrogate at index " + invalidCodePointIndex);
}
}
@@ -169,11 +229,11 @@ public class Utf8Test extends TestCase {
assertEquals(EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT, actual);
}
- private String newString(char... chars) {
+ private static String newString(char... chars) {
return new String(chars);
}
- private byte[] toByteArray(int... bytes) {
+ private static byte[] toByteArray(int... bytes) {
byte[] realBytes = new byte[bytes.length];
for (int i = 0; i < bytes.length; i++) {
realBytes[i] = (byte) bytes[i];
@@ -181,11 +241,11 @@ public class Utf8Test extends TestCase {
return realBytes;
}
- private void assertWellFormed(int... bytes) {
+ private static void assertWellFormed(int... bytes) {
assertTrue(Utf8.isWellFormed(toByteArray(bytes)));
}
- private void assertNotWellFormed(int... bytes) {
+ private static void assertNotWellFormed(int... bytes) {
assertFalse(Utf8.isWellFormed(toByteArray(bytes)));
}
@@ -214,4 +274,3 @@ public class Utf8Test extends TestCase {
return expected;
}
}
-
diff --git a/guava-gwt/test-super/com/google/common/cache/super/com/google/common/cache/CacheBuilderTest.java b/guava-gwt/test-super/com/google/common/cache/super/com/google/common/cache/CacheBuilderTest.java
index 668a066..dfb0a18 100644
--- a/guava-gwt/test-super/com/google/common/cache/super/com/google/common/cache/CacheBuilderTest.java
+++ b/guava-gwt/test-super/com/google/common/cache/super/com/google/common/cache/CacheBuilderTest.java
@@ -20,6 +20,7 @@ import static com.google.common.cache.TestingCacheLoaders.constantLoader;
import static com.google.common.cache.TestingCacheLoaders.identityLoader;
import static com.google.common.cache.TestingRemovalListeners.countingRemovalListener;
import static com.google.common.cache.TestingRemovalListeners.nullRemovalListener;
+import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -28,6 +29,8 @@ import com.google.common.base.Ticker;
import junit.framework.TestCase;
+import java.util.Set;
+
/**
* Unit tests for CacheBuilder.
*/
@@ -187,6 +190,11 @@ public class CacheBuilderTest extends TestCase {
} catch (IllegalStateException expected) {}
}
+ public void testValuesIsNotASet() {
+ assertThat(new CacheBuilder<Object, Object>().build().asMap().values())
+ .isNotInstanceOf(Set.class);
+ }
+
// "Basher tests", where we throw a bunch of stuff at a LoadingCache and check basic invariants.
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractImmutableSetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractImmutableSetTest.java
index b16137a..58db77a 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractImmutableSetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractImmutableSetTest.java
@@ -271,7 +271,7 @@ public abstract class AbstractImmutableSetTest extends TestCase {
.add("d", "e", "f")
.add("g", "h", "i", "j")
.build();
- assertThat(set).has().exactly(
+ assertThat(set).containsExactly(
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j").inOrder();
}
@@ -279,9 +279,9 @@ public abstract class AbstractImmutableSetTest extends TestCase {
ImmutableSet.Builder<String> builder = this.<String>builder()
.add("a")
.add("b");
- assertThat(builder.build()).has().exactly("a", "b").inOrder();
+ assertThat(builder.build()).containsExactly("a", "b").inOrder();
builder.add("c", "d");
- assertThat(builder.build()).has().exactly("a", "b", "c", "d").inOrder();
+ assertThat(builder.build()).containsExactly("a", "b", "c", "d").inOrder();
}
public void testBuilderWithDuplicateElements() {
@@ -301,9 +301,9 @@ public abstract class AbstractImmutableSetTest extends TestCase {
.add("a")
.add("a", "a")
.add("b");
- assertThat(builder.build()).has().exactly("a", "b").inOrder();
+ assertThat(builder.build()).containsExactly("a", "b").inOrder();
builder.add("a", "b", "c", "c");
- assertThat(builder.build()).has().exactly("a", "b", "c").inOrder();
+ assertThat(builder.build()).containsExactly("a", "b", "c").inOrder();
}
public void testBuilderAddAll() {
@@ -313,7 +313,7 @@ public abstract class AbstractImmutableSetTest extends TestCase {
.addAll(a)
.addAll(b)
.build();
- assertThat(set).has().exactly("a", "b", "c", "d", "e").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e").inOrder();
}
static final int LAST_COLOR_ADDED = 0x00BFFF;
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractSequentialIteratorTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractSequentialIteratorTest.java
index 81b9b85..689e6b9 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractSequentialIteratorTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractSequentialIteratorTest.java
@@ -37,7 +37,7 @@ public class AbstractSequentialIteratorTest extends TestCase {
return newDoubler(2, 32);
}
};
- assertThat(doubled).iteratesAs(2, 4, 8, 16, 32);
+ assertThat(doubled).containsExactly(2, 4, 8, 16, 32).inOrder();
}
public void testSampleCode() {
@@ -52,9 +52,11 @@ public class AbstractSequentialIteratorTest extends TestCase {
return powersOfTwo;
}
};
- assertThat(actual).iteratesAs(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
- 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304,
- 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824);
+ assertThat(actual)
+ .containsExactly(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
+ 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216,
+ 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824)
+ .inOrder();
}
public void testEmpty() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractTableReadTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractTableReadTest.java
index 342b112..fdf96e4 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractTableReadTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/AbstractTableReadTest.java
@@ -181,7 +181,7 @@ public abstract class AbstractTableReadTest extends TestCase {
public void testColumnSetPartialOverlap() {
table = create(
"foo", 1, 'a', "bar", 1, 'b', "foo", 2, 'c', "bar", 3, 'd');
- assertThat(table.columnKeySet()).has().exactly(1, 2, 3);
+ assertThat(table.columnKeySet()).containsExactly(1, 2, 3);
}
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimapTest.java
index 18339cc..191847f 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayListMultimapTest.java
@@ -82,9 +82,9 @@ public class ArrayListMultimapTest extends TestCase {
ListMultimap<String, Integer> multimap = create();
multimap.putAll("foo", asList(1, 2, 3, 4, 5));
List<Integer> list = multimap.get("foo");
- assertThat(multimap.get("foo")).has().exactly(1, 2, 3, 4, 5).inOrder();
+ assertThat(multimap.get("foo")).containsExactly(1, 2, 3, 4, 5).inOrder();
List<Integer> sublist = list.subList(0, 5);
- assertThat(sublist).has().exactly(1, 2, 3, 4, 5).inOrder();
+ assertThat(sublist).containsExactly(1, 2, 3, 4, 5).inOrder();
sublist.clear();
assertTrue(sublist.isEmpty());
@@ -153,8 +153,8 @@ public class ArrayListMultimapTest extends TestCase {
multimap.put("bar", 3);
multimap.trimToSize();
assertEquals(3, multimap.size());
- assertThat(multimap.get("foo")).has().exactly(1, 2).inOrder();
- assertThat(multimap.get("bar")).has().item(3);
+ assertThat(multimap.get("foo")).containsExactly(1, 2).inOrder();
+ assertThat(multimap.get("bar")).contains(3);
}
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayTableTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayTableTest.java
index 76cc870..817ce68 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayTableTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ArrayTableTest.java
@@ -279,13 +279,13 @@ public class ArrayTableTest extends AbstractTableTest {
public void testRowKeyList() {
ArrayTable<String, Integer, Character> table
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
- assertThat(table.rowKeyList()).has().exactly("foo", "bar", "cat").inOrder();
+ assertThat(table.rowKeyList()).containsExactly("foo", "bar", "cat").inOrder();
}
public void testColumnKeyList() {
ArrayTable<String, Integer, Character> table
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
- assertThat(table.columnKeyList()).has().exactly(1, 2, 3).inOrder();
+ assertThat(table.columnKeyList()).containsExactly(1, 2, 3).inOrder();
}
public void testGetMissingKeys() {
@@ -362,13 +362,13 @@ public class ArrayTableTest extends AbstractTableTest {
table.put("dog", 1, 'd');
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("Row dog not in [foo, bar, cat]", expected.getMessage());
+ assertThat(expected).hasMessage("Row dog not in [foo, bar, cat]");
}
try {
table.put("foo", 4, 'd');
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("Column 4 not in [1, 2, 3]", expected.getMessage());
+ assertThat(expected).hasMessage("Column 4 not in [1, 2, 3]");
}
assertFalse(table.containsValue('d'));
}
@@ -422,7 +422,7 @@ public class ArrayTableTest extends AbstractTableTest {
map.put(4, 'd');
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("Column 4 not in [1, 2, 3]", expected.getMessage());
+ assertThat(expected).hasMessage("Column 4 not in [1, 2, 3]");
}
}
@@ -433,7 +433,7 @@ public class ArrayTableTest extends AbstractTableTest {
map.put("dog", 'd');
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("Row dog not in [foo, bar, cat]", expected.getMessage());
+ assertThat(expected).hasMessage("Row dog not in [foo, bar, cat]");
}
}
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/Collections2Test.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/Collections2Test.java
index 31e19a4..b788479 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/Collections2Test.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/Collections2Test.java
@@ -79,7 +79,7 @@ public class Collections2Test extends TestCase {
Collections2.orderedPermutations(list);
assertEquals(1, permutationSet.size());
- assertThat(permutationSet).has().item(list);
+ assertThat(permutationSet).contains(list);
Iterator<List<Integer>> permutations = permutationSet.iterator();
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ContiguousSetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ContiguousSetTest.java
index ea7efe1..f2ef4ca 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ContiguousSetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ContiguousSetTest.java
@@ -67,6 +67,10 @@ public class ContiguousSetTest extends TestCase {
ContiguousSet.create(Range.openClosed(0, 3), NOT_EQUAL_TO_INTEGERS),
ContiguousSet.create(Range.open(0, 4), NOT_EQUAL_TO_INTEGERS),
ImmutableSortedSet.of(1, 2, 3))
+ .addEqualityGroup(
+ ContiguousSet.create(Range.closedOpen(1, 1), integers()),
+ ImmutableSortedSet.of(),
+ ImmutableSet.of())
.testEquals();
// not testing hashCode for these because it takes forever to compute
assertEquals(
@@ -108,15 +112,15 @@ public class ContiguousSetTest extends TestCase {
public void testHeadSet() {
ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, 3), integers());
assertThat(set.headSet(1)).isEmpty();
- assertThat(set.headSet(2)).has().item(1);
- assertThat(set.headSet(3)).has().exactly(1, 2).inOrder();
- assertThat(set.headSet(4)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.headSet(Integer.MAX_VALUE)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.headSet(1, true)).has().item(1);
- assertThat(set.headSet(2, true)).has().exactly(1, 2).inOrder();
- assertThat(set.headSet(3, true)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.headSet(4, true)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.headSet(Integer.MAX_VALUE, true)).has().exactly(1, 2, 3).inOrder();
+ assertThat(set.headSet(2)).contains(1);
+ assertThat(set.headSet(3)).containsExactly(1, 2).inOrder();
+ assertThat(set.headSet(4)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.headSet(Integer.MAX_VALUE)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.headSet(1, true)).contains(1);
+ assertThat(set.headSet(2, true)).containsExactly(1, 2).inOrder();
+ assertThat(set.headSet(3, true)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.headSet(4, true)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.headSet(Integer.MAX_VALUE, true)).containsExactly(1, 2, 3).inOrder();
}
public void testHeadSet_tooSmall() {
@@ -125,13 +129,13 @@ public class ContiguousSetTest extends TestCase {
public void testTailSet() {
ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, 3), integers());
- assertThat(set.tailSet(Integer.MIN_VALUE)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.tailSet(1)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.tailSet(2)).has().exactly(2, 3).inOrder();
- assertThat(set.tailSet(3)).has().item(3);
- assertThat(set.tailSet(Integer.MIN_VALUE, false)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.tailSet(1, false)).has().exactly(2, 3).inOrder();
- assertThat(set.tailSet(2, false)).has().item(3);
+ assertThat(set.tailSet(Integer.MIN_VALUE)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.tailSet(1)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.tailSet(2)).containsExactly(2, 3).inOrder();
+ assertThat(set.tailSet(3)).contains(3);
+ assertThat(set.tailSet(Integer.MIN_VALUE, false)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.tailSet(1, false)).containsExactly(2, 3).inOrder();
+ assertThat(set.tailSet(2, false)).contains(3);
assertThat(set.tailSet(3, false)).isEmpty();
}
@@ -141,19 +145,19 @@ public class ContiguousSetTest extends TestCase {
public void testSubSet() {
ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, 3), integers());
- assertThat(set.subSet(1, 4)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.subSet(2, 4)).has().exactly(2, 3).inOrder();
- assertThat(set.subSet(3, 4)).has().item(3);
+ assertThat(set.subSet(1, 4)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.subSet(2, 4)).containsExactly(2, 3).inOrder();
+ assertThat(set.subSet(3, 4)).contains(3);
assertThat(set.subSet(3, 3)).isEmpty();
- assertThat(set.subSet(2, 3)).has().item(2);
- assertThat(set.subSet(1, 3)).has().exactly(1, 2).inOrder();
- assertThat(set.subSet(1, 2)).has().item(1);
+ assertThat(set.subSet(2, 3)).contains(2);
+ assertThat(set.subSet(1, 3)).containsExactly(1, 2).inOrder();
+ assertThat(set.subSet(1, 2)).contains(1);
assertThat(set.subSet(2, 2)).isEmpty();
- assertThat(set.subSet(Integer.MIN_VALUE, Integer.MAX_VALUE)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.subSet(1, true, 3, true)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.subSet(1, false, 3, true)).has().exactly(2, 3).inOrder();
- assertThat(set.subSet(1, true, 3, false)).has().exactly(1, 2).inOrder();
- assertThat(set.subSet(1, false, 3, false)).has().item(2);
+ assertThat(set.subSet(Integer.MIN_VALUE, Integer.MAX_VALUE)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.subSet(1, true, 3, true)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.subSet(1, false, 3, true)).containsExactly(2, 3).inOrder();
+ assertThat(set.subSet(1, true, 3, false)).containsExactly(1, 2).inOrder();
+ assertThat(set.subSet(1, false, 3, false)).contains(2);
}
public void testSubSet_outOfOrder() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EnumBiMapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EnumBiMapTest.java
index bed6626..89bd9a7 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EnumBiMapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EnumBiMapTest.java
@@ -173,16 +173,16 @@ public class EnumBiMapTest extends TestCase {
// forward map ordered by currency
assertThat(bimap.keySet())
- .has().exactly(Currency.DOLLAR, Currency.FRANC, Currency.PESO).inOrder();
+ .containsExactly(Currency.DOLLAR, Currency.FRANC, Currency.PESO).inOrder();
// forward map ordered by currency (even for country values)
assertThat(bimap.values())
- .has().exactly(Country.CANADA, Country.SWITZERLAND, Country.CHILE).inOrder();
+ .containsExactly(Country.CANADA, Country.SWITZERLAND, Country.CHILE).inOrder();
// backward map ordered by country
assertThat(bimap.inverse().keySet())
- .has().exactly(Country.CANADA, Country.CHILE, Country.SWITZERLAND).inOrder();
+ .containsExactly(Country.CANADA, Country.CHILE, Country.SWITZERLAND).inOrder();
// backward map ordered by country (even for currency values)
assertThat(bimap.inverse().values())
- .has().exactly(Currency.DOLLAR, Currency.PESO, Currency.FRANC).inOrder();
+ .containsExactly(Currency.DOLLAR, Currency.PESO, Currency.FRANC).inOrder();
}
public void testKeySetIteratorRemove() {
@@ -200,16 +200,16 @@ public class EnumBiMapTest extends TestCase {
// forward map ordered by currency
assertThat(bimap.keySet())
- .has().exactly(Currency.FRANC, Currency.PESO).inOrder();
+ .containsExactly(Currency.FRANC, Currency.PESO).inOrder();
// forward map ordered by currency (even for country values)
assertThat(bimap.values())
- .has().exactly(Country.SWITZERLAND, Country.CHILE).inOrder();
+ .containsExactly(Country.SWITZERLAND, Country.CHILE).inOrder();
// backward map ordered by country
assertThat(bimap.inverse().keySet())
- .has().exactly(Country.CHILE, Country.SWITZERLAND).inOrder();
+ .containsExactly(Country.CHILE, Country.SWITZERLAND).inOrder();
// backward map ordered by country (even for currency values)
assertThat(bimap.inverse().values())
- .has().exactly(Currency.PESO, Currency.FRANC).inOrder();
+ .containsExactly(Currency.PESO, Currency.FRANC).inOrder();
}
public void testValuesIteratorRemove() {
@@ -228,16 +228,16 @@ public class EnumBiMapTest extends TestCase {
// forward map ordered by currency
assertThat(bimap.keySet())
- .has().exactly(Currency.DOLLAR, Currency.PESO).inOrder();
+ .containsExactly(Currency.DOLLAR, Currency.PESO).inOrder();
// forward map ordered by currency (even for country values)
assertThat(bimap.values())
- .has().exactly(Country.CANADA, Country.CHILE).inOrder();
+ .containsExactly(Country.CANADA, Country.CHILE).inOrder();
// backward map ordered by country
assertThat(bimap.inverse().keySet())
- .has().exactly(Country.CANADA, Country.CHILE).inOrder();
+ .containsExactly(Country.CANADA, Country.CHILE).inOrder();
// backward map ordered by country (even for currency values)
assertThat(bimap.inverse().values())
- .has().exactly(Currency.DOLLAR, Currency.PESO).inOrder();
+ .containsExactly(Currency.DOLLAR, Currency.PESO).inOrder();
}
public void testEntrySet() {
diff --git a/guava-tests/test/com/google/common/collect/EvictingQueueTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EvictingQueueTest.java
similarity index 91%
copy from guava-tests/test/com/google/common/collect/EvictingQueueTest.java
copy to guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EvictingQueueTest.java
index 9567dee..598622e 100644
--- a/guava-tests/test/com/google/common/collect/EvictingQueueTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/EvictingQueueTest.java
@@ -18,7 +18,7 @@ package com.google.common.collect;
import static java.util.Arrays.asList;
-import com.google.common.testing.NullPointerTester;
+import com.google.common.annotations.GwtCompatible;
import com.google.common.testing.SerializableTester;
import junit.framework.TestCase;
@@ -30,6 +30,7 @@ import java.util.NoSuchElementException;
*
* @author Kurt Alfred Kluever
*/
+ at GwtCompatible(emulated = true)
public class EvictingQueueTest extends TestCase {
public void testCreateWithNegativeSize() throws Exception {
@@ -157,16 +158,6 @@ public class EvictingQueueTest extends TestCase {
assertEquals(1, queue.remainingCapacity());
}
- public void testNullPointerExceptions() {
- NullPointerTester tester = new NullPointerTester();
- tester.testAllPublicStaticMethods(EvictingQueue.class);
- tester.testAllPublicConstructors(EvictingQueue.class);
- EvictingQueue<String> queue = EvictingQueue.create(5);
- // The queue must be non-empty so it throws a NPE correctly
- queue.add("one");
- tester.testAllPublicInstanceMethods(queue);
- }
-
public void testSerialization() {
EvictingQueue<String> original = EvictingQueue.create(5);
original.add("one");
@@ -181,3 +172,4 @@ public class EvictingQueueTest extends TestCase {
assertTrue(copy.isEmpty());
}
}
+
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/HashBiMapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/HashBiMapTest.java
index 428805d..672013d 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/HashBiMapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/HashBiMapTest.java
@@ -102,5 +102,13 @@ public class HashBiMapTest extends TestCase {
iterator.remove(); // removes the updated entry
assertTrue(map.isEmpty());
}
+
+ public void testInverseEntrySetValue() {
+ BiMap<Integer, String> map = HashBiMap.create();
+ map.put(1, "one");
+ Entry<String, Integer> inverseEntry = Iterables.getOnlyElement(map.inverse().entrySet());
+ inverseEntry.setValue(2);
+ assertEquals(Integer.valueOf(2), inverseEntry.getValue());
+ }
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMapTest.java
index 514effe..f8817cb 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableBiMapTest.java
@@ -131,6 +131,13 @@ public class ImmutableBiMapTest extends TestCase {
assertMapEquals(map.inverse(), 1, "one");
}
+ public void testBuilder_withImmutableEntry() {
+ ImmutableBiMap<String, Integer> map = new Builder<String, Integer>()
+ .put(Maps.immutableEntry("one", 1))
+ .build();
+ assertMapEquals(map, "one", 1);
+ }
+
public void testBuilder() {
ImmutableBiMap<String, Integer> map
= ImmutableBiMap.<String, Integer>builder()
@@ -145,6 +152,41 @@ public class ImmutableBiMapTest extends TestCase {
assertMapEquals(map.inverse(),
1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
}
+
+ public void testBuilder_orderEntriesByValue() {
+ ImmutableBiMap<String, Integer> map =
+ ImmutableBiMap.<String, Integer>builder()
+ .orderEntriesByValue(Ordering.natural())
+ .put("three", 3)
+ .put("one", 1)
+ .put("five", 5)
+ .put("four", 4)
+ .put("two", 2)
+ .build();
+ assertMapEquals(map,
+ "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
+ assertMapEquals(map.inverse(),
+ 1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
+ }
+
+ public void testBuilder_orderEntriesByValueAfterExactSizeBuild() {
+ ImmutableBiMap.Builder<String, Integer> builder =
+ new ImmutableBiMap.Builder<String, Integer>(2).put("four", 4).put("one", 1);
+ ImmutableMap<String, Integer> keyOrdered = builder.build();
+ ImmutableMap<String, Integer> valueOrdered =
+ builder.orderEntriesByValue(Ordering.natural()).build();
+ assertMapEquals(keyOrdered, "four", 4, "one", 1);
+ assertMapEquals(valueOrdered, "one", 1, "four", 4);
+ }
+
+ public void testBuilder_orderEntriesByValue_usedTwiceFails() {
+ ImmutableBiMap.Builder<String, Integer> builder = new Builder<String, Integer>()
+ .orderEntriesByValue(Ordering.natural());
+ try {
+ builder.orderEntriesByValue(Ordering.natural());
+ fail("Expected IllegalStateException");
+ } catch (IllegalStateException expected) {}
+ }
public void testBuilderPutAllWithEmptyMap() {
ImmutableBiMap<String, Integer> map = new Builder<String, Integer>()
@@ -235,7 +277,7 @@ public class ImmutableBiMapTest extends TestCase {
builder.build();
fail();
} catch (IllegalArgumentException expected) {
- assertTrue(expected.getMessage().contains("one"));
+ assertThat(expected.getMessage()).contains("one");
}
}
@@ -308,7 +350,7 @@ public class ImmutableBiMapTest extends TestCase {
ImmutableBiMap.of("one", 1, "one", 1);
fail();
} catch (IllegalArgumentException expected) {
- assertTrue(expected.getMessage().contains("one"));
+ assertThat(expected.getMessage()).contains("one");
}
}
@@ -382,7 +424,7 @@ public class ImmutableBiMapTest extends TestCase {
ImmutableBiMap.copyOf(map);
fail();
} catch (IllegalArgumentException expected) {
- assertTrue(expected.getMessage().contains("1"));
+ assertThat(expected.getMessage()).contains("1");
}
}
}
@@ -404,7 +446,7 @@ public class ImmutableBiMapTest extends TestCase {
ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4));
Set<String> keys = bimap.keySet();
assertEquals(Sets.newHashSet("one", "two", "three", "four"), keys);
- assertThat(keys).has().exactly("one", "two", "three", "four").inOrder();
+ assertThat(keys).containsExactly("one", "two", "three", "four").inOrder();
}
public void testValues() {
@@ -412,7 +454,7 @@ public class ImmutableBiMapTest extends TestCase {
ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4));
Set<Integer> values = bimap.values();
assertEquals(Sets.newHashSet(1, 2, 3, 4), values);
- assertThat(values).has().exactly(1, 2, 3, 4).inOrder();
+ assertThat(values).containsExactly(1, 2, 3, 4).inOrder();
}
public void testDoubleInverse() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableEnumMapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableEnumMapTest.java
index 1233a93..9a4d548 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableEnumMapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableEnumMapTest.java
@@ -55,7 +55,7 @@ public class ImmutableEnumMapTest extends TestCase {
ImmutableMap<AnEnum, String> map = Maps.immutableEnumMap(
ImmutableMap.of(AnEnum.C, "c", AnEnum.A, "a", AnEnum.E, "e"));
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
Helpers.mapEntry(AnEnum.A, "a"),
Helpers.mapEntry(AnEnum.C, "c"),
Helpers.mapEntry(AnEnum.E, "e")).inOrder();
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimapTest.java
index b71caa8..0a66661 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableListMultimapTest.java
@@ -47,6 +47,13 @@ public class ImmutableListMultimapTest extends TestCase {
return builder.build();
}
}
+ public static class ImmutableListMultimapCopyOfEntriesGenerator
+ extends TestStringListMultimapGenerator {
+ @Override
+ protected ListMultimap<String, String> create(Entry<String, String>[] entries) {
+ return ImmutableListMultimap.copyOf(Arrays.asList(entries));
+ }
+ }
public void testBuilder_withImmutableEntry() {
ImmutableListMultimap<String, Integer> multimap = new Builder<String, Integer>()
@@ -239,10 +246,10 @@ public class ImmutableListMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("b", 6);
ImmutableListMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
- assertThat(multimap.values()).has().exactly(2, 4, 3, 6, 5, 2).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("b")).has().exactly(3, 6).inOrder();
+ assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+ assertThat(multimap.values()).containsExactly(2, 4, 3, 6, 5, 2).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("b")).containsExactly(3, 6).inOrder();
}
public void testBuilderOrderKeysByDuplicates() {
@@ -261,10 +268,10 @@ public class ImmutableListMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("bb", 6);
ImmutableListMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("d", "a", "bb", "cc").inOrder();
- assertThat(multimap.values()).has().exactly(2, 5, 2, 3, 6, 4).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("bb")).has().exactly(3, 6).inOrder();
+ assertThat(multimap.keySet()).containsExactly("d", "a", "bb", "cc").inOrder();
+ assertThat(multimap.values()).containsExactly(2, 5, 2, 3, 6, 4).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("bb")).containsExactly(3, 6).inOrder();
}
public void testBuilderOrderValuesBy() {
@@ -278,10 +285,10 @@ public class ImmutableListMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("b", 6);
ImmutableListMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("b", "d", "a", "c").inOrder();
- assertThat(multimap.values()).has().exactly(6, 3, 2, 5, 2, 4).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+ assertThat(multimap.keySet()).containsExactly("b", "d", "a", "c").inOrder();
+ assertThat(multimap.values()).containsExactly(6, 3, 2, 5, 2, 4).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
}
public void testBuilderOrderKeysAndValuesBy() {
@@ -296,10 +303,10 @@ public class ImmutableListMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("b", 6);
ImmutableListMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
- assertThat(multimap.values()).has().exactly(2, 4, 6, 3, 5, 2).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+ assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+ assertThat(multimap.values()).containsExactly(2, 4, 6, 3, 5, 2).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
}
public void testCopyOf() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapTest.java
index 5acce3a..14ce007 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMapTest.java
@@ -119,14 +119,14 @@ public class ImmutableMapTest extends TestCase {
@Override protected Map<Object, Integer> makePopulatedMap() {
Colliders colliders = new Colliders();
return ImmutableMap.of(
- colliders.e0, 0,
- colliders.e1, 1,
- colliders.e2, 2,
- colliders.e3, 3);
+ colliders.e0(), 0,
+ colliders.e1(), 1,
+ colliders.e2(), 2,
+ colliders.e3(), 3);
}
@Override protected Object getKeyNotInPopulatedMap() {
- return new Colliders().e4;
+ return new Colliders().e4();
}
@Override protected Integer getValueNotInPopulatedMap() {
@@ -159,6 +159,39 @@ public class ImmutableMapTest extends TestCase {
assertMapEquals(map,
"one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
}
+
+ public void testBuilder_orderEntriesByValue() {
+ ImmutableMap<String, Integer> map = new Builder<String, Integer>()
+ .orderEntriesByValue(Ordering.natural())
+ .put("three", 3)
+ .put("one", 1)
+ .put("five", 5)
+ .put("four", 4)
+ .put("two", 2)
+ .build();
+ assertMapEquals(map,
+ "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
+ }
+
+ public void testBuilder_orderEntriesByValueAfterExactSizeBuild() {
+ Builder<String, Integer> builder = new Builder<String, Integer>(2)
+ .put("four", 4)
+ .put("one", 1);
+ ImmutableMap<String, Integer> keyOrdered = builder.build();
+ ImmutableMap<String, Integer> valueOrdered =
+ builder.orderEntriesByValue(Ordering.natural()).build();
+ assertMapEquals(keyOrdered, "four", 4, "one", 1);
+ assertMapEquals(valueOrdered, "one", 1, "four", 4);
+ }
+
+ public void testBuilder_orderEntriesByValue_usedTwiceFails() {
+ ImmutableMap.Builder<String, Integer> builder = new Builder<String, Integer>()
+ .orderEntriesByValue(Ordering.natural());
+ try {
+ builder.orderEntriesByValue(Ordering.natural());
+ fail("Expected IllegalStateException");
+ } catch (IllegalStateException expected) {}
+ }
public void testBuilder_withImmutableEntry() {
ImmutableMap<String, Integer> map = new Builder<String, Integer>()
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimapTest.java
index 06b7294..14f0252 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultimapTest.java
@@ -101,18 +101,18 @@ public class ImmutableMultimapTest extends TestCase {
public void testUnhashableSingletonValue() {
SampleElements<UnhashableObject> unhashables = new Unhashables();
Multimap<Integer, UnhashableObject> multimap = ImmutableMultimap.of(
- 0, unhashables.e0);
+ 0, unhashables.e0());
assertEquals(1, multimap.get(0).size());
- assertTrue(multimap.get(0).contains(unhashables.e0));
+ assertTrue(multimap.get(0).contains(unhashables.e0()));
}
public void testUnhashableMixedValues() {
SampleElements<UnhashableObject> unhashables = new Unhashables();
Multimap<Integer, Object> multimap = ImmutableMultimap.<Integer, Object>of(
- 0, unhashables.e0, 2, "hey you", 0, unhashables.e1);
+ 0, unhashables.e0(), 2, "hey you", 0, unhashables.e1());
assertEquals(2, multimap.get(0).size());
- assertTrue(multimap.get(0).contains(unhashables.e0));
- assertTrue(multimap.get(0).contains(unhashables.e1));
+ assertTrue(multimap.get(0).contains(unhashables.e0()));
+ assertTrue(multimap.get(0).contains(unhashables.e1()));
assertTrue(multimap.get(2).contains("hey you"));
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultisetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultisetTest.java
index 5396ef2..ab42678 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultisetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableMultisetTest.java
@@ -354,7 +354,7 @@ public class ImmutableMultisetTest extends TestCase {
public void testIterationOrder() {
Collection<String> c = ImmutableMultiset.of("a", "b", "a");
- assertThat(c).has().exactly("a", "a", "b").inOrder();
+ assertThat(c).containsExactly("a", "a", "b").inOrder();
}
public void testMultisetWrites() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimapTest.java
index 1b1b586..6365e35 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetMultimapTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.ImmutableSetMultimap.Builder;
+import com.google.common.collect.testing.google.TestStringSetMultimapGenerator;
import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
import com.google.common.testing.EqualsTester;
@@ -36,6 +37,25 @@ import java.util.Map.Entry;
*/
@GwtCompatible(emulated = true)
public class ImmutableSetMultimapTest extends TestCase {
+ private static final class ImmutableSetMultimapGenerator extends
+ TestStringSetMultimapGenerator {
+ @Override
+ protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
+ ImmutableSetMultimap.Builder<String, String> builder = ImmutableSetMultimap.builder();
+ for (Entry<String, String> entry : entries) {
+ builder.put(entry.getKey(), entry.getValue());
+ }
+ return builder.build();
+ }
+ }
+
+ private static final class ImmutableSetMultimapCopyOfEntriesGenerator extends
+ TestStringSetMultimapGenerator {
+ @Override
+ protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
+ return ImmutableSetMultimap.copyOf(Arrays.asList(entries));
+ }
+ }
public void testBuilder_withImmutableEntry() {
ImmutableSetMultimap<String, Integer> multimap = new Builder<String, Integer>()
@@ -216,13 +236,13 @@ public class ImmutableSetMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("b", 6);
ImmutableSetMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
- assertThat(multimap.values()).has().exactly(2, 4, 3, 6, 5, 2).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("b")).has().exactly(3, 6).inOrder();
- assertFalse(multimap.get("a") instanceof ImmutableSortedSet);
- assertFalse(multimap.get("x") instanceof ImmutableSortedSet);
- assertFalse(multimap.asMap().get("a") instanceof ImmutableSortedSet);
+ assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+ assertThat(multimap.values()).containsExactly(2, 4, 3, 6, 5, 2).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("b")).containsExactly(3, 6).inOrder();
+ assertThat(multimap.get("a")).isNotInstanceOf(ImmutableSortedSet.class);
+ assertThat(multimap.get("x")).isNotInstanceOf(ImmutableSortedSet.class);
+ assertThat(multimap.asMap().get("a")).isNotInstanceOf(ImmutableSortedSet.class);
}
public void testBuilderOrderKeysByDuplicates() {
@@ -241,13 +261,13 @@ public class ImmutableSetMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("bb", 6);
ImmutableSetMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("d", "a", "bb", "cc").inOrder();
- assertThat(multimap.values()).has().exactly(2, 5, 2, 3, 6, 4).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("bb")).has().exactly(3, 6).inOrder();
- assertFalse(multimap.get("a") instanceof ImmutableSortedSet);
- assertFalse(multimap.get("x") instanceof ImmutableSortedSet);
- assertFalse(multimap.asMap().get("a") instanceof ImmutableSortedSet);
+ assertThat(multimap.keySet()).containsExactly("d", "a", "bb", "cc").inOrder();
+ assertThat(multimap.values()).containsExactly(2, 5, 2, 3, 6, 4).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("bb")).containsExactly(3, 6).inOrder();
+ assertThat(multimap.get("a")).isNotInstanceOf(ImmutableSortedSet.class);
+ assertThat(multimap.get("x")).isNotInstanceOf(ImmutableSortedSet.class);
+ assertThat(multimap.asMap().get("a")).isNotInstanceOf(ImmutableSortedSet.class);
}
public void testBuilderOrderValuesBy() {
@@ -261,10 +281,10 @@ public class ImmutableSetMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("b", 6);
ImmutableSetMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("b", "d", "a", "c").inOrder();
- assertThat(multimap.values()).has().exactly(6, 3, 2, 5, 2, 4).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+ assertThat(multimap.keySet()).containsExactly("b", "d", "a", "c").inOrder();
+ assertThat(multimap.values()).containsExactly(6, 3, 2, 5, 2, 4).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
assertTrue(multimap.get("a") instanceof ImmutableSortedSet);
assertEquals(Collections.reverseOrder(),
((ImmutableSortedSet<Integer>) multimap.get("a")).comparator());
@@ -288,10 +308,10 @@ public class ImmutableSetMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("b", 6);
ImmutableSetMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
- assertThat(multimap.values()).has().exactly(2, 4, 6, 3, 5, 2).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+ assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+ assertThat(multimap.values()).containsExactly(2, 4, 6, 3, 5, 2).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
assertTrue(multimap.get("a") instanceof ImmutableSortedSet);
assertEquals(Collections.reverseOrder(),
((ImmutableSortedSet<Integer>) multimap.get("a")).comparator());
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetTest.java
index 15cf351..d2fa8aa 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSetTest.java
@@ -103,7 +103,7 @@ public class ImmutableSetTest extends AbstractImmutableSetTest {
// now we'll get the varargs overload
ImmutableSet<String> set = ImmutableSet.of(
"a", "b", "c", "c", "c", "c", "b", "b", "a", "a", "c", "c", "c", "a");
- assertThat(set).has().exactly("a", "b", "c").inOrder();
+ assertThat(set).containsExactly("a", "b", "c").inOrder();
}
public void testCreation_arrayOfArray() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMapTest.java
index 1b76d45..603f6ac 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedMapTest.java
@@ -212,6 +212,14 @@ public class ImmutableSortedMapTest extends TestCase {
assertMapEquals(map,
"five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
}
+
+ public void testBuilder_orderEntriesByValueFails() {
+ ImmutableSortedMap.Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
+ try {
+ builder.orderEntriesByValue(Ordering.natural());
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {}
+ }
public void testBuilder_withImmutableEntry() {
ImmutableSortedMap<String, Integer> map =
@@ -611,7 +619,7 @@ public class ImmutableSortedMapTest extends TestCase {
public void testHeadMapInclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", true);
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
Maps.immutableEntry("one", 1),
Maps.immutableEntry("three", 3)).inOrder();
}
@@ -620,14 +628,14 @@ public class ImmutableSortedMapTest extends TestCase {
public void testHeadMapExclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", false);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1)).inOrder();
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("one", 1));
}
@SuppressWarnings("unchecked") // varargs
public void testTailMapInclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", true);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3),
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("three", 3),
Maps.immutableEntry("two", 2)).inOrder();
}
@@ -635,21 +643,21 @@ public class ImmutableSortedMapTest extends TestCase {
public void testTailMapExclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", false);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("two", 2)).inOrder();
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("two", 2));
}
@SuppressWarnings("unchecked") // varargs
public void testSubMapExclusiveExclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", false);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3)).inOrder();
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("three", 3));
}
@SuppressWarnings("unchecked") // varargs
public void testSubMapInclusiveExclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", false);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1),
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("one", 1),
Maps.immutableEntry("three", 3)).inOrder();
}
@@ -657,7 +665,7 @@ public class ImmutableSortedMapTest extends TestCase {
public void testSubMapExclusiveInclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", true);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3),
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("three", 3),
Maps.immutableEntry("two", 2)).inOrder();
}
@@ -665,7 +673,7 @@ public class ImmutableSortedMapTest extends TestCase {
public void testSubMapInclusiveInclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", true);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1),
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("one", 1),
Maps.immutableEntry("three", 3), Maps.immutableEntry("two", 2)).inOrder();
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSetTest.java
index 89d5448..a07df11 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableSortedSetTest.java
@@ -145,7 +145,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testSingle_headSet() {
SortedSet<String> set = of("e");
assertTrue(set.headSet("g") instanceof ImmutableSortedSet);
- assertThat(set.headSet("g")).has().item("e");
+ assertThat(set.headSet("g")).contains("e");
assertSame(of(), set.headSet("c"));
assertSame(of(), set.headSet("e"));
}
@@ -153,16 +153,16 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testSingle_tailSet() {
SortedSet<String> set = of("e");
assertTrue(set.tailSet("c") instanceof ImmutableSortedSet);
- assertThat(set.tailSet("c")).has().item("e");
- assertThat(set.tailSet("e")).has().item("e");
+ assertThat(set.tailSet("c")).contains("e");
+ assertThat(set.tailSet("e")).contains("e");
assertSame(of(), set.tailSet("g"));
}
public void testSingle_subSet() {
SortedSet<String> set = of("e");
assertTrue(set.subSet("c", "g") instanceof ImmutableSortedSet);
- assertThat(set.subSet("c", "g")).has().item("e");
- assertThat(set.subSet("e", "g")).has().item("e");
+ assertThat(set.subSet("c", "g")).contains("e");
+ assertThat(set.subSet("e", "g")).contains("e");
assertSame(of(), set.subSet("f", "g"));
assertSame(of(), set.subSet("c", "e"));
assertSame(of(), set.subSet("c", "d"));
@@ -180,7 +180,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testOf_ordering() {
SortedSet<String> set = of("e", "a", "f", "b", "d", "c");
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
/*
@@ -229,7 +229,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testOf_ordering_dupes() {
SortedSet<String> set = of("e", "a", "e", "f", "b", "b", "d", "a", "c");
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
public void testOf_comparator() {
@@ -240,8 +240,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testOf_headSet() {
SortedSet<String> set = of("e", "f", "b", "d", "c");
assertTrue(set.headSet("e") instanceof ImmutableSortedSet);
- assertThat(set.headSet("e")).has().exactly("b", "c", "d").inOrder();
- assertThat(set.headSet("g")).has().exactly("b", "c", "d", "e", "f").inOrder();
+ assertThat(set.headSet("e")).containsExactly("b", "c", "d").inOrder();
+ assertThat(set.headSet("g")).containsExactly("b", "c", "d", "e", "f").inOrder();
assertSame(of(), set.headSet("a"));
assertSame(of(), set.headSet("b"));
}
@@ -249,16 +249,16 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testOf_tailSet() {
SortedSet<String> set = of("e", "f", "b", "d", "c");
assertTrue(set.tailSet("e") instanceof ImmutableSortedSet);
- assertThat(set.tailSet("e")).has().exactly("e", "f").inOrder();
- assertThat(set.tailSet("a")).has().exactly("b", "c", "d", "e", "f").inOrder();
+ assertThat(set.tailSet("e")).containsExactly("e", "f").inOrder();
+ assertThat(set.tailSet("a")).containsExactly("b", "c", "d", "e", "f").inOrder();
assertSame(of(), set.tailSet("g"));
}
public void testOf_subSet() {
SortedSet<String> set = of("e", "f", "b", "d", "c");
assertTrue(set.subSet("c", "e") instanceof ImmutableSortedSet);
- assertThat(set.subSet("c", "e")).has().exactly("c", "d").inOrder();
- assertThat(set.subSet("a", "g")).has().exactly("b", "c", "d", "e", "f").inOrder();
+ assertThat(set.subSet("c", "e")).containsExactly("c", "d").inOrder();
+ assertThat(set.subSet("a", "g")).containsExactly("b", "c", "d", "e", "f").inOrder();
assertSame(of(), set.subSet("a", "b"));
assertSame(of(), set.subSet("g", "h"));
assertSame(of(), set.subSet("c", "c"));
@@ -284,14 +284,14 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testExplicit_ordering() {
SortedSet<String> set = ImmutableSortedSet.orderedBy(STRING_LENGTH).add(
"in", "the", "quick", "jumped", "over", "a").build();
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
}
public void testExplicit_ordering_dupes() {
SortedSet<String> set = ImmutableSortedSet.orderedBy(STRING_LENGTH).add(
"in", "the", "quick", "brown", "fox", "jumped",
"over", "a", "lazy", "dog").build();
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
}
public void testExplicit_contains() {
@@ -321,9 +321,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
"in", "the", "quick", "jumped", "over", "a").build();
assertTrue(set.headSet("a") instanceof ImmutableSortedSet);
assertTrue(set.headSet("fish") instanceof ImmutableSortedSet);
- assertThat(set.headSet("fish")).has().exactly("a", "in", "the").inOrder();
- assertThat(set.headSet("california")).has()
- .exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set.headSet("fish")).containsExactly("a", "in", "the").inOrder();
+ assertThat(set.headSet("california"))
+ .containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
assertTrue(set.headSet("a").isEmpty());
assertTrue(set.headSet("").isEmpty());
}
@@ -333,9 +333,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
"in", "the", "quick", "jumped", "over", "a").build();
assertTrue(set.tailSet("california") instanceof ImmutableSortedSet);
assertTrue(set.tailSet("fish") instanceof ImmutableSortedSet);
- assertThat(set.tailSet("fish")).has().exactly("over", "quick", "jumped").inOrder();
+ assertThat(set.tailSet("fish")).containsExactly("over", "quick", "jumped").inOrder();
assertThat(
- set.tailSet("a")).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ set.tailSet("a")).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
assertTrue(set.tailSet("california").isEmpty());
}
@@ -344,9 +344,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
"in", "the", "quick", "jumped", "over", "a").build();
assertTrue(set.subSet("the", "quick") instanceof ImmutableSortedSet);
assertTrue(set.subSet("", "b") instanceof ImmutableSortedSet);
- assertThat(set.subSet("the", "quick")).has().exactly("the", "over").inOrder();
+ assertThat(set.subSet("the", "quick")).containsExactly("the", "over").inOrder();
assertThat(set.subSet("a", "california"))
- .has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ .containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
assertTrue(set.subSet("", "b").isEmpty());
assertTrue(set.subSet("vermont", "california").isEmpty());
assertTrue(set.subSet("aaa", "zzz").isEmpty());
@@ -372,13 +372,13 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testCopyOf_ordering() {
SortedSet<String> set =
copyOf(asList("e", "a", "f", "b", "d", "c"));
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
public void testCopyOf_ordering_dupes() {
SortedSet<String> set =
copyOf(asList("e", "a", "e", "f", "b", "b", "d", "a", "c"));
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
public void testCopyOf_subSet() {
@@ -409,13 +409,13 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testCopyOf_iterator_ordering() {
SortedSet<String> set = copyOf(asIterator("e", "a", "f", "b", "d", "c"));
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
public void testCopyOf_iterator_ordering_dupes() {
SortedSet<String> set =
copyOf(asIterator("e", "a", "e", "f", "b", "b", "d", "a", "c"));
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
public void testCopyOf_iterator_comparator() {
@@ -426,7 +426,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testCopyOf_sortedSet_ordering() {
SortedSet<String> set =
copyOf(Sets.newTreeSet(asList("e", "a", "f", "b", "d", "c")));
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
public void testCopyOf_sortedSet_comparator() {
@@ -438,7 +438,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
SortedSet<String> set =
ImmutableSortedSet.copyOf(STRING_LENGTH, asList(
"in", "the", "quick", "jumped", "over", "a"));
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
}
public void testCopyOfExplicit_ordering_dupes() {
@@ -446,7 +446,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
ImmutableSortedSet.copyOf(STRING_LENGTH, asList(
"in", "the", "quick", "brown", "fox", "jumped", "over", "a",
"lazy", "dog"));
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
}
public void testCopyOfExplicit_comparator() {
@@ -460,7 +460,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
SortedSet<String> set =
ImmutableSortedSet.copyOf(STRING_LENGTH, asIterator(
"in", "the", "quick", "jumped", "over", "a"));
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
}
public void testCopyOfExplicit_iterator_ordering_dupes() {
@@ -468,7 +468,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
ImmutableSortedSet.copyOf(STRING_LENGTH, asIterator(
"in", "the", "quick", "brown", "fox", "jumped", "over", "a",
"lazy", "dog"));
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
}
public void testCopyOfExplicit_iterator_comparator() {
@@ -482,14 +482,14 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
SortedSet<String> input = Sets.newTreeSet(STRING_LENGTH);
Collections.addAll(input, "in", "the", "quick", "jumped", "over", "a");
SortedSet<String> set = copyOf(input);
- assertThat(set).has().exactly("a", "in", "jumped", "over", "quick", "the").inOrder();
+ assertThat(set).containsExactly("a", "in", "jumped", "over", "quick", "the").inOrder();
}
public void testCopyOfSorted_natural_ordering() {
SortedSet<String> input = Sets.newTreeSet(
asList("in", "the", "quick", "jumped", "over", "a"));
SortedSet<String> set = ImmutableSortedSet.copyOfSorted(input);
- assertThat(set).has().exactly("a", "in", "jumped", "over", "quick", "the").inOrder();
+ assertThat(set).containsExactly("a", "in", "jumped", "over", "quick", "the").inOrder();
}
public void testCopyOfSorted_natural_comparator() {
@@ -503,7 +503,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
SortedSet<String> input = Sets.newTreeSet(STRING_LENGTH);
Collections.addAll(input, "in", "the", "quick", "jumped", "over", "a");
SortedSet<String> set = ImmutableSortedSet.copyOfSorted(input);
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
assertSame(STRING_LENGTH, set.comparator());
}
@@ -591,7 +591,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testReverseOrder() {
SortedSet<String> set = ImmutableSortedSet.<String>reverseOrder()
.add("a", "b", "c").build();
- assertThat(set).has().exactly("c", "b", "a").inOrder();
+ assertThat(set).containsExactly("c", "b", "a").inOrder();
assertEquals(Ordering.natural().reverse(), set.comparator());
}
@@ -606,13 +606,13 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testSupertypeComparator() {
SortedSet<Integer> set = new ImmutableSortedSet.Builder<Integer>(TO_STRING)
.add(3, 12, 101, 44).build();
- assertThat(set).has().exactly(101, 12, 3, 44).inOrder();
+ assertThat(set).containsExactly(101, 12, 3, 44).inOrder();
}
public void testSupertypeComparatorSubtypeElements() {
SortedSet<Number> set = new ImmutableSortedSet.Builder<Number>(TO_STRING)
.add(3, 12, 101, 44).build();
- assertThat(set).has().exactly(101, 12, 3, 44).inOrder();
+ assertThat(set).containsExactly(101, 12, 3, 44).inOrder();
}
@Override <E extends Comparable<E>> ImmutableSortedSet.Builder<E> builder() {
@@ -735,7 +735,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
Arrays.sort(strings);
for (int i = 0; i < strings.length; i++) {
assertThat(set.headSet(strings[i], true))
- .has().exactlyAs(sortedNumberNames(0, i + 1)).inOrder();
+ .containsExactlyElementsIn(sortedNumberNames(0, i + 1))
+ .inOrder();
}
}
@@ -744,8 +745,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
ImmutableSortedSet<String> set = ImmutableSortedSet.copyOf(strings);
Arrays.sort(strings);
for (int i = 0; i < strings.length; i++) {
- assertThat(set.headSet(strings[i], false)).has().exactlyAs(
- sortedNumberNames(0, i)).inOrder();
+ assertThat(set.headSet(strings[i], false))
+ .containsExactlyElementsIn(sortedNumberNames(0, i))
+ .inOrder();
}
}
@@ -754,8 +756,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
ImmutableSortedSet<String> set = ImmutableSortedSet.copyOf(strings);
Arrays.sort(strings);
for (int i = 0; i < strings.length; i++) {
- assertThat(set.tailSet(strings[i], true)).has().exactlyAs(
- sortedNumberNames(i, strings.length)).inOrder();
+ assertThat(set.tailSet(strings[i], true))
+ .containsExactlyElementsIn(sortedNumberNames(i, strings.length))
+ .inOrder();
}
}
@@ -764,8 +767,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
ImmutableSortedSet<String> set = ImmutableSortedSet.copyOf(strings);
Arrays.sort(strings);
for (int i = 0; i < strings.length; i++) {
- assertThat(set.tailSet(strings[i], false)).has().exactlyAs(
- sortedNumberNames(i + 1, strings.length)).inOrder();
+ assertThat(set.tailSet(strings[i], false))
+ .containsExactlyElementsIn(sortedNumberNames(i + 1, strings.length))
+ .inOrder();
}
}
@@ -776,7 +780,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
for (int i = 0; i < strings.length; i++) {
for (int j = i; j < strings.length; j++) {
assertThat(set.subSet(strings[i], false, strings[j], false))
- .has().exactlyAs(sortedNumberNames(Math.min(i + 1, j), j)).inOrder();
+ .containsExactlyElementsIn(sortedNumberNames(Math.min(i + 1, j), j))
+ .inOrder();
}
}
}
@@ -788,7 +793,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
for (int i = 0; i < strings.length; i++) {
for (int j = i; j < strings.length; j++) {
assertThat(set.subSet(strings[i], true, strings[j], false))
- .has().exactlyAs(sortedNumberNames(i, j)).inOrder();
+ .containsExactlyElementsIn(sortedNumberNames(i, j))
+ .inOrder();
}
}
}
@@ -800,7 +806,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
for (int i = 0; i < strings.length; i++) {
for (int j = i; j < strings.length; j++) {
assertThat(set.subSet(strings[i], false, strings[j], true))
- .has().exactlyAs(sortedNumberNames(i + 1, j + 1)).inOrder();
+ .containsExactlyElementsIn(sortedNumberNames(i + 1, j + 1))
+ .inOrder();
}
}
}
@@ -812,7 +819,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
for (int i = 0; i < strings.length; i++) {
for (int j = i; j < strings.length; j++) {
assertThat(set.subSet(strings[i], true, strings[j], true))
- .has().exactlyAs(sortedNumberNames(i, j + 1)).inOrder();
+ .containsExactlyElementsIn(sortedNumberNames(i, j + 1))
+ .inOrder();
}
}
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableTableTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableTableTest.java
index c602d65..685cbf5 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableTableTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ImmutableTableTest.java
@@ -184,9 +184,9 @@ public class ImmutableTableTest extends AbstractTableReadTest {
validateTableCopies(table);
// Even though rowKeySet, columnKeySet, and cellSet have the same
// iteration ordering, row has an inconsistent ordering.
- assertThat(table.row('b').keySet()).has().exactly(1, 2).inOrder();
+ assertThat(table.row('b').keySet()).containsExactly(1, 2).inOrder();
assertThat(ImmutableTable.copyOf(table).row('b').keySet())
- .has().exactly(2, 1).inOrder();
+ .containsExactly(2, 1).inOrder();
}
public void testCopyOfSparse() {
@@ -227,10 +227,10 @@ public class ImmutableTableTest extends AbstractTableReadTest {
= builder.orderRowsBy(Ordering.natural())
.orderColumnsBy(Ordering.natural())
.putAll(table).build();
- assertThat(copy.rowKeySet()).has().exactly('a', 'b').inOrder();
- assertThat(copy.columnKeySet()).has().exactly(1, 2).inOrder();
- assertThat(copy.values()).has().exactly("baz", "bar", "foo").inOrder();
- assertThat(copy.row('b').keySet()).has().exactly(1, 2).inOrder();
+ assertThat(copy.rowKeySet()).containsExactly('a', 'b').inOrder();
+ assertThat(copy.columnKeySet()).containsExactly(1, 2).inOrder();
+ assertThat(copy.values()).containsExactly("baz", "bar", "foo").inOrder();
+ assertThat(copy.row('b').keySet()).containsExactly(1, 2).inOrder();
}
public void testBuilder_orderRowsAndColumnsBy_sparse() {
@@ -248,12 +248,12 @@ public class ImmutableTableTest extends AbstractTableReadTest {
builder.put('r', 4, "foo");
builder.put('x', 5, "bar");
Table<Character, Integer, String> table = builder.build();
- assertThat(table.rowKeySet()).has().exactly('b', 'c', 'e', 'r', 'x').inOrder();
- assertThat(table.columnKeySet()).has().exactly(0, 1, 2, 3, 4, 5, 7).inOrder();
- assertThat(table.values()).has().exactly("cat", "axe", "baz", "tub",
+ assertThat(table.rowKeySet()).containsExactly('b', 'c', 'e', 'r', 'x').inOrder();
+ assertThat(table.columnKeySet()).containsExactly(0, 1, 2, 3, 4, 5, 7).inOrder();
+ assertThat(table.values()).containsExactly("cat", "axe", "baz", "tub",
"dog", "bar", "foo", "foo", "bar").inOrder();
- assertThat(table.row('c').keySet()).has().exactly(0, 3).inOrder();
- assertThat(table.column(5).keySet()).has().exactly('e', 'x').inOrder();
+ assertThat(table.row('c').keySet()).containsExactly(0, 3).inOrder();
+ assertThat(table.column(5).keySet()).containsExactly('e', 'x').inOrder();
}
public void testBuilder_orderRowsAndColumnsBy_dense() {
@@ -270,12 +270,12 @@ public class ImmutableTableTest extends AbstractTableReadTest {
builder.put('a', 2, "bar");
builder.put('a', 1, "baz");
Table<Character, Integer, String> table = builder.build();
- assertThat(table.rowKeySet()).has().exactly('a', 'b', 'c').inOrder();
- assertThat(table.columnKeySet()).has().exactly(1, 2, 3).inOrder();
- assertThat(table.values()).has().exactly("baz", "bar", "foo", "dog",
+ assertThat(table.rowKeySet()).containsExactly('a', 'b', 'c').inOrder();
+ assertThat(table.columnKeySet()).containsExactly(1, 2, 3).inOrder();
+ assertThat(table.values()).containsExactly("baz", "bar", "foo", "dog",
"cat", "baz", "bar", "foo").inOrder();
- assertThat(table.row('c').keySet()).has().exactly(1, 2, 3).inOrder();
- assertThat(table.column(1).keySet()).has().exactly('a', 'b', 'c').inOrder();
+ assertThat(table.row('c').keySet()).containsExactly(1, 2, 3).inOrder();
+ assertThat(table.column(1).keySet()).containsExactly('a', 'b', 'c').inOrder();
}
public void testBuilder_orderRowsBy_sparse() {
@@ -292,8 +292,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
builder.put('r', 4, "foo");
builder.put('x', 5, "bar");
Table<Character, Integer, String> table = builder.build();
- assertThat(table.rowKeySet()).has().exactly('b', 'c', 'e', 'r', 'x').inOrder();
- assertThat(table.column(5).keySet()).has().exactly('e', 'x').inOrder();
+ assertThat(table.rowKeySet()).containsExactly('b', 'c', 'e', 'r', 'x').inOrder();
+ assertThat(table.column(5).keySet()).containsExactly('e', 'x').inOrder();
}
public void testBuilder_orderRowsBy_dense() {
@@ -309,8 +309,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
builder.put('a', 2, "bar");
builder.put('a', 1, "baz");
Table<Character, Integer, String> table = builder.build();
- assertThat(table.rowKeySet()).has().exactly('a', 'b', 'c').inOrder();
- assertThat(table.column(1).keySet()).has().exactly('a', 'b', 'c').inOrder();
+ assertThat(table.rowKeySet()).containsExactly('a', 'b', 'c').inOrder();
+ assertThat(table.column(1).keySet()).containsExactly('a', 'b', 'c').inOrder();
}
public void testBuilder_orderColumnsBy_sparse() {
@@ -327,8 +327,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
builder.put('r', 4, "foo");
builder.put('x', 5, "bar");
Table<Character, Integer, String> table = builder.build();
- assertThat(table.columnKeySet()).has().exactly(0, 1, 2, 3, 4, 5, 7).inOrder();
- assertThat(table.row('c').keySet()).has().exactly(0, 3).inOrder();
+ assertThat(table.columnKeySet()).containsExactly(0, 1, 2, 3, 4, 5, 7).inOrder();
+ assertThat(table.row('c').keySet()).containsExactly(0, 3).inOrder();
}
public void testBuilder_orderColumnsBy_dense() {
@@ -344,8 +344,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
builder.put('a', 2, "bar");
builder.put('a', 1, "baz");
Table<Character, Integer, String> table = builder.build();
- assertThat(table.columnKeySet()).has().exactly(1, 2, 3).inOrder();
- assertThat(table.row('c').keySet()).has().exactly(1, 2, 3).inOrder();
+ assertThat(table.columnKeySet()).containsExactly(1, 2, 3).inOrder();
+ assertThat(table.row('c').keySet()).containsExactly(1, 2, 3).inOrder();
}
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IterablesTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IterablesTest.java
index 5d0b304..68101ec 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IterablesTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IterablesTest.java
@@ -26,7 +26,6 @@ import static java.util.Collections.emptyList;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Function;
-import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.testing.IteratorTester;
@@ -234,14 +233,10 @@ public class IterablesTest extends TestCase {
public void testTryFind() {
Iterable<String> list = newArrayList("cool", "pants");
- assertEquals(Optional.of("cool"),
- Iterables.tryFind(list, Predicates.equalTo("cool")));
- assertEquals(Optional.of("pants"),
- Iterables.tryFind(list, Predicates.equalTo("pants")));
- assertEquals(Optional.of("cool"),
- Iterables.tryFind(list, Predicates.alwaysTrue()));
- assertEquals(Optional.absent(),
- Iterables.tryFind(list, Predicates.alwaysFalse()));
+ assertThat(Iterables.tryFind(list, Predicates.equalTo("cool"))).hasValue("cool");
+ assertThat(Iterables.tryFind(list, Predicates.equalTo("pants"))).hasValue("pants");
+ assertThat(Iterables.tryFind(list, Predicates.alwaysTrue())).hasValue("cool");
+ assertThat(Iterables.tryFind(list, Predicates.alwaysFalse())).isAbsent();
assertCanIterateAgain(list);
}
@@ -374,8 +369,7 @@ public class IterablesTest extends TestCase {
int n = 4;
Iterable<Integer> repeated
= Iterables.concat(Collections.nCopies(n, iterable));
- assertThat(repeated).iteratesAs(
- 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3);
+ assertThat(repeated).containsExactly(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3).inOrder();
}
public void testPartition_badSize() {
@@ -451,7 +445,7 @@ public class IterablesTest extends TestCase {
List<String> freshlyAdded = newArrayList("freshly", "added");
boolean changed = Iterables.addAll(alreadyThere, freshlyAdded);
- assertThat(alreadyThere).has().exactly(
+ assertThat(alreadyThere).containsExactly(
"already", "there", "freshly", "added").inOrder();
assertTrue(changed);
}
@@ -603,7 +597,7 @@ public class IterablesTest extends TestCase {
Iterable<String> tail = skip(set, 1);
set.remove("b");
set.addAll(newArrayList("A", "B", "C"));
- assertThat(tail).iteratesAs("c", "A", "B", "C");
+ assertThat(tail).containsExactly("c", "A", "B", "C").inOrder();
}
public void testSkip_structurallyModifiedSkipSomeList() throws Exception {
@@ -611,7 +605,7 @@ public class IterablesTest extends TestCase {
Iterable<String> tail = skip(list, 1);
list.subList(1, 3).clear();
list.addAll(0, newArrayList("A", "B", "C"));
- assertThat(tail).iteratesAs("B", "C", "a");
+ assertThat(tail).containsExactly("B", "C", "a").inOrder();
}
public void testSkip_structurallyModifiedSkipAll() throws Exception {
@@ -1042,12 +1036,12 @@ public class IterablesTest extends TestCase {
assertEquals("Iterables.consumingIterable(...)", consumingIterable.toString());
Iterator<String> consumingIterator = consumingIterable.iterator();
- assertThat(list).has().exactly("a", "b").inOrder();
+ assertThat(list).containsExactly("a", "b").inOrder();
assertTrue(consumingIterator.hasNext());
- assertThat(list).has().exactly("a", "b").inOrder();
+ assertThat(list).containsExactly("a", "b").inOrder();
assertEquals("a", consumingIterator.next());
- assertThat(list).has().item("b");
+ assertThat(list).contains("b");
assertTrue(consumingIterator.hasNext());
assertEquals("b", consumingIterator.next());
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IteratorsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IteratorsTest.java
index 38bb635..a1fd86b 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IteratorsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/IteratorsTest.java
@@ -16,6 +16,7 @@
package com.google.common.collect;
+import static com.google.common.collect.CollectPreconditions.checkRemove;
import static com.google.common.collect.Iterators.advance;
import static com.google.common.collect.Iterators.get;
import static com.google.common.collect.Iterators.getLast;
@@ -31,7 +32,9 @@ import com.google.common.base.Predicates;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.ConcurrentModificationException;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
@@ -169,8 +172,7 @@ public class IteratorsTest extends TestCase {
Iterators.getOnlyElement(iterator);
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("expected one element but was: <one, two>",
- expected.getMessage());
+ assertThat(expected).hasMessage("expected one element but was: <one, two>");
}
}
@@ -181,9 +183,8 @@ public class IteratorsTest extends TestCase {
Iterators.getOnlyElement(iterator);
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("expected one element but was: "
- + "<one, two, three, four, five>",
- expected.getMessage());
+ assertThat(expected)
+ .hasMessage("expected one element but was: " + "<one, two, three, four, five>");
}
}
@@ -194,9 +195,8 @@ public class IteratorsTest extends TestCase {
Iterators.getOnlyElement(iterator);
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("expected one element but was: "
- + "<one, two, three, four, five, ...>",
- expected.getMessage());
+ assertThat(expected)
+ .hasMessage("expected one element but was: " + "<one, two, three, four, five, ...>");
}
}
@@ -221,8 +221,7 @@ public class IteratorsTest extends TestCase {
Iterators.getOnlyElement(iterator, "x");
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("expected one element but was: <foo, bar>",
- expected.getMessage());
+ assertThat(expected).hasMessage("expected one element but was: <foo, bar>");
}
}
@@ -365,22 +364,19 @@ public class IteratorsTest extends TestCase {
public void testTryFind_firstElement() {
Iterable<String> list = Lists.newArrayList("cool", "pants");
Iterator<String> iterator = list.iterator();
- assertEquals("cool",
- Iterators.tryFind(iterator, Predicates.equalTo("cool")).get());
+ assertThat(Iterators.tryFind(iterator, Predicates.equalTo("cool"))).hasValue("cool");
}
public void testTryFind_lastElement() {
Iterable<String> list = Lists.newArrayList("cool", "pants");
Iterator<String> iterator = list.iterator();
- assertEquals("pants",
- Iterators.tryFind(iterator, Predicates.equalTo("pants")).get());
+ assertThat(Iterators.tryFind(iterator, Predicates.equalTo("pants"))).hasValue("pants");
}
public void testTryFind_alwaysTrue() {
Iterable<String> list = Lists.newArrayList("cool", "pants");
Iterator<String> iterator = list.iterator();
- assertEquals("cool",
- Iterators.tryFind(iterator, Predicates.alwaysTrue()).get());
+ assertThat(Iterators.tryFind(iterator, Predicates.alwaysTrue())).hasValue("cool");
}
public void testTryFind_alwaysFalse_orDefault() {
@@ -394,8 +390,7 @@ public class IteratorsTest extends TestCase {
public void testTryFind_alwaysFalse_isPresent() {
Iterable<String> list = Lists.newArrayList("cool", "pants");
Iterator<String> iterator = list.iterator();
- assertFalse(
- Iterators.tryFind(iterator, Predicates.alwaysFalse()).isPresent());
+ assertThat(Iterators.tryFind(iterator, Predicates.alwaysFalse())).isAbsent();
assertFalse(iterator.hasNext());
}
@@ -562,6 +557,69 @@ public class IteratorsTest extends TestCase {
assertFalse(cycle.hasNext());
}
+ /** An Iterable whose Iterator is rigorous in checking for concurrent modification. */
+ private static final class PickyIterable<E> implements Iterable<E> {
+ final List<E> elements;
+ int modCount = 0;
+
+ PickyIterable(E... elements) {
+ this.elements = new ArrayList<E>(asList(elements));
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new PickyIterator();
+ }
+
+ final class PickyIterator implements Iterator<E> {
+ int expectedModCount = modCount;
+ int index = 0;
+ boolean canRemove;
+
+ @Override
+ public boolean hasNext() {
+ checkConcurrentModification();
+ return index < elements.size();
+ }
+
+ @Override
+ public E next() {
+ checkConcurrentModification();
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ canRemove = true;
+ return elements.get(index++);
+ }
+
+ @Override
+ public void remove() {
+ checkConcurrentModification();
+ checkRemove(canRemove);
+ elements.remove(--index);
+ expectedModCount = ++modCount;
+ canRemove = false;
+ }
+
+ void checkConcurrentModification() {
+ if (expectedModCount != modCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+ }
+ }
+
+ public void testCycleRemoveAfterHasNextExtraPicky() {
+ PickyIterable<String> iterable = new PickyIterable("a");
+ Iterator<String> cycle = Iterators.cycle(iterable);
+ assertTrue(cycle.hasNext());
+ assertEquals("a", cycle.next());
+ assertTrue(cycle.hasNext());
+ cycle.remove();
+ assertTrue(iterable.elements.isEmpty());
+ assertFalse(cycle.hasNext());
+ }
+
public void testCycleNoSuchElementException() {
Iterable<String> iterable = Lists.newArrayList("a");
Iterator<String> cycle = Iterators.cycle(iterable);
@@ -613,7 +671,7 @@ public class IteratorsTest extends TestCase {
boolean changed = Iterators.addAll(alreadyThere,
Iterators.<String>emptyIterator());
- assertThat(alreadyThere).has().exactly("already", "there").inOrder();
+ assertThat(alreadyThere).containsExactly("already", "there").inOrder();
assertFalse(changed);
}
@@ -623,7 +681,7 @@ public class IteratorsTest extends TestCase {
boolean changed = Iterators.addAll(alreadyThere, freshlyAdded.iterator());
- assertThat(alreadyThere).has().exactly("already", "there", "freshly", "added");
+ assertThat(alreadyThere).containsExactly("already", "there", "freshly", "added");
assertTrue(changed);
}
@@ -633,7 +691,7 @@ public class IteratorsTest extends TestCase {
List<String> oneMore = Lists.newArrayList("there");
boolean changed = Iterators.addAll(alreadyThere, oneMore.iterator());
- assertThat(alreadyThere).has().exactly("already", "there").inOrder();
+ assertThat(alreadyThere).containsExactly("already", "there").inOrder();
assertFalse(changed);
}
@@ -1229,12 +1287,12 @@ public class IteratorsTest extends TestCase {
assertEquals("Iterators.consumingIterator(...)", consumingIterator.toString());
- assertThat(list).has().exactly("a", "b").inOrder();
+ assertThat(list).containsExactly("a", "b").inOrder();
assertTrue(consumingIterator.hasNext());
- assertThat(list).has().exactly("a", "b").inOrder();
+ assertThat(list).containsExactly("a", "b").inOrder();
assertEquals("a", consumingIterator.next());
- assertThat(list).has().item("b");
+ assertThat(list).contains("b");
assertTrue(consumingIterator.hasNext());
assertEquals("b", consumingIterator.next());
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimapTest.java
index 05d6650..ac4803d 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultimapTest.java
@@ -88,12 +88,12 @@ public class LinkedHashMultimapTest extends TestCase {
}
private void assertOrderingReadOnly(Multimap<String, Integer> multimap) {
- assertThat(multimap.get("foo")).has().exactly(5, 3).inOrder();
- assertThat(multimap.get("bar")).has().exactly(4, 1).inOrder();
- assertThat(multimap.get("cow")).has().item(2);
+ assertThat(multimap.get("foo")).containsExactly(5, 3).inOrder();
+ assertThat(multimap.get("bar")).containsExactly(4, 1).inOrder();
+ assertThat(multimap.get("cow")).contains(2);
- assertThat(multimap.keySet()).has().exactly("foo", "bar", "cow").inOrder();
- assertThat(multimap.values()).has().exactly(5, 4, 3, 2, 1).inOrder();
+ assertThat(multimap.keySet()).containsExactly("foo", "bar", "cow").inOrder();
+ assertThat(multimap.values()).containsExactly(5, 4, 3, 2, 1).inOrder();
Iterator<Map.Entry<String, Integer>> entryIterator =
multimap.entries().iterator();
@@ -107,28 +107,28 @@ public class LinkedHashMultimapTest extends TestCase {
multimap.asMap().entrySet().iterator();
Map.Entry<String, Collection<Integer>> entry = collectionIterator.next();
assertEquals("foo", entry.getKey());
- assertThat(entry.getValue()).has().exactly(5, 3).inOrder();
+ assertThat(entry.getValue()).containsExactly(5, 3).inOrder();
entry = collectionIterator.next();
assertEquals("bar", entry.getKey());
- assertThat(entry.getValue()).has().exactly(4, 1).inOrder();
+ assertThat(entry.getValue()).containsExactly(4, 1).inOrder();
entry = collectionIterator.next();
assertEquals("cow", entry.getKey());
- assertThat(entry.getValue()).has().item(2);
+ assertThat(entry.getValue()).contains(2);
}
public void testOrderingUpdates() {
Multimap<String, Integer> multimap = initializeMultimap5();
- assertThat(multimap.replaceValues("foo", asList(6, 7))).has().exactly(5, 3).inOrder();
- assertThat(multimap.keySet()).has().exactly("foo", "bar", "cow").inOrder();
- assertThat(multimap.removeAll("foo")).has().exactly(6, 7).inOrder();
- assertThat(multimap.keySet()).has().exactly("bar", "cow").inOrder();
+ assertThat(multimap.replaceValues("foo", asList(6, 7))).containsExactly(5, 3).inOrder();
+ assertThat(multimap.keySet()).containsExactly("foo", "bar", "cow").inOrder();
+ assertThat(multimap.removeAll("foo")).containsExactly(6, 7).inOrder();
+ assertThat(multimap.keySet()).containsExactly("bar", "cow").inOrder();
assertTrue(multimap.remove("bar", 4));
- assertThat(multimap.keySet()).has().exactly("bar", "cow").inOrder();
+ assertThat(multimap.keySet()).containsExactly("bar", "cow").inOrder();
assertTrue(multimap.remove("bar", 1));
- assertThat(multimap.keySet()).has().item("cow");
+ assertThat(multimap.keySet()).contains("cow");
multimap.put("bar", 9);
- assertThat(multimap.keySet()).has().exactly("cow", "bar").inOrder();
+ assertThat(multimap.keySet()).containsExactly("cow", "bar").inOrder();
}
public void testToStringNullExact() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultisetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultisetTest.java
index bfab499..a08ffbd 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultisetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedHashMultisetTest.java
@@ -97,14 +97,14 @@ public class LinkedHashMultisetTest extends TestCase {
ms.add("a");
ms.add("b", 2);
ms.add("c");
- assertThat(ms.elementSet()).has().exactly("a", "b", "c").inOrder();
+ assertThat(ms.elementSet()).containsExactly("a", "b", "c").inOrder();
ms.remove("b");
- assertThat(ms.elementSet()).has().exactly("a", "b", "c").inOrder();
+ assertThat(ms.elementSet()).containsExactly("a", "b", "c").inOrder();
ms.add("b");
- assertThat(ms.elementSet()).has().exactly("a", "b", "c").inOrder();
+ assertThat(ms.elementSet()).containsExactly("a", "b", "c").inOrder();
ms.remove("b", 2);
ms.add("b");
- assertThat(ms.elementSet()).has().exactly("a", "c", "b").inOrder();
+ assertThat(ms.elementSet()).containsExactly("a", "c", "b").inOrder();
}
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimapTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimapTest.java
index 469b1b6..ea7d041 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimapTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/LinkedListMultimapTest.java
@@ -51,8 +51,8 @@ public class LinkedListMultimapTest extends TestCase {
Multimap<String, Integer> multimap = create();
multimap.put("foo", 1);
multimap.put("foo", 3);
- assertFalse(multimap.get("foo") instanceof RandomAccess);
- assertFalse(multimap.get("bar") instanceof RandomAccess);
+ assertThat(multimap.get("foo")).isNotInstanceOf(RandomAccess.class);
+ assertThat(multimap.get("bar")).isNotInstanceOf(RandomAccess.class);
}
/**
@@ -89,7 +89,7 @@ public class LinkedListMultimapTest extends TestCase {
LinkedListMultimap<String, Integer> copy =
LinkedListMultimap.create(multimap);
assertEquals(multimap, copy);
- assertThat(copy.entries()).has().exactlyAs(multimap.entries()).inOrder();
+ assertThat(copy.entries()).containsExactlyElementsIn(multimap.entries()).inOrder();
}
public void testCreateFromSize() {
@@ -183,7 +183,7 @@ public class LinkedListMultimapTest extends TestCase {
List<Integer> foos = map.get("foo");
Collection<Integer> values = map.values();
assertEquals(asList(1, 2), foos);
- assertThat(values).has().exactly(1, 2, 3).inOrder();
+ assertThat(values).containsExactly(1, 2, 3).inOrder();
map.clear();
assertEquals(Collections.emptyList(), foos);
assertThat(values).isEmpty();
@@ -210,7 +210,7 @@ public class LinkedListMultimapTest extends TestCase {
map.put("bar", 4);
assertEquals("[bar=1, foo=2, bar=3, bar=4]",
map.entries().toString());
- assertThat(map.keys()).has().exactly("bar", "foo", "bar", "bar").inOrder();
+ assertThat(map.keys()).containsExactly("bar", "foo", "bar", "bar").inOrder();
map.keys().remove("bar"); // bar is no longer the first key!
assertEquals("{foo=[2], bar=[3, 4]}", map.toString());
}
@@ -256,7 +256,7 @@ public class LinkedListMultimapTest extends TestCase {
= map.asMap().entrySet().iterator();
Map.Entry<String, Collection<Integer>> entry = entries.next();
assertEquals("bar", entry.getKey());
- assertThat(entry.getValue()).has().exactly(1, 3).inOrder();
+ assertThat(entry.getValue()).containsExactly(1, 3).inOrder();
try {
entry.setValue(Arrays.<Integer>asList());
fail("UnsupportedOperationException expected");
@@ -264,7 +264,7 @@ public class LinkedListMultimapTest extends TestCase {
entries.remove(); // clear
entry = entries.next();
assertEquals("foo", entry.getKey());
- assertThat(entry.getValue()).has().item(2);
+ assertThat(entry.getValue()).contains(2);
assertFalse(entries.hasNext());
assertEquals("{foo=[2]}", map.toString());
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ListsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ListsTest.java
index dcd52d5..d142a37 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ListsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ListsTest.java
@@ -214,7 +214,7 @@ public class ListsTest extends TestCase {
}
private void checkFooBarBazList(List<String> list) {
- assertThat(list).has().exactly("foo", "bar", "baz").inOrder();
+ assertThat(list).containsExactly("foo", "bar", "baz").inOrder();
assertEquals(3, list.size());
assertIndexIsOutOfBounds(list, -1);
assertEquals("foo", list.get(0));
@@ -225,7 +225,7 @@ public class ListsTest extends TestCase {
public void testAsList1Small() {
List<String> list = Lists.asList("foo", new String[0]);
- assertThat(list).has().item("foo");
+ assertThat(list).contains("foo");
assertEquals(1, list.size());
assertIndexIsOutOfBounds(list, -1);
assertEquals("foo", list.get(0));
@@ -308,24 +308,24 @@ public class ListsTest extends TestCase {
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_binary1x1() {
- assertThat(Lists.cartesianProduct(list(1), list(2))).has().item(list(1, 2));
+ assertThat(Lists.cartesianProduct(list(1), list(2))).contains(list(1, 2));
}
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_binary1x2() {
assertThat(Lists.cartesianProduct(list(1), list(2, 3)))
- .has().exactly(list(1, 2), list(1, 3)).inOrder();
+ .containsExactly(list(1, 2), list(1, 3)).inOrder();
}
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_binary2x2() {
assertThat(Lists.cartesianProduct(list(1, 2), list(3, 4)))
- .has().exactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
+ .containsExactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
}
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_2x2x2() {
- assertThat(Lists.cartesianProduct(list(0, 1), list(0, 1), list(0, 1))).has().exactly(
+ assertThat(Lists.cartesianProduct(list(0, 1), list(0, 1), list(0, 1))).containsExactly(
list(0, 0, 0), list(0, 0, 1), list(0, 1, 0), list(0, 1, 1),
list(1, 0, 0), list(1, 0, 1), list(1, 1, 0), list(1, 1, 1)).inOrder();
}
@@ -351,7 +351,7 @@ public class ListsTest extends TestCase {
List<Object> exp4 = list((Object) 2, "4");
assertThat(Lists.<Object>cartesianProduct(x, y))
- .has().exactly(exp1, exp2, exp3, exp4).inOrder();
+ .containsExactly(exp1, exp2, exp3, exp4).inOrder();
}
@SuppressWarnings("unchecked") // varargs!
@@ -442,7 +442,7 @@ public class ListsTest extends TestCase {
public void testTransformSequential() {
List<String> list = Lists.transform(SOME_SEQUENTIAL_LIST, SOME_FUNCTION);
- assertFalse(list instanceof RandomAccess);
+ assertThat(list).isNotInstanceOf(RandomAccess.class);
}
public void testTransformListIteratorRandomAccess() {
@@ -598,9 +598,9 @@ public class ListsTest extends TestCase {
public void testPartitionRandomAccessFalse() {
List<Integer> source = Lists.newLinkedList(asList(1, 2, 3));
List<List<Integer>> partitions = Lists.partition(source, 2);
- assertFalse(partitions instanceof RandomAccess);
- assertFalse(partitions.get(0) instanceof RandomAccess);
- assertFalse(partitions.get(1) instanceof RandomAccess);
+ assertThat(partitions).isNotInstanceOf(RandomAccess.class);
+ assertThat(partitions.get(0)).isNotInstanceOf(RandomAccess.class);
+ assertThat(partitions.get(1)).isNotInstanceOf(RandomAccess.class);
}
// TODO: use the ListTestSuiteBuilder
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapConstraintsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapConstraintsTest.java
index 928f809..05263d3 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapConstraintsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapConstraintsTest.java
@@ -110,10 +110,10 @@ public class MapConstraintsTest extends TestCase {
assertEquals(map.keySet(), constrained.keySet());
assertEquals(HashMultiset.create(map.values()),
HashMultiset.create(constrained.values()));
- assertFalse(map.values() instanceof Serializable);
+ assertThat(map.values()).isNotInstanceOf(Serializable.class);
assertEquals(map.toString(), constrained.toString());
assertEquals(map.hashCode(), constrained.hashCode());
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
Maps.immutableEntry(TEST_KEY, TEST_VALUE),
Maps.immutableEntry("foo", 1),
Maps.immutableEntry("bar", 2),
@@ -161,7 +161,7 @@ public class MapConstraintsTest extends TestCase {
assertEquals(map.values(), constrained.values());
assertEquals(map.toString(), constrained.toString());
assertEquals(map.hashCode(), constrained.hashCode());
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
Maps.immutableEntry(TEST_KEY, TEST_VALUE),
Maps.immutableEntry("foo", 1),
Maps.immutableEntry("bar", 2),
@@ -230,7 +230,7 @@ public class MapConstraintsTest extends TestCase {
assertTrue(constrained.equals(multimap));
assertThat(ImmutableList.copyOf(multimap.entries())).isEqualTo(
ImmutableList.copyOf(constrained.entries()));
- assertThat(constrained.asMap().get("foo")).has().item(1);
+ assertThat(constrained.asMap().get("foo")).contains(1);
assertNull(constrained.asMap().get("missing"));
assertEquals(multimap.asMap(), constrained.asMap());
assertEquals(multimap.values(), constrained.values());
@@ -238,7 +238,7 @@ public class MapConstraintsTest extends TestCase {
assertEquals(multimap.keySet(), constrained.keySet());
assertEquals(multimap.toString(), constrained.toString());
assertEquals(multimap.hashCode(), constrained.hashCode());
- assertThat(multimap.entries()).has().exactly(
+ assertThat(multimap.entries()).containsExactly(
Maps.immutableEntry(TEST_KEY, TEST_VALUE),
Maps.immutableEntry("foo", 1),
Maps.immutableEntry("bar", 2),
@@ -251,9 +251,8 @@ public class MapConstraintsTest extends TestCase {
Maps.immutableEntry("bop", 9),
Maps.immutableEntry("dig", 10),
Maps.immutableEntry("dag", 11)).inOrder();
- assertFalse(constrained.asMap().values() instanceof Serializable);
- Iterator<Collection<Integer>> iterator =
- constrained.asMap().values().iterator();
+ assertThat(constrained.asMap().values()).isNotInstanceOf(Serializable.class);
+ Iterator<Collection<Integer>> iterator = constrained.asMap().values().iterator();
iterator.next();
iterator.next().add(12);
assertTrue(multimap.containsEntry("foo", 12));
@@ -538,7 +537,18 @@ public class MapConstraintsTest extends TestCase {
Collection<Map.Entry<String, Integer>> entries = constrained.entries();
assertFalse(entries.remove(nefariousEntry));
assertFalse(multimap.containsValue(TEST_VALUE));
- assertFalse(entries.removeAll(Collections.singleton(nefariousEntry)));
+ /*
+ * Either the Multimap should reject the nefarious internalEntry.setValue() call that
+ * queryEntry.equals() makes, or it should arrange for internalEntry.equals(queryEntry) to be
+ * used instead of the reverse so that queryEntry.equals(internalEntry) is never invoked.
+ *
+ * Probably the other tests should be similarly tolerant of either outcome. But for now, this is
+ * the only one failing in any of our environments.
+ */
+ try {
+ assertFalse(entries.removeAll(Collections.singleton(nefariousEntry)));
+ } catch (TestValueException tolerated) {
+ }
assertFalse(multimap.containsValue(TEST_VALUE));
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapsTest.java
index f2b3538..fc8b911 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MapsTest.java
@@ -94,7 +94,7 @@ public class MapsTest extends TestCase {
try {
Maps.capacity(-1);
fail("Negative expected size must result in IllegalArgumentException");
- } catch (IllegalArgumentException ex) {
+ } catch (IllegalArgumentException expected) {
}
}
@@ -183,9 +183,9 @@ public class MapsTest extends TestCase {
assertEquals(Collections.emptyMap(), map);
map.put(new Derived("foo"), 1);
map.put(new Derived("bar"), 2);
- assertThat(map.keySet()).has().exactly(
+ assertThat(map.keySet()).containsExactly(
new Derived("bar"), new Derived("foo")).inOrder();
- assertThat(map.values()).has().exactly(2, 1).inOrder();
+ assertThat(map.values()).containsExactly(2, 1).inOrder();
assertNull(map.comparator());
}
@@ -194,9 +194,9 @@ public class MapsTest extends TestCase {
assertEquals(Collections.emptyMap(), map);
map.put(new LegacyComparable("foo"), 1);
map.put(new LegacyComparable("bar"), 2);
- assertThat(map.keySet()).has().exactly(
+ assertThat(map.keySet()).containsExactly(
new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
- assertThat(map.values()).has().exactly(2, 1).inOrder();
+ assertThat(map.values()).containsExactly(2, 1).inOrder();
assertNull(map.comparator());
}
@@ -460,13 +460,13 @@ public class MapsTest extends TestCase {
SortedMapDifference<Integer, String> diff1 =
Maps.difference(left, right);
assertFalse(diff1.areEqual());
- assertThat(diff1.entriesOnlyOnLeft().entrySet()).has().exactly(
+ assertThat(diff1.entriesOnlyOnLeft().entrySet()).containsExactly(
Maps.immutableEntry(4, "d"), Maps.immutableEntry(2, "b")).inOrder();
- assertThat(diff1.entriesOnlyOnRight().entrySet()).has().item(
+ assertThat(diff1.entriesOnlyOnRight().entrySet()).contains(
Maps.immutableEntry(6, "z"));
- assertThat(diff1.entriesInCommon().entrySet()).has().item(
+ assertThat(diff1.entriesInCommon().entrySet()).contains(
Maps.immutableEntry(1, "a"));
- assertThat(diff1.entriesDiffering().entrySet()).has().exactly(
+ assertThat(diff1.entriesDiffering().entrySet()).containsExactly(
Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g")),
Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f"))).inOrder();
assertEquals("not equal: only on left={4=d, 2=b}: only on right={6=z}: "
@@ -475,11 +475,11 @@ public class MapsTest extends TestCase {
SortedMapDifference<Integer, String> diff2 =
Maps.difference(right, left);
assertFalse(diff2.areEqual());
- assertThat(diff2.entriesOnlyOnLeft().entrySet()).has().item(
+ assertThat(diff2.entriesOnlyOnLeft().entrySet()).contains(
Maps.immutableEntry(6, "z"));
- assertThat(diff2.entriesOnlyOnRight().entrySet()).has().exactly(
+ assertThat(diff2.entriesOnlyOnRight().entrySet()).containsExactly(
Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder();
- assertThat(diff1.entriesInCommon().entrySet()).has().item(
+ assertThat(diff1.entriesInCommon().entrySet()).contains(
Maps.immutableEntry(1, "a"));
assertEquals(ImmutableMap.of(
3, ValueDifferenceImpl.create("f", "c"),
@@ -499,13 +499,13 @@ public class MapsTest extends TestCase {
Maps.difference(left, right);
left.put(6, "z");
assertFalse(diff1.areEqual());
- assertThat(diff1.entriesOnlyOnLeft().entrySet()).has().exactly(
+ assertThat(diff1.entriesOnlyOnLeft().entrySet()).containsExactly(
Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder();
- assertThat(diff1.entriesOnlyOnRight().entrySet()).has().item(
+ assertThat(diff1.entriesOnlyOnRight().entrySet()).contains(
Maps.immutableEntry(6, "z"));
- assertThat(diff1.entriesInCommon().entrySet()).has().item(
+ assertThat(diff1.entriesInCommon().entrySet()).contains(
Maps.immutableEntry(1, "a"));
- assertThat(diff1.entriesDiffering().entrySet()).has().exactly(
+ assertThat(diff1.entriesDiffering().entrySet()).containsExactly(
Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f")),
Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g"))).inOrder();
try {
@@ -562,7 +562,7 @@ public class MapsTest extends TestCase {
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
assertEquals(Integer.valueOf(5), map.get("three"));
assertNull(map.get("five"));
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("two", 3),
mapEntry("three", 5)).inOrder();
@@ -585,7 +585,7 @@ public class MapsTest extends TestCase {
Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
assertEquals(Integer.valueOf(3), map.remove("two"));
- assertThat(strings).has().exactly("one", "three").inOrder();
+ assertThat(strings).containsExactly("one", "three").inOrder();
}
public void testAsMapEmpty() {
@@ -618,14 +618,14 @@ public class MapsTest extends TestCase {
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
assertEquals(Integer.valueOf(5), map.get("three"));
assertNull(map.get("five"));
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("three", 5),
mapEntry("two", 3)).inOrder();
- assertThat(map.tailMap("onea").entrySet()).has().exactly(
+ assertThat(map.tailMap("onea").entrySet()).containsExactly(
mapEntry("three", 5),
mapEntry("two", 3)).inOrder();
- assertThat(map.subMap("one", "two").entrySet()).has().exactly(
+ assertThat(map.subMap("one", "two").entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("three", 5)).inOrder();
}
@@ -651,7 +651,7 @@ public class MapsTest extends TestCase {
assertEquals(
ImmutableSortedMap.of("five", 4, "four", 4, "three", 5),
headMap);
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("five", 4),
mapEntry("four", 4),
mapEntry("three", 5),
@@ -664,7 +664,7 @@ public class MapsTest extends TestCase {
SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
assertEquals(Integer.valueOf(3), map.remove("two"));
- assertThat(strings).has().exactly("one", "three").inOrder();
+ assertThat(strings).containsExactly("one", "three").inOrder();
}
public void testAsMapSortedSubViewKeySetsDoNotSupportAdd() {
@@ -704,7 +704,7 @@ public class MapsTest extends TestCase {
Iterable<String> strings = ImmutableList.of("one", "two", "three");
ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("two", 3),
mapEntry("three", 5)).inOrder();
@@ -714,7 +714,7 @@ public class MapsTest extends TestCase {
Iterator<String> strings = ImmutableList.of("one", "two", "three").iterator();
ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("two", 3),
mapEntry("three", 5)).inOrder();
@@ -724,7 +724,7 @@ public class MapsTest extends TestCase {
Iterable<String> strings = ImmutableList.of("one", "two", "three", "two", "one");
ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("two", 3),
mapEntry("three", 5)).inOrder();
@@ -787,6 +787,7 @@ public class MapsTest extends TestCase {
Maps.uniqueIndex(ImmutableSet.of("one", "uno"), Functions.constant(1));
fail();
} catch (IllegalArgumentException expected) {
+ assertThat(expected.getMessage()).contains("Multimaps.index");
}
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultimapsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultimapsTest.java
index 43b9831..81fe775 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultimapsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultimapsTest.java
@@ -28,7 +28,6 @@ import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
-import com.google.common.collect.Maps.EntryTransformer;
import com.google.common.collect.testing.IteratorTester;
import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
@@ -66,14 +65,6 @@ public class MultimapsTest extends TestCase {
private static final Comparator<Integer> INT_COMPARATOR =
Ordering.<Integer>natural().reverse().nullsFirst();
- private static final EntryTransformer<Object, Object, Object> ALWAYS_NULL =
- new EntryTransformer<Object, Object, Object>() {
- @Override
- public Object transformEntry(Object k, Object v1) {
- return null;
- }
- };
-
@SuppressWarnings("deprecation")
public void testUnmodifiableListMultimapShortCircuit() {
ListMultimap<String, Integer> mod = ArrayListMultimap.create();
@@ -125,10 +116,9 @@ public class MultimapsTest extends TestCase {
ListMultimap<String, Integer> delegate = LinkedListMultimap.create();
delegate.put("foo", 1);
delegate.put("foo", 3);
- ListMultimap<String, Integer> multimap
- = Multimaps.unmodifiableListMultimap(delegate);
- assertFalse(multimap.get("foo") instanceof RandomAccess);
- assertFalse(multimap.get("bar") instanceof RandomAccess);
+ ListMultimap<String, Integer> multimap = Multimaps.unmodifiableListMultimap(delegate);
+ assertThat(multimap.get("foo")).isNotInstanceOf(RandomAccess.class);
+ assertThat(multimap.get("bar")).isNotInstanceOf(RandomAccess.class);
}
public void testUnmodifiableMultimapIsView() {
@@ -205,10 +195,10 @@ public class MultimapsTest extends TestCase {
assertEquals(multimap.hashCode(), unmodifiable.hashCode());
assertEquals(multimap, unmodifiable);
- assertThat(unmodifiable.asMap().get("bar")).has().exactly(5, -1);
+ assertThat(unmodifiable.asMap().get("bar")).containsExactly(5, -1);
assertNull(unmodifiable.asMap().get("missing"));
- assertFalse(unmodifiable.entries() instanceof Serializable);
+ assertThat(unmodifiable.entries()).isNotInstanceOf(Serializable.class);
}
/**
@@ -362,13 +352,11 @@ public class MultimapsTest extends TestCase {
assertFalse(map.containsKey("bar"));
assertEquals(map.keySet(), multimapView.keySet());
assertEquals(map.keySet(), multimapView.keys().elementSet());
- assertThat(multimapView.keys()).has().item("foo");
- assertThat(multimapView.values()).has().item(1);
- assertThat(multimapView.entries()).has().item(
- Maps.immutableEntry("foo", 1));
- assertThat(multimapView.asMap().entrySet()).has().item(
- Maps.immutableEntry(
- "foo", (Collection<Integer>) Collections.singleton(1)));
+ assertThat(multimapView.keys()).contains("foo");
+ assertThat(multimapView.values()).contains(1);
+ assertThat(multimapView.entries()).contains(Maps.immutableEntry("foo", 1));
+ assertThat(multimapView.asMap().entrySet())
+ .contains(Maps.immutableEntry("foo", (Collection<Integer>) Collections.singleton(1)));
multimapView.clear();
assertFalse(multimapView.containsKey("foo"));
assertFalse(map.containsKey("foo"));
@@ -514,7 +502,7 @@ public class MultimapsTest extends TestCase {
} catch (IllegalArgumentException expected) {
// expected
}
- assertThat(multimap.entries()).has().exactly(
+ assertThat(multimap.entries()).containsExactly(
Maps.immutableEntry(Color.RED, 1),
Maps.immutableEntry(Color.BLUE, 2));
}
@@ -539,8 +527,8 @@ public class MultimapsTest extends TestCase {
Collection<Integer> collection = multimap.get(Color.BLUE);
assertEquals(collection, collection);
- assertFalse(multimap.keySet() instanceof SortedSet);
- assertFalse(multimap.asMap() instanceof SortedMap);
+ assertThat(multimap.keySet()).isNotInstanceOf(SortedSet.class);
+ assertThat(multimap.asMap()).isNotInstanceOf(SortedMap.class);
}
private static class ListSupplier extends
@@ -562,7 +550,7 @@ public class MultimapsTest extends TestCase {
multimap.putAll(Color.RED, asList(2, 7, 1, 8));
assertEquals(2, factory.count);
assertEquals("{BLUE=[3, 1, 4, 1], RED=[2, 7, 1, 8]}", multimap.toString());
- assertFalse(multimap.get(Color.BLUE) instanceof RandomAccess);
+ assertThat(multimap.get(Color.BLUE)).isNotInstanceOf(RandomAccess.class);
assertTrue(multimap.keySet() instanceof SortedSet);
assertTrue(multimap.asMap() instanceof SortedMap);
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultisetsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultisetsTest.java
index 5394626..6f879f0 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultisetsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/MultisetsTest.java
@@ -44,7 +44,7 @@ public class MultisetsTest extends TestCase {
assertTrue(set.isEmpty());
set.add(new DerivedComparable("foo"), 2);
set.add(new DerivedComparable("bar"), 3);
- assertThat(set).has().exactly(
+ assertThat(set).containsExactly(
new DerivedComparable("bar"), new DerivedComparable("bar"), new DerivedComparable("bar"),
new DerivedComparable("foo"), new DerivedComparable("foo")).inOrder();
}
@@ -54,7 +54,7 @@ public class MultisetsTest extends TestCase {
assertTrue(set.isEmpty());
set.add(new LegacyComparable("foo"), 2);
set.add(new LegacyComparable("bar"), 3);
- assertThat(set).has().exactly(new LegacyComparable("bar"),
+ assertThat(set).containsExactly(new LegacyComparable("bar"),
new LegacyComparable("bar"), new LegacyComparable("bar"),
new LegacyComparable("foo"), new LegacyComparable("foo")).inOrder();
}
@@ -64,7 +64,7 @@ public class MultisetsTest extends TestCase {
= TreeMultiset.create(Collections.reverseOrder());
multiset.add("bar", 3);
multiset.add("foo", 2);
- assertThat(multiset).has().exactly("foo", "foo", "bar", "bar", "bar").inOrder();
+ assertThat(multiset).containsExactly("foo", "foo", "bar", "bar", "bar").inOrder();
}
public void testRetainOccurrencesEmpty() {
@@ -86,7 +86,7 @@ public class MultisetsTest extends TestCase {
Multiset<String> multiset = HashMultiset.create();
Multiset<String> toRemove =
HashMultiset.create(Arrays.asList("a", "b", "a"));
- assertFalse(Multisets.retainOccurrences(multiset, toRemove));
+ assertFalse(Multisets.removeOccurrences(multiset, toRemove));
assertTrue(multiset.isEmpty());
}
@@ -94,7 +94,7 @@ public class MultisetsTest extends TestCase {
Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> ms2 = HashMultiset.create(
Arrays.asList("a", "b", "b", "c"));
- assertThat(Multisets.union(ms1, ms2)).has().exactly("a", "a", "b", "b", "c");
+ assertThat(Multisets.union(ms1, ms2)).containsExactly("a", "a", "b", "b", "c");
}
public void testUnionEqualMultisets() {
@@ -130,38 +130,38 @@ public class MultisetsTest extends TestCase {
public void testSum() {
Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> ms2 = HashMultiset.create(Arrays.asList("b", "c"));
- assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "a", "b", "b", "c");
+ assertThat(Multisets.sum(ms1, ms2)).containsExactly("a", "a", "b", "b", "c");
}
public void testSumEmptyNonempty() {
Multiset<String> ms1 = HashMultiset.create();
Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
- assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "b", "a");
+ assertThat(Multisets.sum(ms1, ms2)).containsExactly("a", "b", "a");
}
public void testSumNonemptyEmpty() {
Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> ms2 = HashMultiset.create();
- assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "b", "a");
+ assertThat(Multisets.sum(ms1, ms2)).containsExactly("a", "b", "a");
}
public void testDifferenceWithNoRemovedElements() {
Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a"));
- assertThat(Multisets.difference(ms1, ms2)).has().exactly("a", "b");
+ assertThat(Multisets.difference(ms1, ms2)).containsExactly("a", "b");
}
public void testDifferenceWithRemovedElement() {
Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> ms2 = HashMultiset.create(Arrays.asList("b"));
- assertThat(Multisets.difference(ms1, ms2)).has().exactly("a", "a");
+ assertThat(Multisets.difference(ms1, ms2)).containsExactly("a", "a");
}
public void testDifferenceWithMoreElementsInSecondMultiset() {
Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "b", "b"));
Multiset<String> diff = Multisets.difference(ms1, ms2);
- assertThat(diff).has().item("a");
+ assertThat(diff).contains("a");
assertEquals(0, diff.count("b"));
assertEquals(1, diff.count("a"));
assertFalse(diff.contains("b"));
@@ -211,7 +211,7 @@ public class MultisetsTest extends TestCase {
Multiset<String> toRetain =
HashMultiset.create(Arrays.asList("a", "b", "b"));
assertTrue(Multisets.retainOccurrences(multiset, toRetain));
- assertThat(multiset).has().exactly("a", "b").inOrder();
+ assertThat(multiset).containsExactly("a", "b").inOrder();
}
public void testRemoveEmptyOccurrencesMultiset() {
@@ -219,7 +219,7 @@ public class MultisetsTest extends TestCase {
TreeMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> toRemove = HashMultiset.create();
assertFalse(Multisets.removeOccurrences(multiset, toRemove));
- assertThat(multiset).has().exactly("a", "a", "b").inOrder();
+ assertThat(multiset).containsExactly("a", "a", "b").inOrder();
}
public void testRemoveOccurrencesMultiset() {
@@ -228,7 +228,7 @@ public class MultisetsTest extends TestCase {
Multiset<String> toRemove =
HashMultiset.create(Arrays.asList("a", "b", "b"));
assertTrue(Multisets.removeOccurrences(multiset, toRemove));
- assertThat(multiset).has().exactly("a", "c").inOrder();
+ assertThat(multiset).containsExactly("a", "c").inOrder();
}
public void testRemoveEmptyOccurrencesIterable() {
@@ -236,7 +236,7 @@ public class MultisetsTest extends TestCase {
TreeMultiset.create(Arrays.asList("a", "b", "a"));
Iterable<String> toRemove = ImmutableList.of();
assertFalse(Multisets.removeOccurrences(multiset, toRemove));
- assertThat(multiset).has().exactly("a", "a", "b").inOrder();
+ assertThat(multiset).containsExactly("a", "a", "b").inOrder();
}
public void testRemoveOccurrencesMultisetIterable() {
@@ -244,7 +244,7 @@ public class MultisetsTest extends TestCase {
TreeMultiset.create(Arrays.asList("a", "b", "a", "c"));
List<String> toRemove = Arrays.asList("a", "b", "b");
assertTrue(Multisets.removeOccurrences(multiset, toRemove));
- assertThat(multiset).has().exactly("a", "c").inOrder();
+ assertThat(multiset).containsExactly("a", "c").inOrder();
}
@SuppressWarnings("deprecation")
@@ -264,11 +264,11 @@ public class MultisetsTest extends TestCase {
ImmutableMultiset<String> sortedMultiset =
Multisets.copyHighestCountFirst(multiset);
- assertThat(sortedMultiset.entrySet()).has().exactly(
+ assertThat(sortedMultiset.entrySet()).containsExactly(
Multisets.immutableEntry("a", 3), Multisets.immutableEntry("c", 2),
Multisets.immutableEntry("b", 1)).inOrder();
- assertThat(sortedMultiset).has().exactly(
+ assertThat(sortedMultiset).containsExactly(
"a",
"a",
"a",
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ObjectArraysTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ObjectArraysTest.java
index b9342da..e6ff97e 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ObjectArraysTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/ObjectArraysTest.java
@@ -36,20 +36,20 @@ public class ObjectArraysTest extends TestCase {
public void testNewArray_fromArray_Empty() {
String[] in = new String[0];
String[] empty = ObjectArrays.newArray(in, 0);
- assertEquals(0, empty.length);
+ assertThat(empty).isEmpty();
}
public void testNewArray_fromArray_Nonempty() {
String[] array = ObjectArrays.newArray(new String[0], 2);
assertEquals(String[].class, array.getClass());
- assertEquals(2, array.length);
+ assertThat(array).hasLength(2);
assertNull(array[0]);
}
public void testNewArray_fromArray_OfArray() {
String[][] array = ObjectArrays.newArray(new String[0][0], 1);
assertEquals(String[][].class, array.getClass());
- assertEquals(1, array.length);
+ assertThat(array).hasLength(1);
assertNull(array[0]);
}
@@ -99,32 +99,32 @@ public class ObjectArraysTest extends TestCase {
public void testPrependZeroElements() {
String[] result = ObjectArrays.concat("foo", new String[] {});
- assertThat(result).asList().has().item("foo");
+ assertThat(result).asList().contains("foo");
}
public void testPrependOneElement() {
String[] result = ObjectArrays.concat("foo", new String[] { "bar" });
- assertThat(result).asList().has().exactly("foo", "bar").inOrder();
+ assertThat(result).asList().containsExactly("foo", "bar").inOrder();
}
public void testPrependTwoElements() {
String[] result = ObjectArrays.concat("foo", new String[] { "bar", "baz" });
- assertThat(result).asList().has().exactly("foo", "bar", "baz").inOrder();
+ assertThat(result).asList().containsExactly("foo", "bar", "baz").inOrder();
}
public void testAppendZeroElements() {
String[] result = ObjectArrays.concat(new String[] {}, "foo");
- assertThat(result).asList().has().item("foo");
+ assertThat(result).asList().contains("foo");
}
public void testAppendOneElement() {
String[] result = ObjectArrays.concat(new String[] { "foo" }, "bar");
- assertThat(result).asList().has().exactly("foo", "bar").inOrder();
+ assertThat(result).asList().containsExactly("foo", "bar").inOrder();
}
public void testAppendTwoElements() {
String[] result = ObjectArrays.concat(new String[] { "foo", "bar" }, "baz");
- assertThat(result).asList().has().exactly("foo", "bar", "baz").inOrder();
+ assertThat(result).asList().containsExactly("foo", "bar", "baz").inOrder();
}
public void testEmptyArrayToEmpty() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/OrderingTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/OrderingTest.java
index 579842c..17b607d 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/OrderingTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/OrderingTest.java
@@ -70,6 +70,38 @@ public class OrderingTest extends TestCase {
assertEquals(strings, comparator.immutableSortedCopy(strings));
}
+ // From https://github.com/google/guava/issues/1342
+ public void testComplicatedOrderingExample() {
+ Integer nullInt = (Integer) null;
+ Ordering<Iterable<Integer>> example =
+ Ordering.<Integer>natural().nullsFirst().reverse().lexicographical().reverse().nullsLast();
+ List<Integer> list1 = Lists.newArrayList();
+ List<Integer> list2 = Lists.newArrayList(1);
+ List<Integer> list3 = Lists.newArrayList(1, 1);
+ List<Integer> list4 = Lists.newArrayList(1, 2);
+ List<Integer> list5 = Lists.newArrayList(1, null, 2);
+ List<Integer> list6 = Lists.newArrayList(2);
+ List<Integer> list7 = Lists.newArrayList(nullInt);
+ List<Integer> list8 = Lists.newArrayList(nullInt, nullInt);
+ List<List<Integer>> list =
+ Lists.newArrayList(list1, list2, list3, list4, list5, list6, list7, list8, null);
+ List<List<Integer>> sorted = example.sortedCopy(list);
+
+ // [[null, null], [null], [1, null, 2], [1, 1], [1, 2], [1], [2], [], null]
+ assertThat(sorted)
+ .containsExactly(
+ Lists.newArrayList(nullInt, nullInt),
+ Lists.newArrayList(nullInt),
+ Lists.newArrayList(1, null, 2),
+ Lists.newArrayList(1, 1),
+ Lists.newArrayList(1, 2),
+ Lists.newArrayList(1),
+ Lists.newArrayList(2),
+ Lists.newArrayList(),
+ null)
+ .inOrder();
+ }
+
public void testNatural() {
Ordering<Integer> comparator = Ordering.natural();
Helpers.testComparator(comparator,
@@ -155,7 +187,7 @@ public class OrderingTest extends TestCase {
= Ordering.explicit(2, 8, 6, 1, 7, 5, 3, 4, 0, 9);
List<Integer> list = Arrays.asList(0, 3, 5, 6, 7, 8, 9);
Collections.sort(list, c);
- assertThat(list).has().exactly(8, 6, 7, 5, 3, 0, 9).inOrder();
+ assertThat(list).containsExactly(8, 6, 7, 5, 3, 0, 9).inOrder();
reserializeAndAssert(c);
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SetsTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SetsTest.java
index 6242ee2..66ab974 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SetsTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SetsTest.java
@@ -91,7 +91,7 @@ public class SetsTest extends TestCase {
public void testImmutableEnumSet() {
Set<SomeEnum> units = Sets.immutableEnumSet(SomeEnum.D, SomeEnum.B);
- assertThat(units).has().exactly(SomeEnum.B, SomeEnum.D).inOrder();
+ assertThat(units).containsExactly(SomeEnum.B, SomeEnum.D).inOrder();
try {
units.remove(SomeEnum.B);
fail("ImmutableEnumSet should throw an exception on remove()");
@@ -109,11 +109,10 @@ public class SetsTest extends TestCase {
ImmutableSet<SomeEnum> one
= Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.B));
- assertThat(one).has().item(SomeEnum.B);
+ assertThat(one).contains(SomeEnum.B);
- ImmutableSet<SomeEnum> two
- = Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.D, SomeEnum.B));
- assertThat(two).has().exactly(SomeEnum.B, SomeEnum.D).inOrder();
+ ImmutableSet<SomeEnum> two = Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.D, SomeEnum.B));
+ assertThat(two).containsExactly(SomeEnum.B, SomeEnum.D).inOrder();
}
private static byte[] prepended(byte b, byte[] array) {
@@ -230,7 +229,7 @@ public class SetsTest extends TestCase {
assertTrue(set.isEmpty());
set.add(new Derived("foo"));
set.add(new Derived("bar"));
- assertThat(set).has().exactly(new Derived("bar"), new Derived("foo")).inOrder();
+ assertThat(set).containsExactly(new Derived("bar"), new Derived("foo")).inOrder();
}
public void testNewTreeSetEmptyNonGeneric() {
@@ -238,8 +237,8 @@ public class SetsTest extends TestCase {
assertTrue(set.isEmpty());
set.add(new LegacyComparable("foo"));
set.add(new LegacyComparable("bar"));
- assertThat(set).has()
- .exactly(new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
+ assertThat(set).containsExactly(
+ new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
}
public void testNewTreeSetFromCollection() {
@@ -256,7 +255,7 @@ public class SetsTest extends TestCase {
Iterable<Derived> iterable =
Arrays.asList(new Derived("foo"), new Derived("bar"));
TreeSet<Derived> set = Sets.newTreeSet(iterable);
- assertThat(set).has().exactly(
+ assertThat(set).containsExactly(
new Derived("bar"), new Derived("foo")).inOrder();
}
@@ -264,7 +263,7 @@ public class SetsTest extends TestCase {
Iterable<LegacyComparable> iterable =
Arrays.asList(new LegacyComparable("foo"), new LegacyComparable("bar"));
TreeSet<LegacyComparable> set = Sets.newTreeSet(iterable);
- assertThat(set).has().exactly(
+ assertThat(set).containsExactly(
new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
}
@@ -357,7 +356,7 @@ public class SetsTest extends TestCase {
*/
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_zeroary() {
- assertThat(Sets.cartesianProduct()).has().exactly(list());
+ assertThat(Sets.cartesianProduct()).containsExactly(list());
}
/**
@@ -366,7 +365,7 @@ public class SetsTest extends TestCase {
*/
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_unary() {
- assertThat(Sets.cartesianProduct(set(1, 2))).has().exactly(list(1), list(2));
+ assertThat(Sets.cartesianProduct(set(1, 2))).containsExactly(list(1), list(2));
}
@SuppressWarnings("unchecked") // varargs!
@@ -395,24 +394,24 @@ public class SetsTest extends TestCase {
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_binary1x1() {
- assertThat(Sets.cartesianProduct(set(1), set(2))).has().item(list(1, 2));
+ assertThat(Sets.cartesianProduct(set(1), set(2))).contains(list(1, 2));
}
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_binary1x2() {
assertThat(Sets.cartesianProduct(set(1), set(2, 3)))
- .has().exactly(list(1, 2), list(1, 3)).inOrder();
+ .containsExactly(list(1, 2), list(1, 3)).inOrder();
}
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_binary2x2() {
assertThat(Sets.cartesianProduct(set(1, 2), set(3, 4)))
- .has().exactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
+ .containsExactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
}
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_2x2x2() {
- assertThat(Sets.cartesianProduct(set(0, 1), set(0, 1), set(0, 1))).has().exactly(
+ assertThat(Sets.cartesianProduct(set(0, 1), set(0, 1), set(0, 1))).containsExactly(
list(0, 0, 0), list(0, 0, 1), list(0, 1, 0), list(0, 1, 1),
list(1, 0, 0), list(1, 0, 1), list(1, 1, 0), list(1, 1, 1)).inOrder();
}
@@ -438,7 +437,7 @@ public class SetsTest extends TestCase {
List<Object> exp4 = list((Object) 2, "4");
assertThat(Sets.<Object>cartesianProduct(x, y))
- .has().exactly(exp1, exp2, exp3, exp4).inOrder();
+ .containsExactly(exp1, exp2, exp3, exp4).inOrder();
}
@SuppressWarnings("unchecked") // varargs!
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SingletonImmutableTableTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SingletonImmutableTableTest.java
index c21fdc0..d7f04ec 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SingletonImmutableTableTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/SingletonImmutableTableTest.java
@@ -117,7 +117,7 @@ public class SingletonImmutableTableTest extends AbstractImmutableTableTest {
}
public void testValues() {
- assertThat(testTable.values()).has().item("blah");
+ assertThat(testTable.values()).contains("blah");
}
@Override Iterable<ImmutableTable<Character, Integer, String>> getTestInstances() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeBasedTableTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeBasedTableTest.java
index 7977f8d..fe71a6d 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeBasedTableTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeBasedTableTest.java
@@ -117,8 +117,8 @@ public class TreeBasedTableTest extends AbstractTableTest {
table.put("foo", 12, 'b');
table.put("bar", 5, 'c');
table.put("cat", 8, 'd');
- assertThat(table.rowKeySet()).has().exactly("foo", "cat", "bar").inOrder();
- assertThat(table.row("foo").keySet()).has().exactly(12, 3).inOrder();
+ assertThat(table.rowKeySet()).containsExactly("foo", "cat", "bar").inOrder();
+ assertThat(table.row("foo").keySet()).containsExactly(12, 3).inOrder();
}
public void testCreateCopy() {
@@ -129,8 +129,8 @@ public class TreeBasedTableTest extends AbstractTableTest {
original.put("bar", 5, 'c');
original.put("cat", 8, 'd');
table = TreeBasedTable.create(original);
- assertThat(table.rowKeySet()).has().exactly("foo", "cat", "bar").inOrder();
- assertThat(table.row("foo").keySet()).has().exactly(12, 3).inOrder();
+ assertThat(table.rowKeySet()).containsExactly("foo", "cat", "bar").inOrder();
+ assertThat(table.row("foo").keySet()).containsExactly(12, 3).inOrder();
assertEquals(original, table);
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapExplicitTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapExplicitTest.java
index e0b1ec4..f392586 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapExplicitTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapExplicitTest.java
@@ -97,13 +97,13 @@ public class TreeMultimapExplicitTest extends TestCase {
tree.put("google", 6);
tree.put("tree", 0);
tree.put("tree", 3);
- assertThat(tree.keySet()).has().exactly("tree", "google").inOrder();
- assertThat(tree.get("google")).has().exactly(6, 2).inOrder();
+ assertThat(tree.keySet()).containsExactly("tree", "google").inOrder();
+ assertThat(tree.get("google")).containsExactly(6, 2).inOrder();
TreeMultimap<String, Integer> copy = TreeMultimap.create(tree);
assertEquals(tree, copy);
- assertThat(copy.keySet()).has().exactly("google", "tree").inOrder();
- assertThat(copy.get("google")).has().exactly(2, 6).inOrder();
+ assertThat(copy.keySet()).containsExactly("google", "tree").inOrder();
+ assertThat(copy.get("google")).containsExactly(2, 6).inOrder();
assertEquals(Ordering.natural(), copy.keyComparator());
assertEquals(Ordering.natural(), copy.valueComparator());
assertEquals(Ordering.natural(), copy.get("google").comparator());
@@ -128,14 +128,14 @@ public class TreeMultimapExplicitTest extends TestCase {
public void testOrderedGet() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.get(null)).has().exactly(7, 3, 1).inOrder();
- assertThat(multimap.get("google")).has().exactly(6, 2).inOrder();
- assertThat(multimap.get("tree")).has().exactly(null, 0).inOrder();
+ assertThat(multimap.get(null)).containsExactly(7, 3, 1).inOrder();
+ assertThat(multimap.get("google")).containsExactly(6, 2).inOrder();
+ assertThat(multimap.get("tree")).containsExactly(null, 0).inOrder();
}
public void testOrderedKeySet() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.keySet()).has().exactly(null, "tree", "google").inOrder();
+ assertThat(multimap.keySet()).containsExactly(null, "tree", "google").inOrder();
}
public void testOrderedAsMapEntries() {
@@ -144,18 +144,18 @@ public class TreeMultimapExplicitTest extends TestCase {
multimap.asMap().entrySet().iterator();
Map.Entry<String, Collection<Integer>> entry = iterator.next();
assertEquals(null, entry.getKey());
- assertThat(entry.getValue()).has().exactly(7, 3, 1);
+ assertThat(entry.getValue()).containsExactly(7, 3, 1);
entry = iterator.next();
assertEquals("tree", entry.getKey());
- assertThat(entry.getValue()).has().exactly(null, 0);
+ assertThat(entry.getValue()).containsExactly(null, 0);
entry = iterator.next();
assertEquals("google", entry.getKey());
- assertThat(entry.getValue()).has().exactly(6, 2);
+ assertThat(entry.getValue()).containsExactly(6, 2);
}
public void testOrderedEntries() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.entries()).has().exactly(
+ assertThat(multimap.entries()).containsExactly(
Maps.immutableEntry((String) null, 7),
Maps.immutableEntry((String) null, 3),
Maps.immutableEntry((String) null, 1),
@@ -167,7 +167,7 @@ public class TreeMultimapExplicitTest extends TestCase {
public void testOrderedValues() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.values()).has().exactly(7, 3, 1, null, 0, 6, 2).inOrder();
+ assertThat(multimap.values()).containsExactly(7, 3, 1, null, 0, 6, 2).inOrder();
}
public void testComparator() {
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapNaturalTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapNaturalTest.java
index 3882958..3f093dc 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapNaturalTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultimapNaturalTest.java
@@ -68,14 +68,14 @@ public class TreeMultimapNaturalTest extends TestCase {
public void testOrderedGet() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.get("foo")).has().exactly(1, 3, 7).inOrder();
- assertThat(multimap.get("google")).has().exactly(2, 6).inOrder();
- assertThat(multimap.get("tree")).has().exactly(0, 4).inOrder();
+ assertThat(multimap.get("foo")).containsExactly(1, 3, 7).inOrder();
+ assertThat(multimap.get("google")).containsExactly(2, 6).inOrder();
+ assertThat(multimap.get("tree")).containsExactly(0, 4).inOrder();
}
public void testOrderedKeySet() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.keySet()).has().exactly("foo", "google", "tree").inOrder();
+ assertThat(multimap.keySet()).containsExactly("foo", "google", "tree").inOrder();
}
public void testOrderedAsMapEntries() {
@@ -84,18 +84,18 @@ public class TreeMultimapNaturalTest extends TestCase {
multimap.asMap().entrySet().iterator();
Map.Entry<String, Collection<Integer>> entry = iterator.next();
assertEquals("foo", entry.getKey());
- assertThat(entry.getValue()).has().exactly(1, 3, 7);
+ assertThat(entry.getValue()).containsExactly(1, 3, 7);
entry = iterator.next();
assertEquals("google", entry.getKey());
- assertThat(entry.getValue()).has().exactly(2, 6);
+ assertThat(entry.getValue()).containsExactly(2, 6);
entry = iterator.next();
assertEquals("tree", entry.getKey());
- assertThat(entry.getValue()).has().exactly(0, 4);
+ assertThat(entry.getValue()).containsExactly(0, 4);
}
public void testOrderedEntries() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.entries()).has().exactly(
+ assertThat(multimap.entries()).containsExactly(
Maps.immutableEntry("foo", 1),
Maps.immutableEntry("foo", 3),
Maps.immutableEntry("foo", 7),
@@ -107,7 +107,7 @@ public class TreeMultimapNaturalTest extends TestCase {
public void testOrderedValues() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.values()).has().exactly(
+ assertThat(multimap.values()).containsExactly(
1, 3, 7, 2, 6, 0, 4).inOrder();
}
diff --git a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultisetTest.java b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultisetTest.java
index 65f1a95..8391dc7 100644
--- a/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultisetTest.java
+++ b/guava-gwt/test-super/com/google/common/collect/super/com/google/common/collect/TreeMultisetTest.java
@@ -83,9 +83,9 @@ public class TreeMultisetTest extends TestCase {
assertEquals("c", elementSet.last());
assertEquals(Ordering.natural(), elementSet.comparator());
- assertThat(elementSet.headSet("b")).has().exactly("a").inOrder();
- assertThat(elementSet.tailSet("b")).has().exactly("b", "c").inOrder();
- assertThat(elementSet.subSet("a", "c")).has().exactly("a", "b").inOrder();
+ assertThat(elementSet.headSet("b")).containsExactly("a");
+ assertThat(elementSet.tailSet("b")).containsExactly("b", "c").inOrder();
+ assertThat(elementSet.subSet("a", "c")).containsExactly("a", "b").inOrder();
}
public void testElementSetSubsetRemove() {
@@ -98,18 +98,18 @@ public class TreeMultisetTest extends TestCase {
ms.add("f", 2);
SortedSet<String> elementSet = ms.elementSet();
- assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
SortedSet<String> subset = elementSet.subSet("b", "f");
- assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+ assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
assertTrue(subset.remove("c"));
- assertThat(elementSet).has().exactly("a", "b", "d", "e", "f").inOrder();
- assertThat(subset).has().exactly("b", "d", "e").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
+ assertThat(subset).containsExactly("b", "d", "e").inOrder();
assertEquals(10, ms.size());
assertFalse(subset.remove("a"));
- assertThat(elementSet).has().exactly("a", "b", "d", "e", "f").inOrder();
- assertThat(subset).has().exactly("b", "d", "e").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
+ assertThat(subset).containsExactly("b", "d", "e").inOrder();
assertEquals(10, ms.size());
}
@@ -123,13 +123,13 @@ public class TreeMultisetTest extends TestCase {
ms.add("f", 2);
SortedSet<String> elementSet = ms.elementSet();
- assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
SortedSet<String> subset = elementSet.subSet("b", "f");
- assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+ assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
assertTrue(subset.removeAll(Arrays.asList("a", "c")));
- assertThat(elementSet).has().exactly("a", "b", "d", "e", "f").inOrder();
- assertThat(subset).has().exactly("b", "d", "e").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
+ assertThat(subset).containsExactly("b", "d", "e").inOrder();
assertEquals(10, ms.size());
}
@@ -143,13 +143,13 @@ public class TreeMultisetTest extends TestCase {
ms.add("f", 2);
SortedSet<String> elementSet = ms.elementSet();
- assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
SortedSet<String> subset = elementSet.subSet("b", "f");
- assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+ assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
assertTrue(subset.retainAll(Arrays.asList("a", "c")));
- assertThat(elementSet).has().exactly("a", "c", "f").inOrder();
- assertThat(subset).has().exactly("c").inOrder();
+ assertThat(elementSet).containsExactly("a", "c", "f").inOrder();
+ assertThat(subset).containsExactly("c");
assertEquals(5, ms.size());
}
@@ -163,12 +163,12 @@ public class TreeMultisetTest extends TestCase {
ms.add("f", 2);
SortedSet<String> elementSet = ms.elementSet();
- assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
SortedSet<String> subset = elementSet.subSet("b", "f");
- assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+ assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
subset.clear();
- assertThat(elementSet).has().exactly("a", "f").inOrder();
+ assertThat(elementSet).containsExactly("a", "f").inOrder();
assertThat(subset).isEmpty();
assertEquals(3, ms.size());
}
@@ -188,7 +188,7 @@ public class TreeMultisetTest extends TestCase {
ms.add("b");
ms.add("d");
- assertThat(ms).has().exactly("d", "c", "b", "b", "a").inOrder();
+ assertThat(ms).containsExactly("d", "c", "b", "b", "a").inOrder();
SortedSet<String> elementSet = ms.elementSet();
assertEquals("d", elementSet.first());
@@ -206,7 +206,7 @@ public class TreeMultisetTest extends TestCase {
ms.add("b");
ms.add(null, 2);
- assertThat(ms).has().exactly(null, null, null, "a", "b", "b").inOrder();
+ assertThat(ms).containsExactly(null, null, null, "a", "b", "b").inOrder();
assertEquals(3, ms.count(null));
SortedSet<String> elementSet = ms.elementSet();
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java
index 1674ba9..b2b6b4f 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java
@@ -107,16 +107,16 @@ public abstract class AbstractMultisetSetCountTester<E>
// Unconditional setCount no-ops.
private void assertZeroToZero() {
- assertSetCount(samples.e3, 0);
+ assertSetCount(e3(), 0);
}
private void assertOneToOne() {
- assertSetCount(samples.e0, 1);
+ assertSetCount(e0(), 1);
}
private void assertThreeToThree() {
initThreeCopies();
- assertSetCount(samples.e0, 3);
+ assertSetCount(e0(), 3);
}
@CollectionFeature.Require(SUPPORTS_ADD)
@@ -183,7 +183,7 @@ public abstract class AbstractMultisetSetCountTester<E>
@CollectionFeature.Require(SUPPORTS_ADD)
public void testSetCount_zeroToOne_supported() {
- assertSetCount(samples.e3, 1);
+ assertSetCount(e3(), 1);
}
@CollectionFeature.Require({SUPPORTS_ADD,
@@ -191,7 +191,7 @@ public abstract class AbstractMultisetSetCountTester<E>
public void testSetCountZeroToOneConcurrentWithIteration() {
try {
Iterator<E> iterator = collection.iterator();
- assertSetCount(samples.e3, 1);
+ assertSetCount(e3(), 1);
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -204,7 +204,7 @@ public abstract class AbstractMultisetSetCountTester<E>
public void testSetCountZeroToOneConcurrentWithEntrySetIteration() {
try {
Iterator<Entry<E>> iterator = getMultiset().entrySet().iterator();
- assertSetCount(samples.e3, 1);
+ assertSetCount(e3(), 1);
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -214,29 +214,29 @@ public abstract class AbstractMultisetSetCountTester<E>
@CollectionFeature.Require(SUPPORTS_ADD)
public void testSetCount_zeroToThree_supported() {
- assertSetCount(samples.e3, 3);
+ assertSetCount(e3(), 3);
}
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require(SUPPORTS_ADD)
public void testSetCount_oneToThree_supported() {
- assertSetCount(samples.e0, 3);
+ assertSetCount(e0(), 3);
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
public void testSetCount_zeroToOne_unsupported() {
- assertSetCountIncreasingFailure(samples.e3, 1);
+ assertSetCountIncreasingFailure(e3(), 1);
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
public void testSetCount_zeroToThree_unsupported() {
- assertSetCountIncreasingFailure(samples.e3, 3);
+ assertSetCountIncreasingFailure(e3(), 3);
}
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require(absent = SUPPORTS_ADD)
public void testSetCount_oneToThree_unsupported() {
- assertSetCountIncreasingFailure(samples.e3, 3);
+ assertSetCountIncreasingFailure(e3(), 3);
}
// Unconditional setCount size decreases:
@@ -244,7 +244,7 @@ public abstract class AbstractMultisetSetCountTester<E>
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testSetCount_oneToZero_supported() {
- assertSetCount(samples.e0, 0);
+ assertSetCount(e0(), 0);
}
@CollectionFeature.Require({SUPPORTS_REMOVE,
@@ -253,7 +253,7 @@ public abstract class AbstractMultisetSetCountTester<E>
public void testSetCountOneToZeroConcurrentWithIteration() {
try {
Iterator<E> iterator = collection.iterator();
- assertSetCount(samples.e0, 0);
+ assertSetCount(e0(), 0);
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -267,7 +267,7 @@ public abstract class AbstractMultisetSetCountTester<E>
public void testSetCountOneToZeroConcurrentWithEntrySetIteration() {
try {
Iterator<Entry<E>> iterator = getMultiset().entrySet().iterator();
- assertSetCount(samples.e0, 0);
+ assertSetCount(e0(), 0);
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -279,34 +279,34 @@ public abstract class AbstractMultisetSetCountTester<E>
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testSetCount_threeToZero_supported() {
initThreeCopies();
- assertSetCount(samples.e0, 0);
+ assertSetCount(e0(), 0);
}
@CollectionSize.Require(SEVERAL)
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testSetCount_threeToOne_supported() {
initThreeCopies();
- assertSetCount(samples.e0, 1);
+ assertSetCount(e0(), 1);
}
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
public void testSetCount_oneToZero_unsupported() {
- assertSetCountDecreasingFailure(samples.e0, 0);
+ assertSetCountDecreasingFailure(e0(), 0);
}
@CollectionSize.Require(SEVERAL)
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
public void testSetCount_threeToZero_unsupported() {
initThreeCopies();
- assertSetCountDecreasingFailure(samples.e0, 0);
+ assertSetCountDecreasingFailure(e0(), 0);
}
@CollectionSize.Require(SEVERAL)
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
public void testSetCount_threeToOne_unsupported() {
initThreeCopies();
- assertSetCountDecreasingFailure(samples.e0, 1);
+ assertSetCountDecreasingFailure(e0(), 1);
}
// setCount with nulls:
@@ -365,7 +365,7 @@ public abstract class AbstractMultisetSetCountTester<E>
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testSetCount_negative_removeSupported() {
try {
- setCountNoCheckReturnValue(samples.e3, -1);
+ setCountNoCheckReturnValue(e3(), -1);
fail("calling setCount() with a negative count should throw "
+ "IllegalArgumentException");
} catch (IllegalArgumentException expected) {
@@ -375,7 +375,7 @@ public abstract class AbstractMultisetSetCountTester<E>
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
public void testSetCount_negative_removeUnsupported() {
try {
- setCountNoCheckReturnValue(samples.e3, -1);
+ setCountNoCheckReturnValue(e3(), -1);
fail("calling setCount() with a negative count should throw "
+ "IllegalArgumentException or UnsupportedOperationException");
} catch (IllegalArgumentException expected) {
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetCountTester.java b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetCountTester.java
index 7955df5..0f8356a 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetCountTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetCountTester.java
@@ -36,20 +36,20 @@ public class MultisetCountTester<E> extends AbstractMultisetTester<E> {
public void testCount_0() {
assertEquals("multiset.count(missing) didn't return 0",
- 0, getMultiset().count(samples.e3));
+ 0, getMultiset().count(e3()));
}
@CollectionSize.Require(absent = ZERO)
public void testCount_1() {
assertEquals("multiset.count(present) didn't return 1",
- 1, getMultiset().count(samples.e0));
+ 1, getMultiset().count(e0()));
}
@CollectionSize.Require(SEVERAL)
public void testCount_3() {
initThreeCopies();
assertEquals("multiset.count(thriceContained) didn't return 3",
- 3, getMultiset().count(samples.e0));
+ 3, getMultiset().count(e0()));
}
@CollectionFeature.Require(ALLOWS_NULL_QUERIES)
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetIteratorTester.java b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetIteratorTester.java
index 9c129ab..fb8cb80 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetIteratorTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetIteratorTester.java
@@ -14,11 +14,12 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.IteratorFeature.MODIFIABLE;
+import static com.google.common.collect.testing.IteratorFeature.UNMODIFIABLE;
import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.testing.IteratorFeature;
import com.google.common.collect.testing.IteratorTester;
import com.google.common.collect.testing.features.CollectionFeature;
@@ -36,12 +37,12 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
@SuppressWarnings("unchecked")
@CollectionFeature.Require({SUPPORTS_ITERATOR_REMOVE, KNOWN_ORDER})
public void testRemovingIteratorKnownOrder() {
- new IteratorTester<E>(4, IteratorFeature.MODIFIABLE, getSubjectGenerator().order(
- Arrays.asList(samples.e0, samples.e1, samples.e1, samples.e2)),
+ new IteratorTester<E>(4, MODIFIABLE, getSubjectGenerator().order(
+ Arrays.asList(e0(), e1(), e1(), e2())),
IteratorTester.KnownOrder.KNOWN_ORDER) {
@Override
protected Iterator<E> newTargetIterator() {
- return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+ return getSubjectGenerator().create(e0(), e1(), e1(), e2())
.iterator();
}
}.test();
@@ -50,11 +51,11 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
@SuppressWarnings("unchecked")
@CollectionFeature.Require(value = SUPPORTS_ITERATOR_REMOVE, absent = KNOWN_ORDER)
public void testRemovingIteratorUnknownOrder() {
- new IteratorTester<E>(4, IteratorFeature.MODIFIABLE, Arrays.asList(samples.e0, samples.e1,
- samples.e1, samples.e2), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
+ new IteratorTester<E>(4, MODIFIABLE, Arrays.asList(e0(), e1(),
+ e1(), e2()), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
@Override
protected Iterator<E> newTargetIterator() {
- return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+ return getSubjectGenerator().create(e0(), e1(), e1(), e2())
.iterator();
}
}.test();
@@ -63,12 +64,12 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
@SuppressWarnings("unchecked")
@CollectionFeature.Require(value = KNOWN_ORDER, absent = SUPPORTS_ITERATOR_REMOVE)
public void testIteratorKnownOrder() {
- new IteratorTester<E>(4, IteratorFeature.UNMODIFIABLE, getSubjectGenerator().order(
- Arrays.asList(samples.e0, samples.e1, samples.e1, samples.e2)),
+ new IteratorTester<E>(4, UNMODIFIABLE, getSubjectGenerator().order(
+ Arrays.asList(e0(), e1(), e1(), e2())),
IteratorTester.KnownOrder.KNOWN_ORDER) {
@Override
protected Iterator<E> newTargetIterator() {
- return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+ return getSubjectGenerator().create(e0(), e1(), e1(), e2())
.iterator();
}
}.test();
@@ -77,11 +78,11 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
@SuppressWarnings("unchecked")
@CollectionFeature.Require(absent = {SUPPORTS_ITERATOR_REMOVE, KNOWN_ORDER})
public void testIteratorUnknownOrder() {
- new IteratorTester<E>(4, IteratorFeature.UNMODIFIABLE, Arrays.asList(samples.e0, samples.e1,
- samples.e1, samples.e2), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
+ new IteratorTester<E>(4, UNMODIFIABLE, Arrays.asList(e0(), e1(),
+ e1(), e2()), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
@Override
protected Iterator<E> newTargetIterator() {
- return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+ return getSubjectGenerator().create(e0(), e1(), e1(), e2())
.iterator();
}
}.test();
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetRemoveTester.java b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetRemoveTester.java
index 46148b9..05ee270 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetRemoveTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/google/super/com/google/common/collect/testing/google/MultisetRemoveTester.java
@@ -16,12 +16,12 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertEmpty;
import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_QUERIES;
import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES;
import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.testing.Helpers;
@@ -35,32 +35,32 @@ import java.util.List;
/**
* Tests for {@code Multiset#remove}, {@code Multiset.removeAll}, and {@code Multiset.retainAll}
* not already covered by the corresponding Collection testers.
- *
+ *
* @author Jared Levy
*/
@GwtCompatible(emulated = true)
-public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
+public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemoveNegative() {
try {
- getMultiset().remove(samples.e0, -1);
+ getMultiset().remove(e0(), -1);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {}
expectUnchanged();
}
-
+
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
public void testRemoveUnsupported() {
try {
- getMultiset().remove(samples.e0, 2);
+ getMultiset().remove(e0(), 2);
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {}
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemoveZeroNoOp() {
- int originalCount = getMultiset().count(samples.e0);
- assertEquals("old count", originalCount, getMultiset().remove(samples.e0, 0));
+ int originalCount = getMultiset().count(e0());
+ assertEquals("old count", originalCount, getMultiset().remove(e0(), 0));
expectUnchanged();
}
@@ -68,10 +68,10 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemove_occurrences_present() {
assertEquals("multiset.remove(present, 2) didn't return the old count",
- 1, getMultiset().remove(samples.e0, 2));
+ 1, getMultiset().remove(e0(), 2));
assertFalse("multiset contains present after multiset.remove(present, 2)",
- getMultiset().contains(samples.e0));
- assertEquals(0, getMultiset().count(samples.e0));
+ getMultiset().contains(e0()));
+ assertEquals(0, getMultiset().count(e0()));
}
@CollectionSize.Require(SEVERAL)
@@ -79,16 +79,16 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
public void testRemove_some_occurrences_present() {
initThreeCopies();
assertEquals("multiset.remove(present, 2) didn't return the old count",
- 3, getMultiset().remove(samples.e0, 2));
+ 3, getMultiset().remove(e0(), 2));
assertTrue("multiset contains present after multiset.remove(present, 2)",
- getMultiset().contains(samples.e0));
- assertEquals(1, getMultiset().count(samples.e0));
+ getMultiset().contains(e0()));
+ assertEquals(1, getMultiset().count(e0()));
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemove_occurrences_absent() {
assertEquals("multiset.remove(absent, 0) didn't return 0",
- 0, getMultiset().remove(samples.e3, 2));
+ 0, getMultiset().remove(e3(), 2));
}
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -97,21 +97,21 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
try {
assertEquals(
"multiset.remove(absent, 2) didn't return 0 or throw an exception",
- 0, getMultiset().remove(samples.e3, 2));
+ 0, getMultiset().remove(e3(), 2));
} catch (UnsupportedOperationException ok) {}
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemove_occurrences_0() {
- int oldCount = getMultiset().count(samples.e0);
+ int oldCount = getMultiset().count(e0());
assertEquals("multiset.remove(E, 0) didn't return the old count",
- oldCount, getMultiset().remove(samples.e0, 0));
+ oldCount, getMultiset().remove(e0(), 0));
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemove_occurrences_negative() {
try {
- getMultiset().remove(samples.e0, -1);
+ getMultiset().remove(e0(), -1);
fail("multiset.remove(E, -1) didn't throw an exception");
} catch (IllegalArgumentException required) {}
}
@@ -121,7 +121,7 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
assertEquals("multiset.remove(wrongType, 1) didn't return 0",
0, getMultiset().remove(WrongType.VALUE, 1));
}
-
+
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
public void testRemove_nullPresent() {
@@ -131,12 +131,12 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
getMultiset().contains(null));
assertEquals(0, getMultiset().count(null));
}
-
+
@CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_QUERIES})
public void testRemove_nullAbsent() {
assertEquals(0, getMultiset().remove(null, 2));
}
-
+
@CollectionFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_QUERIES)
public void testRemove_nullForbidden() {
try {
@@ -144,21 +144,21 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
fail("Expected NullPointerException");
} catch (NullPointerException expected) {}
}
-
+
@CollectionSize.Require(SEVERAL)
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemoveAllIgnoresCount() {
initThreeCopies();
- assertTrue(getMultiset().removeAll(Collections.singleton(samples.e0)));
- assertThat(getMultiset()).isEmpty();
+ assertTrue(getMultiset().removeAll(Collections.singleton(e0())));
+ assertEmpty(getMultiset());
}
-
+
@CollectionSize.Require(SEVERAL)
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRetainAllIgnoresCount() {
initThreeCopies();
List<E> contents = Helpers.copyToList(getMultiset());
- assertFalse(getMultiset().retainAll(Collections.singleton(samples.e0)));
+ assertFalse(getMultiset().retainAll(Collections.singleton(e0())));
expectContents(contents);
}
}
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/GwtPlatform.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/GwtPlatform.java
index b4d12b8..2b71e6e 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/GwtPlatform.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/GwtPlatform.java
@@ -17,7 +17,8 @@
package com.google.common.collect.testing;
import com.google.gwt.core.client.GwtScriptOnly;
-import com.google.gwt.lang.Array;
+
+import java.util.Arrays;
/**
* Version of {@link GwtPlatform} used in web-mode. It includes methods in
@@ -33,6 +34,6 @@ public final class GwtPlatform {
private GwtPlatform() {}
public static <T> T[] clone(T[] array) {
- return (T[]) Array.clone(array);
+ return (T[]) Arrays.copyOfRange(array, 0, array.length);
}
}
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/Helpers.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/Helpers.java
index 28f5571..6546131 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/Helpers.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/Helpers.java
@@ -74,6 +74,49 @@ public class Helpers {
return Collections.singletonMap(key, value).entrySet().iterator().next();
}
+ private static boolean isEmpty(Iterable<?> iterable) {
+ return iterable instanceof Collection
+ ? ((Collection<?>) iterable).isEmpty()
+ : iterable.iterator().hasNext();
+ }
+
+ public static void assertEmpty(Iterable<?> iterable) {
+ if (!isEmpty(iterable)) {
+ Assert.fail("Not true that " + iterable + " is empty");
+ }
+ }
+
+ public static void assertEmpty(Map<?, ?> map) {
+ if (!map.isEmpty()) {
+ Assert.fail("Not true that " + map + " is empty");
+ }
+ }
+
+ public static void assertEqualInOrder(
+ Iterable<?> expected, Iterable<?> actual) {
+ Iterator<?> expectedIter = expected.iterator();
+ Iterator<?> actualIter = actual.iterator();
+
+ while (expectedIter.hasNext() && actualIter.hasNext()) {
+ if (!equal(expectedIter.next(), actualIter.next())) {
+ Assert.fail(
+ "contents were not equal and in the same order: "
+ + "expected = " + expected + ", actual = " + actual);
+ }
+ }
+
+ if (expectedIter.hasNext() || actualIter.hasNext()) {
+ // actual either had too few or too many elements
+ Assert.fail(
+ "contents were not equal and in the same order: "
+ + "expected = " + expected + ", actual = " + actual);
+ }
+ }
+
+ public static void assertContentsInOrder(Iterable<?> actual, Object... expected) {
+ assertEqualInOrder(Arrays.asList(expected), actual);
+ }
+
public static void assertEqualIgnoringOrder(
Iterable<?> expected, Iterable<?> actual) {
List<?> exp = copyToList(expected);
@@ -98,6 +141,39 @@ public class Helpers {
assertEqualIgnoringOrder(Arrays.asList(expected), actual);
}
+ public static void assertContains(Iterable<?> actual, Object expected) {
+ boolean contained = false;
+ if (actual instanceof Collection) {
+ contained = ((Collection<?>) actual).contains(expected);
+ } else {
+ for (Object o : actual) {
+ if (equal(o, expected)) {
+ contained = true;
+ break;
+ }
+ }
+ }
+
+ if (!contained) {
+ Assert.fail("Not true that " + actual + " contains " + expected);
+ }
+ }
+
+ public static void assertContainsAllOf(
+ Iterable<?> actual, Object... expected) {
+ List<Object> expectedList = new ArrayList<Object>();
+ expectedList.addAll(Arrays.asList(expected));
+
+ for (Object o : actual) {
+ expectedList.remove(o);
+ }
+
+ if (!expectedList.isEmpty()) {
+ Assert.fail(
+ "Not true that " + actual + " contains all of " + Arrays.asList(expected));
+ }
+ }
+
public static <E> boolean addAll(
Collection<E> addTo, Iterable<? extends E> elementsToAdd) {
boolean modified = false;
@@ -178,11 +254,31 @@ public class Helpers {
};
}
+ /**
+ * Asserts that all pairs of {@code T} values within {@code valuesInExpectedOrder} are ordered
+ * consistently between their order within {@code valuesInExpectedOrder} and the order implied by
+ * the given {@code comparator}.
+ *
+ * @see #testComparator(Comparator, List)
+ */
public static <T> void testComparator(
Comparator<? super T> comparator, T... valuesInExpectedOrder) {
testComparator(comparator, Arrays.asList(valuesInExpectedOrder));
}
+ /**
+ * Asserts that all pairs of {@code T} values within {@code valuesInExpectedOrder} are ordered
+ * consistently between their order within {@code valuesInExpectedOrder} and the order implied by
+ * the given {@code comparator}.
+ *
+ * <p>In detail, this method asserts
+ * <ul>
+ * <li><i>reflexivity</i>: {@code comparator.compare(t, t) = 0} for all {@code t} in
+ * {@code valuesInExpectedOrder}; and
+ * <li><i>consistency</i>: {@code comparator.compare(ti, tj) < 0} and
+ * {@code comparator.compare(tj, ti) > 0} for {@code i < j}, where
+ * {@code ti = valuesInExpectedOrder.get(i)} and {@code tj = valuesInExpectedOrder.get(j)}.
+ */
public static <T> void testComparator(
Comparator<? super T> comparator, List<T> valuesInExpectedOrder) {
// This does an O(n^2) test of all pairs of values in both orders
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddAllTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddAllTester.java
index f521cf3..07f5349 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddAllTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddAllTester.java
@@ -65,7 +65,7 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
public void testAddAll_supportedNonePresent() {
assertTrue("addAll(nonePresent) should return true",
collection.addAll(createDisjointCollection()));
- expectAdded(samples.e3, samples.e4);
+ expectAdded(e3(), e4());
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
@@ -76,23 +76,23 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- expectMissing(samples.e3, samples.e4);
+ expectMissing(e3(), e4());
}
@CollectionFeature.Require(SUPPORTS_ADD)
@CollectionSize.Require(absent = ZERO)
public void testAddAll_supportedSomePresent() {
assertTrue("addAll(somePresent) should return true",
- collection.addAll(MinimalCollection.of(samples.e3, samples.e0)));
- assertTrue("should contain " + samples.e3, collection.contains(samples.e3));
- assertTrue("should contain " + samples.e0, collection.contains(samples.e0));
+ collection.addAll(MinimalCollection.of(e3(), e0())));
+ assertTrue("should contain " + e3(), collection.contains(e3()));
+ assertTrue("should contain " + e0(), collection.contains(e0()));
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
@CollectionSize.Require(absent = ZERO)
public void testAddAll_unsupportedSomePresent() {
try {
- collection.addAll(MinimalCollection.of(samples.e3, samples.e0));
+ collection.addAll(MinimalCollection.of(e3(), e0()));
fail("addAll(somePresent) should throw");
} catch (UnsupportedOperationException expected) {
}
@@ -105,7 +105,7 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
public void testAddAllConcurrentWithIteration() {
try {
Iterator<E> iterator = collection.iterator();
- assertTrue(collection.addAll(MinimalCollection.of(samples.e3, samples.e0)));
+ assertTrue(collection.addAll(MinimalCollection.of(e3(), e0())));
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -118,7 +118,7 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
public void testAddAll_unsupportedAllPresent() {
try {
assertFalse("addAll(allPresent) should return false or throw",
- collection.addAll(MinimalCollection.of(samples.e0)));
+ collection.addAll(MinimalCollection.of(e0())));
} catch (UnsupportedOperationException tolerated) {
}
expectUnchanged();
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddTester.java
index dd8c3dd..16ca4bf 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionAddTester.java
@@ -44,19 +44,19 @@ public class CollectionAddTester<E> extends AbstractCollectionTester<E> {
@CollectionFeature.Require(SUPPORTS_ADD)
public void testAdd_supportedNotPresent() {
assertTrue("add(notPresent) should return true",
- collection.add(samples.e3));
- expectAdded(samples.e3);
+ collection.add(e3()));
+ expectAdded(e3());
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
public void testAdd_unsupportedNotPresent() {
try {
- collection.add(samples.e3);
+ collection.add(e3());
fail("add(notPresent) should throw");
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
@@ -64,7 +64,7 @@ public class CollectionAddTester<E> extends AbstractCollectionTester<E> {
public void testAdd_unsupportedPresent() {
try {
assertFalse("add(present) should return false or throw",
- collection.add(samples.e0));
+ collection.add(e0()));
} catch (UnsupportedOperationException tolerated) {
}
expectUnchanged();
@@ -97,7 +97,7 @@ public class CollectionAddTester<E> extends AbstractCollectionTester<E> {
public void testAddConcurrentWithIteration() {
try {
Iterator<E> iterator = collection.iterator();
- assertTrue(collection.add(samples.e3));
+ assertTrue(collection.add(e3()));
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionToArrayTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionToArrayTester.java
index e3dfb67..6b8ac48 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionToArrayTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/CollectionToArrayTester.java
@@ -118,8 +118,8 @@ public class CollectionToArrayTester<E> extends AbstractCollectionTester<E> {
public void testToArray_oversizedArray() {
E[] array = getSubjectGenerator().createArray(getNumElements() + 2);
- array[getNumElements()] = samples.e3;
- array[getNumElements() + 1] = samples.e3;
+ array[getNumElements()] = e3();
+ array[getNumElements() + 1] = e3();
assertSame("toArray(overSizedE[]) should return the given array",
array, collection.toArray(array));
@@ -139,8 +139,8 @@ public class CollectionToArrayTester<E> extends AbstractCollectionTester<E> {
@CollectionFeature.Require(KNOWN_ORDER)
public void testToArray_oversizedArray_ordered() {
E[] array = getSubjectGenerator().createArray(getNumElements() + 2);
- array[getNumElements()] = samples.e3;
- array[getNumElements() + 1] = samples.e3;
+ array[getNumElements()] = e3();
+ array[getNumElements() + 1] = e3();
assertSame("toArray(overSizedE[]) should return the given array",
array, collection.toArray(array));
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddAtIndexTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddAtIndexTester.java
index 75e953f..5371d5e 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddAtIndexTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddAtIndexTester.java
@@ -43,8 +43,8 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@CollectionSize.Require(absent = ZERO)
public void testAddAtIndex_supportedPresent() {
- getList().add(0, samples.e0);
- expectAdded(0, samples.e0);
+ getList().add(0, e0());
+ expectAdded(0, e0());
}
@ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
@@ -55,7 +55,7 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
*/
public void testAddAtIndex_unsupportedPresent() {
try {
- getList().add(0, samples.e0);
+ getList().add(0, e0());
fail("add(n, present) should throw");
} catch (UnsupportedOperationException expected) {
}
@@ -64,8 +64,8 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
public void testAddAtIndex_supportedNotPresent() {
- getList().add(0, samples.e3);
- expectAdded(0, samples.e3);
+ getList().add(0, e3());
+ expectAdded(0, e3());
}
@CollectionFeature.Require(FAILS_FAST_ON_CONCURRENT_MODIFICATION)
@@ -73,7 +73,7 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
public void testAddAtIndexConcurrentWithIteration() {
try {
Iterator<E> iterator = collection.iterator();
- getList().add(0, samples.e3);
+ getList().add(0, e3());
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -84,26 +84,26 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
@ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
public void testAddAtIndex_unsupportedNotPresent() {
try {
- getList().add(0, samples.e3);
+ getList().add(0, e3());
fail("add(n, notPresent) should throw");
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@CollectionSize.Require(absent = {ZERO, ONE})
public void testAddAtIndex_middle() {
- getList().add(getNumElements() / 2, samples.e3);
- expectAdded(getNumElements() / 2, samples.e3);
+ getList().add(getNumElements() / 2, e3());
+ expectAdded(getNumElements() / 2, e3());
}
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@CollectionSize.Require(absent = ZERO)
public void testAddAtIndex_end() {
- getList().add(getNumElements(), samples.e3);
- expectAdded(getNumElements(), samples.e3);
+ getList().add(getNumElements(), e3());
+ expectAdded(getNumElements(), e3());
}
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@@ -129,23 +129,23 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
public void testAddAtIndex_negative() {
try {
- getList().add(-1, samples.e3);
+ getList().add(-1, e3());
fail("add(-1, e) should throw");
} catch (IndexOutOfBoundsException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
public void testAddAtIndex_tooLarge() {
try {
- getList().add(getNumElements() + 1, samples.e3);
+ getList().add(getNumElements() + 1, e3());
fail("add(size + 1, e) should throw");
} catch (IndexOutOfBoundsException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
}
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddTester.java
index c4c8b2c..51be66d 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListAddTester.java
@@ -40,8 +40,8 @@ public class ListAddTester<E> extends AbstractListTester<E> {
@CollectionFeature.Require(SUPPORTS_ADD)
@CollectionSize.Require(absent = ZERO)
public void testAdd_supportedPresent() {
- assertTrue("add(present) should return true", getList().add(samples.e0));
- expectAdded(samples.e0);
+ assertTrue("add(present) should return true", getList().add(e0()));
+ expectAdded(e0());
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
@@ -52,7 +52,7 @@ public class ListAddTester<E> extends AbstractListTester<E> {
*/
public void testAdd_unsupportedPresent() {
try {
- getList().add(samples.e0);
+ getList().add(e0());
fail("add(present) should throw");
} catch (UnsupportedOperationException expected) {
}
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListListIteratorTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListListIteratorTester.java
index 6c62083..049c320 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListListIteratorTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListListIteratorTester.java
@@ -65,7 +65,7 @@ public class ListListIteratorTester<E> extends AbstractListTester<E> {
private void runListIteratorTest(Set<IteratorFeature> features) {
new ListIteratorTester<E>(
- listListIteratorTesterNumIterations(), singleton(samples.e4), features,
+ listListIteratorTesterNumIterations(), singleton(e4()), features,
Helpers.copyToList(getOrderedElements()), 0) {
{
// TODO: don't set this universally
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSetTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSetTester.java
index 121d7b0..ccacc53 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSetTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSetTester.java
@@ -37,7 +37,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_SET)
@CollectionSize.Require(absent = ZERO)
public void testSet() {
- doTestSet(samples.e3);
+ doTestSet(e3());
}
@CollectionSize.Require(absent = ZERO)
@@ -56,7 +56,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
elements[i] = null;
collection = getSubjectGenerator().create(elements);
- doTestSet(samples.e3);
+ doTestSet(e3());
}
private void doTestSet(E newValue) {
@@ -73,7 +73,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_SET)
public void testSet_indexTooLow() {
try {
- getList().set(-1, samples.e3);
+ getList().set(-1, e3());
fail("set(-1) should throw IndexOutOfBoundsException");
} catch (IndexOutOfBoundsException expected) {
}
@@ -84,7 +84,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
public void testSet_indexTooHigh() {
int index = getNumElements();
try {
- getList().set(index, samples.e3);
+ getList().set(index, e3());
fail("set(size) should throw IndexOutOfBoundsException");
} catch (IndexOutOfBoundsException expected) {
}
@@ -95,7 +95,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
@ListFeature.Require(absent = SUPPORTS_SET)
public void testSet_unsupported() {
try {
- getList().set(aValidIndex(), samples.e3);
+ getList().set(aValidIndex(), e3());
fail("set() should throw UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
@@ -106,7 +106,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
@ListFeature.Require(absent = SUPPORTS_SET)
public void testSet_unsupportedByEmptyList() {
try {
- getList().set(0, samples.e3);
+ getList().set(0, e3());
fail("set() should throw UnsupportedOperationException "
+ "or IndexOutOfBoundsException");
} catch (UnsupportedOperationException tolerated) {
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSubListTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSubListTester.java
index c2fc1b7..52bd42c 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSubListTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/ListSubListTester.java
@@ -109,17 +109,17 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
public void testSubList_subListAddAffectsOriginal() {
List<E> subList = getList().subList(0, 0);
- subList.add(samples.e3);
- expectAdded(0, samples.e3);
+ subList.add(e3());
+ expectAdded(0, e3());
}
@ListFeature.Require(SUPPORTS_SET)
@CollectionSize.Require(absent = ZERO)
public void testSubList_subListSetAffectsOriginal() {
List<E> subList = getList().subList(0, 1);
- subList.set(0, samples.e3);
+ subList.set(0, e3());
List<E> expected = Helpers.copyToList(createSamplesArray());
- expected.set(0, samples.e3);
+ expected.set(0, e3());
expectContents(expected);
}
@@ -127,17 +127,17 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testSubList_originalListSetAffectsSubList() {
List<E> subList = getList().subList(0, 1);
- getList().set(0, samples.e3);
+ getList().set(0, e3());
assertEquals("A set() call to a list after a sublist has been created "
+ "should be reflected in the sublist",
- Collections.singletonList(samples.e3), subList);
+ Collections.singletonList(e3()), subList);
}
@ListFeature.Require(SUPPORTS_REMOVE_WITH_INDEX)
@CollectionSize.Require(absent = {ZERO, ONE})
public void testSubList_subListRemoveAffectsOriginalLargeList() {
List<E> subList = getList().subList(1, 3);
- subList.remove(samples.e2);
+ subList.remove(e2());
List<E> expected = Helpers.copyToList(createSamplesArray());
expected.remove(2);
expectContents(expected);
@@ -147,17 +147,17 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(absent = {ZERO, ONE})
public void testSubList_subListAddAtIndexAffectsOriginalLargeList() {
List<E> subList = getList().subList(2, 3);
- subList.add(0, samples.e3);
- expectAdded(2, samples.e3);
+ subList.add(0, e3());
+ expectAdded(2, e3());
}
@ListFeature.Require(SUPPORTS_SET)
@CollectionSize.Require(absent = {ZERO, ONE})
public void testSubList_subListSetAffectsOriginalLargeList() {
List<E> subList = getList().subList(1, 2);
- subList.set(0, samples.e3);
+ subList.set(0, e3());
List<E> expected = Helpers.copyToList(createSamplesArray());
- expected.set(1, samples.e3);
+ expected.set(1, e3());
expectContents(expected);
}
@@ -165,10 +165,10 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(absent = {ZERO, ONE})
public void testSubList_originalListSetAffectsSubListLargeList() {
List<E> subList = getList().subList(1, 3);
- getList().set(1, samples.e3);
+ getList().set(1, e3());
assertEquals("A set() call to a list after a sublist has been created "
+ "should be reflected in the sublist",
- Arrays.asList(samples.e3, samples.e2), subList);
+ Arrays.asList(e3(), e2()), subList);
}
public void testSubList_ofSubListEmpty() {
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapCreationTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapCreationTester.java
index 5870e6f..93eec35 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapCreationTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapCreationTester.java
@@ -127,7 +127,7 @@ public class MapCreationTester<K, V> extends AbstractMapTester<K, V> {
private Entry<K, V>[] getEntriesMultipleNonNullKeys() {
Entry<K, V>[] entries = createSamplesArray();
- entries[0] = entry(samples.e1.getKey(), samples.e0.getValue());
+ entries[0] = entry(k1(), v0());
return entries;
}
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutAllTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutAllTester.java
index 7ece1c7..3357792 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutAllTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutAllTester.java
@@ -53,8 +53,8 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
@Override public void setUp() throws Exception {
super.setUp();
- containsNullKey = singletonList(entry(null, samples.e3.getValue()));
- containsNullValue = singletonList(entry(samples.e3.getKey(), null));
+ containsNullKey = singletonList(entry(null, v3()));
+ containsNullValue = singletonList(entry(k3(), null));
}
@MapFeature.Require(SUPPORTS_PUT)
@@ -75,7 +75,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAll_supportedNonePresent() {
putAll(createDisjointCollection());
- expectAdded(samples.e3, samples.e4);
+ expectAdded(e3(), e4());
}
@MapFeature.Require(absent = SUPPORTS_PUT)
@@ -86,14 +86,14 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- expectMissing(samples.e3, samples.e4);
+ expectMissing(e3(), e4());
}
@MapFeature.Require(SUPPORTS_PUT)
@CollectionSize.Require(absent = ZERO)
public void testPutAll_supportedSomePresent() {
- putAll(MinimalCollection.of(samples.e3, samples.e0));
- expectAdded(samples.e3);
+ putAll(MinimalCollection.of(e3(), e0()));
+ expectAdded(e3());
}
@MapFeature.Require({ FAILS_FAST_ON_CONCURRENT_MODIFICATION,
@@ -102,7 +102,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
public void testPutAllSomePresentConcurrentWithEntrySetIteration() {
try {
Iterator<Entry<K, V>> iterator = getMap().entrySet().iterator();
- putAll(MinimalCollection.of(samples.e3, samples.e0));
+ putAll(MinimalCollection.of(e3(), e0()));
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -114,7 +114,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testPutAll_unsupportedSomePresent() {
try {
- putAll(MinimalCollection.of(samples.e3, samples.e0));
+ putAll(MinimalCollection.of(e3(), e0()));
fail("putAll(somePresent) should throw");
} catch (UnsupportedOperationException expected) {
}
@@ -125,7 +125,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testPutAll_unsupportedAllPresent() {
try {
- putAll(MinimalCollection.of(samples.e0));
+ putAll(MinimalCollection.of(e0()));
} catch (UnsupportedOperationException tolerated) {
}
expectUnchanged();
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutTester.java
index 014bdb2..58f647a 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/MapPutTester.java
@@ -50,16 +50,16 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
@Override public void setUp() throws Exception {
super.setUp();
- nullKeyEntry = entry(null, samples.e3.getValue());
- nullValueEntry = entry(samples.e3.getKey(), null);
+ nullKeyEntry = entry(null, v3());
+ nullValueEntry = entry(k3(), null);
nullKeyValueEntry = entry(null, null);
- presentKeyNullValueEntry = entry(samples.e0.getKey(), null);
+ presentKeyNullValueEntry = entry(k0(), null);
}
@MapFeature.Require(SUPPORTS_PUT)
public void testPut_supportedNotPresent() {
- assertNull("put(notPresent, value) should return null", put(samples.e3));
- expectAdded(samples.e3);
+ assertNull("put(notPresent, value) should return null", put(e3()));
+ expectAdded(e3());
}
@MapFeature.Require({FAILS_FAST_ON_CONCURRENT_MODIFICATION, SUPPORTS_PUT})
@@ -67,7 +67,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
public void testPutAbsentConcurrentWithEntrySetIteration() {
try {
Iterator<Entry<K, V>> iterator = getMap().entrySet().iterator();
- put(samples.e3);
+ put(e3());
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -80,7 +80,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
public void testPutAbsentConcurrentWithKeySetIteration() {
try {
Iterator<K> iterator = getMap().keySet().iterator();
- put(samples.e3);
+ put(e3());
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -93,7 +93,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
public void testPutAbsentConcurrentWithValueIteration() {
try {
Iterator<V> iterator = getMap().values().iterator();
- put(samples.e3);
+ put(e3());
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -104,12 +104,12 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
@MapFeature.Require(absent = SUPPORTS_PUT)
public void testPut_unsupportedNotPresent() {
try {
- put(samples.e3);
+ put(e3());
fail("put(notPresent, value) should throw");
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
@MapFeature.Require(absent = SUPPORTS_PUT)
@@ -117,7 +117,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
public void testPut_unsupportedPresentExistingValue() {
try {
assertEquals("put(present, existingValue) should return present or throw",
- samples.e0.getValue(), put(samples.e0));
+ v0(), put(e0()));
} catch (UnsupportedOperationException tolerated) {
}
expectUnchanged();
@@ -127,7 +127,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testPut_unsupportedPresentDifferentValue() {
try {
- getMap().put(samples.e0.getKey(), samples.e3.getValue());
+ getMap().put(k0(), v3());
fail("put(present, differentValue) should throw");
} catch (UnsupportedOperationException expected) {
}
@@ -143,7 +143,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
@MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS})
@CollectionSize.Require(absent = ZERO)
public void testPut_nullKeySupportedPresent() {
- Entry<K, V> newEntry = entry(null, samples.e3.getValue());
+ Entry<K, V> newEntry = entry(null, v3());
initMapWithNullKey();
assertEquals("put(present, value) should return the associated value",
getValueForNullKey(), put(newEntry));
@@ -187,7 +187,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testPut_replaceWithNullValueSupported() {
assertEquals("put(present, null) should return the associated value",
- samples.e0.getValue(), put(presentKeyNullValueEntry));
+ v0(), put(presentKeyNullValueEntry));
expectReplacement(presentKeyNullValueEntry);
}
@@ -216,7 +216,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
@MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
@CollectionSize.Require(absent = ZERO)
public void testPut_replaceNullValueWithNonNullSupported() {
- Entry<K, V> newEntry = entry(getKeyForNullValue(), samples.e3.getValue());
+ Entry<K, V> newEntry = entry(getKeyForNullValue(), v3());
initMapWithNullValue();
assertNull("put(present, value) should return the associated value (null)",
put(newEntry));
diff --git a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/SetAddTester.java b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/SetAddTester.java
index ba84654..5e07e1f 100644
--- a/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/SetAddTester.java
+++ b/guava-gwt/test-super/com/google/common/collect/testing/super/com/google/common/collect/testing/testers/SetAddTester.java
@@ -36,7 +36,7 @@ public class SetAddTester<E> extends AbstractSetTester<E> {
@CollectionFeature.Require(SUPPORTS_ADD)
@CollectionSize.Require(absent = ZERO)
public void testAdd_supportedPresent() {
- assertFalse("add(present) should return false", getSet().add(samples.e0));
+ assertFalse("add(present) should return false", getSet().add(e0()));
expectUnchanged();
}
diff --git a/guava-gwt/test-super/com/google/common/io/super/com/google/common/io/BaseEncodingTest.java b/guava-gwt/test-super/com/google/common/io/super/com/google/common/io/BaseEncodingTest.java
index cbfa51f..9374350 100644
--- a/guava-gwt/test-super/com/google/common/io/super/com/google/common/io/BaseEncodingTest.java
+++ b/guava-gwt/test-super/com/google/common/io/super/com/google/common/io/BaseEncodingTest.java
@@ -18,6 +18,7 @@ import static com.google.common.io.BaseEncoding.base16;
import static com.google.common.io.BaseEncoding.base32;
import static com.google.common.io.BaseEncoding.base32Hex;
import static com.google.common.io.BaseEncoding.base64;
+import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Ascii;
@@ -30,6 +31,8 @@ import junit.framework.TestCase;
import java.io.UnsupportedEncodingException;
+import javax.annotation.Nullable;
+
/**
* Tests for {@code BaseEncoding}.
*
@@ -93,12 +96,16 @@ public class BaseEncodingTest extends TestCase {
public void testBase64InvalidDecodings() {
// These contain bytes not in the decodabet.
- assertFailsToDecode(base64(), "\u007f");
- assertFailsToDecode(base64(), "Wf2!");
+ assertFailsToDecode(base64(), "A\u007f", "Unrecognized character: 0x7f");
+ assertFailsToDecode(base64(), "Wf2!", "Unrecognized character: !");
// This sentence just isn't base64() encoded.
assertFailsToDecode(base64(), "let's not talk of love or chains!");
// A 4n+1 length string is never legal base64().
- assertFailsToDecode(base64(), "12345");
+ assertFailsToDecode(base64(), "12345", "Invalid input length 5");
+ // These have a combination of invalid length, unrecognized characters and wrong padding.
+ assertFailsToDecode(base64(), "AB=C", "Unrecognized character: =");
+ assertFailsToDecode(base64(), "A=BCD", "Invalid input length 5");
+ assertFailsToDecode(base64(), "?", "Invalid input length 1");
}
@SuppressWarnings("ReturnValueIgnored")
@@ -143,6 +150,14 @@ public class BaseEncodingTest extends TestCase {
testEncodingWithSeparators(enc, "foobar", "Zm9vYmFy");
}
+ public void testBase64Offset() {
+ testEncodesWithOffset(base64(), "foobar", 0, 6, "Zm9vYmFy");
+ testEncodesWithOffset(base64(), "foobar", 1, 5, "b29iYXI=");
+ testEncodesWithOffset(base64(), "foobar", 2, 3, "b2Jh");
+ testEncodesWithOffset(base64(), "foobar", 3, 1, "Yg==");
+ testEncodesWithOffset(base64(), "foobar", 4, 0, "");
+ }
+
public void testBase32() {
// The following test vectors are specified in RFC 4648 itself
testEncodingWithCasing(base32(), "", "");
@@ -176,20 +191,32 @@ public class BaseEncodingTest extends TestCase {
public void testBase32InvalidDecodings() {
// These contain bytes not in the decodabet.
- assertFailsToDecode(base32(), "\u007f");
- assertFailsToDecode(base32(), "Wf2!");
+ assertFailsToDecode(base32(), "A ", "Unrecognized character: 0x20");
+ assertFailsToDecode(base32(), "Wf2!", "Unrecognized character: f");
// This sentence just isn't base32() encoded.
assertFailsToDecode(base32(), "let's not talk of love or chains!");
// An 8n+{1,3,6} length string is never legal base32.
- assertFailsToDecode(base32(), "A");
+ assertFailsToDecode(base32(), "A", "Invalid input length 1");
assertFailsToDecode(base32(), "ABC");
assertFailsToDecode(base32(), "ABCDEF");
+ // These have a combination of invalid length, unrecognized characters and wrong padding.
+ assertFailsToDecode(base32(), "AB=C", "Unrecognized character: =");
+ assertFailsToDecode(base32(), "A=BCDE", "Invalid input length 6");
+ assertFailsToDecode(base32(), "?", "Invalid input length 1");
}
public void testBase32UpperCaseIsNoOp() {
assertSame(base32(), base32().upperCase());
}
+ public void testBase32Offset() {
+ testEncodesWithOffset(base32(), "foobar", 0, 6, "MZXW6YTBOI======");
+ testEncodesWithOffset(base32(), "foobar", 1, 5, "N5XWEYLS");
+ testEncodesWithOffset(base32(), "foobar", 2, 3, "N5RGC===");
+ testEncodesWithOffset(base32(), "foobar", 3, 1, "MI======");
+ testEncodesWithOffset(base32(), "foobar", 4, 0, "");
+ }
+
public void testBase32Hex() {
// The following test vectors are specified in RFC 4648 itself
testEncodingWithCasing(base32Hex(), "", "");
@@ -212,8 +239,8 @@ public class BaseEncodingTest extends TestCase {
public void testBase32HexInvalidDecodings() {
// These contain bytes not in the decodabet.
- assertFailsToDecode(base32Hex(), "\u007f");
- assertFailsToDecode(base32Hex(), "Wf2!");
+ assertFailsToDecode(base32Hex(), "A\u007f", "Unrecognized character: 0x7f");
+ assertFailsToDecode(base32Hex(), "Wf2!", "Unrecognized character: W");
// This sentence just isn't base32 encoded.
assertFailsToDecode(base32Hex(), "let's not talk of love or chains!");
// An 8n+{1,3,6} length string is never legal base32.
@@ -240,6 +267,25 @@ public class BaseEncodingTest extends TestCase {
assertSame(base16(), base16().upperCase());
}
+ public void testBase16InvalidDecodings() {
+ // These contain bytes not in the decodabet.
+ assertFailsToDecode(base16(), "\n\n", "Unrecognized character: 0xa");
+ assertFailsToDecode(base16(), "EFGH", "Unrecognized character: G");
+ // Valid base16 strings always have an even length.
+ assertFailsToDecode(base16(), "A", "Invalid input length 1");
+ assertFailsToDecode(base16(), "ABC");
+ // These have a combination of invalid length and unrecognized characters.
+ assertFailsToDecode(base16(), "?", "Invalid input length 1");
+ }
+
+ public void testBase16Offset() {
+ testEncodesWithOffset(base16(), "foobar", 0, 6, "666F6F626172");
+ testEncodesWithOffset(base16(), "foobar", 1, 5, "6F6F626172");
+ testEncodesWithOffset(base16(), "foobar", 2, 3, "6F6261");
+ testEncodesWithOffset(base16(), "foobar", 3, 1, "62");
+ testEncodesWithOffset(base16(), "foobar", 4, 0, "");
+ }
+
private static void testEncodingWithCasing(
BaseEncoding encoding, String decoded, String encoded) {
testEncodingWithSeparators(encoding, decoded, encoded);
@@ -266,39 +312,48 @@ public class BaseEncodingTest extends TestCase {
}
private static void testEncodes(BaseEncoding encoding, String decoded, String encoded) {
- byte[] bytes;
- try {
- // GWT does not support String.getBytes(Charset)
- bytes = decoded.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError();
- }
- assertEquals(encoded, encoding.encode(bytes));
+ assertEquals(encoded, encoding.encode(getBytes(decoded)));
+ }
+
+ private static void testEncodesWithOffset(
+ BaseEncoding encoding, String decoded, int offset, int len, String encoded) {
+ assertEquals(encoded, encoding.encode(getBytes(decoded), offset, len));
}
private static void testDecodes(BaseEncoding encoding, String encoded, String decoded) {
- byte[] bytes;
- try {
- // GWT does not support String.getBytes(Charset)
- bytes = decoded.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError();
- }
- assertEquals(bytes, encoding.decode(encoded));
+ assertEquals(getBytes(decoded), encoding.decode(encoded));
}
private static void assertFailsToDecode(BaseEncoding encoding, String cannotDecode) {
+ assertFailsToDecode(encoding, cannotDecode, null);
+ }
+
+ private static void assertFailsToDecode(
+ BaseEncoding encoding, String cannotDecode, @Nullable String expectedMessage) {
try {
encoding.decode(cannotDecode);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {
- // success
+ if (expectedMessage != null) {
+ assertThat(expected.getCause()).hasMessage(expectedMessage);
+ }
}
try {
encoding.decodeChecked(cannotDecode);
fail("Expected DecodingException");
} catch (DecodingException expected) {
- // success
+ if (expectedMessage != null) {
+ assertThat(expected).hasMessage(expectedMessage);
+ }
+ }
+ }
+
+ private static byte[] getBytes(String decoded) {
+ try {
+ // GWT does not support String.getBytes(Charset)
+ return decoded.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new AssertionError();
}
}
diff --git a/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/InternetDomainNameTest.java b/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/InternetDomainNameTest.java
index 8dda0c5..ae4ccf2 100644
--- a/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/InternetDomainNameTest.java
+++ b/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/InternetDomainNameTest.java
@@ -109,7 +109,7 @@ public final class InternetDomainNameTest extends TestCase {
);
private static final ImmutableSet<String> NO_PS = ImmutableSet.of(
- "www", "foo.google", "x.y.z");
+ "www", "foo.ihopethiswillneverbeapublicsuffix", "x.y.z");
private static final ImmutableSet<String> NON_PS = ImmutableSet.of(
"foo.bar.com", "foo.ca", "foo.bar.ca",
diff --git a/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/MediaTypeTest.java b/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/MediaTypeTest.java
index a6eef7e..571c7f9 100644
--- a/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/MediaTypeTest.java
+++ b/guava-gwt/test-super/com/google/common/net/super/com/google/common/net/MediaTypeTest.java
@@ -26,10 +26,9 @@ import static com.google.common.net.MediaType.ANY_VIDEO_TYPE;
import static com.google.common.net.MediaType.HTML_UTF_8;
import static com.google.common.net.MediaType.JPEG;
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
+import static com.google.common.truth.Truth.assertThat;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
-import com.google.common.base.Optional;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.testing.EqualsTester;
@@ -44,7 +43,6 @@ import java.nio.charset.UnsupportedCharsetException;
*
* @author Gregory Kick
*/
- at Beta
@GwtCompatible(emulated = true)
public class MediaTypeTest extends TestCase {
@@ -273,9 +271,8 @@ public class MediaTypeTest extends TestCase {
}
public void testGetCharset() {
- assertEquals(Optional.absent(), MediaType.parse("text/plain").charset());
- assertEquals(Optional.of(UTF_8),
- MediaType.parse("text/plain; charset=utf-8").charset());
+ assertThat(MediaType.parse("text/plain").charset()).isAbsent();
+ assertThat(MediaType.parse("text/plain; charset=utf-8").charset()).hasValue(UTF_8);
}
public void testGetCharset_tooMany() {
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BooleansTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BooleansTest.java
index 0488aa9..2ebd5af 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BooleansTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BooleansTest.java
@@ -120,6 +120,7 @@ public class BooleansTest extends TestCase {
Booleans.ensureCapacity(new boolean[] {true}, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Booleans.ensureCapacity(ARRAY_FALSE, -1, 1);
@@ -193,6 +194,7 @@ public class BooleansTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Boolean> list = Arrays.asList(false, true, null);
try {
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BytesTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BytesTest.java
index 44de341..56c5872 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BytesTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/BytesTest.java
@@ -143,6 +143,7 @@ public class BytesTest extends TestCase {
Bytes.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Bytes.ensureCapacity(ARRAY1, -1, 1);
@@ -189,6 +190,7 @@ public class BytesTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Byte> list = Arrays.asList((byte) 0, (byte) 1, null);
try {
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/CharsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/CharsTest.java
index 18dcf97..84dd2eb 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/CharsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/CharsTest.java
@@ -72,6 +72,7 @@ public class CharsTest extends TestCase {
assertEquals(LEAST, Chars.saturatedCast(Long.MIN_VALUE));
}
+ @SuppressWarnings("CheckReturnValue")
private void assertCastFails(long value) {
try {
Chars.checkedCast(value);
@@ -165,6 +166,7 @@ public class CharsTest extends TestCase {
(char) 3));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
Chars.max();
@@ -181,6 +183,7 @@ public class CharsTest extends TestCase {
(char) 5, (char) 3, (char) 0, (char) 9));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
Chars.min();
@@ -221,6 +224,7 @@ public class CharsTest extends TestCase {
Chars.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Chars.ensureCapacity(ARRAY1, -1, 1);
@@ -290,6 +294,7 @@ public class CharsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Character> list = Arrays.asList((char) 0, (char) 1, null);
try {
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/DoublesTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/DoublesTest.java
index 84717f3..dfa66a4 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/DoublesTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/DoublesTest.java
@@ -177,6 +177,7 @@ public class DoublesTest extends TestCase {
assertEquals(-1, Doubles.lastIndexOf(new double[] {NaN, 5.0}, NaN));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
Doubles.max();
@@ -198,6 +199,7 @@ public class DoublesTest extends TestCase {
assertTrue(Double.isNaN(Doubles.max(VALUES)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
Doubles.min();
@@ -243,6 +245,7 @@ public class DoublesTest extends TestCase {
Doubles.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Doubles.ensureCapacity(ARRAY1, -1, 1);
@@ -312,6 +315,7 @@ public class DoublesTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Double> list = Arrays.asList((double) 0, (double) 1, null);
try {
@@ -345,7 +349,7 @@ public class DoublesTest extends TestCase {
list.set(0, (double) 2);
assertTrue(Arrays.equals(new double[] {(double) 2, (double) 1}, array));
array[1] = (double) 3;
- assertThat(list).has().exactly((double) 2, (double) 3).inOrder();
+ assertThat(list).containsExactly((double) 2, (double) 3).inOrder();
}
public void testAsList_toArray_roundTrip() {
@@ -406,6 +410,7 @@ public class DoublesTest extends TestCase {
assertEquals((Double) 1e-6, converter.convert("1e-6"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testStringConverter_convertError() {
try {
Doubles.stringConverter().convert("notanumber");
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/FloatsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/FloatsTest.java
index d136719..d3c884c 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/FloatsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/FloatsTest.java
@@ -174,6 +174,7 @@ public class FloatsTest extends TestCase {
assertEquals(-1, Floats.lastIndexOf(new float[] {NaN, 5f}, NaN));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
Floats.max();
@@ -195,6 +196,7 @@ public class FloatsTest extends TestCase {
assertTrue(Float.isNaN(Floats.max(VALUES)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
Floats.min();
@@ -240,6 +242,7 @@ public class FloatsTest extends TestCase {
Floats.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Floats.ensureCapacity(ARRAY1, -1, 1);
@@ -302,6 +305,7 @@ public class FloatsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Float> list = Arrays.asList((float) 0, (float) 1, null);
try {
@@ -335,7 +339,7 @@ public class FloatsTest extends TestCase {
list.set(0, (float) 2);
assertTrue(Arrays.equals(new float[] {(float) 2, (float) 1}, array));
array[1] = (float) 3;
- assertThat(list).has().exactly((float) 2, (float) 3).inOrder();
+ assertThat(list).containsExactly((float) 2, (float) 3).inOrder();
}
public void testAsList_toArray_roundTrip() {
@@ -384,6 +388,7 @@ public class FloatsTest extends TestCase {
{ "", "+-", "+-0", " 5", "32 ", " 55 ", "infinity", "POSITIVE_INFINITY", "0x9A", "0x9A.bE-5",
".", ".e5", "NaNd", "InfinityF" };
+ @SuppressWarnings("CheckReturnValue")
public void testStringConverter_convertError() {
try {
Floats.stringConverter().convert("notanumber");
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/IntsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/IntsTest.java
index f1e7ed1..36aef0e 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/IntsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/IntsTest.java
@@ -73,6 +73,7 @@ public class IntsTest extends TestCase {
assertEquals(LEAST, Ints.saturatedCast(Long.MIN_VALUE));
}
+ @SuppressWarnings("CheckReturnValue")
private static void assertCastFails(long value) {
try {
Ints.checkedCast(value);
@@ -166,6 +167,7 @@ public class IntsTest extends TestCase {
(int) 3));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
Ints.max();
@@ -182,6 +184,7 @@ public class IntsTest extends TestCase {
(int) 5, (int) 3, (int) 0, (int) 9));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
Ints.min();
@@ -222,6 +225,7 @@ public class IntsTest extends TestCase {
Ints.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Ints.ensureCapacity(ARRAY1, -1, 1);
@@ -292,6 +296,7 @@ public class IntsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Integer> list = Arrays.asList((int) 0, (int) 1, null);
try {
@@ -367,6 +372,7 @@ public class IntsTest extends TestCase {
assertEquals((Integer) 438, converter.convert("0666"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testStringConverter_convertError() {
try {
Ints.stringConverter().convert("notanumber");
@@ -424,4 +430,52 @@ public class IntsTest extends TestCase {
private static void tryParseAndAssertEquals(Integer expected, String value) {
assertEquals(expected, Ints.tryParse(value));
}
+
+ public void testTryParse_radix() {
+ for (int radix = Character.MIN_RADIX;
+ radix <= Character.MAX_RADIX; radix++) {
+ radixEncodeParseAndAssertEquals(0, radix);
+ radixEncodeParseAndAssertEquals(8000, radix);
+ radixEncodeParseAndAssertEquals(-8000, radix);
+ radixEncodeParseAndAssertEquals(GREATEST, radix);
+ radixEncodeParseAndAssertEquals(LEAST, radix);
+ assertNull("Radix: " + radix, Ints.tryParse("9999999999999999", radix));
+ assertNull("Radix: " + radix,
+ Ints.tryParse(Long.toString((long) GREATEST + 1, radix), radix));
+ assertNull("Radix: " + radix,
+ Ints.tryParse(Long.toString((long) LEAST - 1, radix), radix));
+ }
+ assertNull("Hex string and dec parm", Ints.tryParse("FFFF", 10));
+ assertEquals("Mixed hex case", 65535, (int) Ints.tryParse("ffFF", 16));
+ }
+
+ /**
+ * Encodes the an integer as a string with given radix, then uses
+ * {@link Ints#tryParse(String, int)} to parse the result. Asserts the result
+ * is the same as what we started with.
+ */
+ private static void radixEncodeParseAndAssertEquals(Integer value,
+ int radix) {
+ assertEquals("Radix: " + radix, value,
+ Ints.tryParse(Integer.toString(value, radix), radix));
+ }
+
+ @SuppressWarnings("CheckReturnValue")
+ public void testTryParse_radixTooBig() {
+ try {
+ Ints.tryParse("0", Character.MAX_RADIX + 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @SuppressWarnings("CheckReturnValue")
+ public void testTryParse_radixTooSmall() {
+ try {
+ Ints.tryParse("0", Character.MIN_RADIX - 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
}
+
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/LongsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/LongsTest.java
index c1556cc..863837e 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/LongsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/LongsTest.java
@@ -132,6 +132,7 @@ public class LongsTest extends TestCase {
(long) 3));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
Longs.max();
@@ -148,6 +149,7 @@ public class LongsTest extends TestCase {
(long) 5, (long) 3, (long) 0, (long) 9));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
Longs.min();
@@ -203,7 +205,10 @@ public class LongsTest extends TestCase {
new byte[] {
(byte) 0xFF, (byte) 0xEE, (byte) 0xDD, (byte) 0xCC,
(byte) 0xBB, (byte) 0xAA, (byte) 0x99, (byte) 0x88}));
+ }
+ @SuppressWarnings("CheckReturnValue")
+ public void testFromByteArrayFails() {
try {
Longs.fromByteArray(new byte[Longs.BYTES - 1]);
fail();
@@ -244,6 +249,7 @@ public class LongsTest extends TestCase {
Longs.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Longs.ensureCapacity(ARRAY1, -1, 1);
@@ -314,6 +320,7 @@ public class LongsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Long> list = Arrays.asList((long) 0, (long) 1, null);
try {
@@ -444,5 +451,51 @@ public class LongsTest extends TestCase {
private static void tryParseAndAssertEquals(Long expected, String value) {
assertEquals(expected, Longs.tryParse(value));
}
+
+ public void testTryParse_radix() {
+ for (int radix = Character.MIN_RADIX;
+ radix <= Character.MAX_RADIX; radix++) {
+ radixEncodeParseAndAssertEquals((long) 0, radix);
+ radixEncodeParseAndAssertEquals((long) 8000, radix);
+ radixEncodeParseAndAssertEquals((long) -8000, radix);
+ radixEncodeParseAndAssertEquals(MAX_VALUE, radix);
+ radixEncodeParseAndAssertEquals(MIN_VALUE, radix);
+ assertNull("Radix: " + radix, Longs.tryParse("999999999999999999999999", radix));
+ assertNull("Radix: " + radix,
+ Longs.tryParse(BigInteger.valueOf(MAX_VALUE).add(BigInteger.ONE).toString(), radix));
+ assertNull("Radix: " + radix,
+ Longs.tryParse(BigInteger.valueOf(MIN_VALUE).subtract(BigInteger.ONE).toString(), radix));
+ }
+ assertNull("Hex string and dec parm", Longs.tryParse("FFFF", 10));
+ assertEquals("Mixed hex case", 65535, Longs.tryParse("ffFF", 16).longValue());
+ }
+
+ /**
+ * Encodes the long as a string with given radix, then uses
+ * {@link Longs#tryParse(String, int)} to parse the result. Asserts the result
+ * is the same as what we started with.
+ */
+ private static void radixEncodeParseAndAssertEquals(Long value, int radix) {
+ assertEquals("Radix: " + radix, value,
+ Longs.tryParse(Long.toString(value, radix), radix));
+ }
+
+ @SuppressWarnings("CheckReturnValue")
+ public void testTryParse_radixTooBig() {
+ try {
+ Longs.tryParse("0", Character.MAX_RADIX + 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @SuppressWarnings("CheckReturnValue")
+ public void testTryParse_radixTooSmall() {
+ try {
+ Longs.tryParse("0", Character.MIN_RADIX - 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
}
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/ShortsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/ShortsTest.java
index 1447f27..958028f 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/ShortsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/ShortsTest.java
@@ -73,6 +73,7 @@ public class ShortsTest extends TestCase {
assertEquals(LEAST, Shorts.saturatedCast(Long.MIN_VALUE));
}
+ @SuppressWarnings("CheckReturnValue")
private static void assertCastFails(long value) {
try {
Shorts.checkedCast(value);
@@ -174,6 +175,7 @@ public class ShortsTest extends TestCase {
(short) 3));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
Shorts.max();
@@ -190,6 +192,7 @@ public class ShortsTest extends TestCase {
(short) 5, (short) 3, (short) 0, (short) 9));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
Shorts.min();
@@ -230,6 +233,7 @@ public class ShortsTest extends TestCase {
Shorts.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Shorts.ensureCapacity(ARRAY1, -1, 1);
@@ -300,6 +304,7 @@ public class ShortsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Short> list = Arrays.asList((short) 0, (short) 1, null);
try {
@@ -375,6 +380,7 @@ public class ShortsTest extends TestCase {
assertEquals((Short) (short) 438, converter.convert("0666"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testStringConverter_convertError() {
try {
Shorts.stringConverter().convert("notanumber");
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/SignedBytesTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/SignedBytesTest.java
index e753df8..8f2074d 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/SignedBytesTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/SignedBytesTest.java
@@ -62,6 +62,7 @@ public class SignedBytesTest extends TestCase {
assertEquals(LEAST, SignedBytes.saturatedCast(Long.MIN_VALUE));
}
+ @SuppressWarnings("CheckReturnValue")
private static void assertCastFails(long value) {
try {
SignedBytes.checkedCast(value);
@@ -91,6 +92,7 @@ public class SignedBytesTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
SignedBytes.max();
@@ -106,6 +108,7 @@ public class SignedBytesTest extends TestCase {
(byte) 0, (byte) -128, (byte) -1, (byte) 127, (byte) 1));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
SignedBytes.min();
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedIntsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedIntsTest.java
index 6e8035d..6bf836f 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedIntsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedIntsTest.java
@@ -42,7 +42,7 @@ public class UnsignedIntsTest extends TestCase {
0xfffffffdL,
0xfffffffeL,
0xffffffffL};
-
+
private static final int LEAST = (int) 0L;
private static final int GREATEST = (int) 0xffffffffL;
@@ -61,7 +61,8 @@ public class UnsignedIntsTest extends TestCase {
}
}
}
-
+
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
UnsignedInts.max();
@@ -69,7 +70,7 @@ public class UnsignedIntsTest extends TestCase {
} catch (IllegalArgumentException expected) {
}
}
-
+
public void testMax() {
assertEquals(LEAST, UnsignedInts.max(LEAST));
assertEquals(GREATEST, UnsignedInts.max(GREATEST));
@@ -78,7 +79,8 @@ public class UnsignedIntsTest extends TestCase {
(int) 0x12345678L, (int) 0x5a4316b8L,
(int) 0xff1a618bL, (int) 0L));
}
-
+
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
UnsignedInts.min();
@@ -140,27 +142,29 @@ public class UnsignedIntsTest extends TestCase {
}
public void testParseInt() {
- try {
- for (long a : UNSIGNED_INTS) {
- assertEquals((int) a, UnsignedInts.parseUnsignedInt(Long.toString(a)));
- }
- } catch (NumberFormatException e) {
- fail(e.getMessage());
+ for (long a : UNSIGNED_INTS) {
+ assertEquals((int) a, UnsignedInts.parseUnsignedInt(Long.toString(a)));
}
+ }
+ @SuppressWarnings("CheckReturnValue")
+ public void testParseIntFail() {
try {
UnsignedInts.parseUnsignedInt(Long.toString(1L << 32));
fail("Expected NumberFormatException");
} catch (NumberFormatException expected) {}
}
- public void testParseIntWithRadix() throws NumberFormatException {
+ public void testParseIntWithRadix() {
for (long a : UNSIGNED_INTS) {
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
assertEquals((int) a, UnsignedInts.parseUnsignedInt(Long.toString(a, radix), radix));
}
}
+ }
+ @SuppressWarnings("CheckReturnValue")
+ public void testParseIntWithRadixLimits() {
// loops through all legal radix values.
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
// tests can successfully parse a number string with this radix.
@@ -177,6 +181,7 @@ public class UnsignedIntsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testParseIntThrowsExceptionForInvalidRadix() {
// Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX,
// inclusive.
@@ -207,6 +212,7 @@ public class UnsignedIntsTest extends TestCase {
assertEquals(0, UnsignedInts.decode("0"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testDecodeIntFails() {
try {
// One more than maximum value
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongTest.java
index 81947d5..4c05236 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongTest.java
@@ -219,7 +219,7 @@ public class UnsignedLongTest extends TestCase {
}
}
- @SuppressWarnings("ReturnValueIgnored")
+ @SuppressWarnings("CheckReturnValue")
public void testModByZero() {
for (long a : TEST_LONGS) {
try {
diff --git a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongsTest.java b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongsTest.java
index 0ecf473..ec7050b 100644
--- a/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongsTest.java
+++ b/guava-gwt/test-super/com/google/common/primitives/super/com/google/common/primitives/UnsignedLongsTest.java
@@ -58,6 +58,7 @@ public class UnsignedLongsTest extends TestCase {
assertTrue(UnsignedLongs.compare(0xff1a618b7f65ea12L, 0xff1a618b7f65ea12L) == 0);
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
UnsignedLongs.max();
@@ -73,7 +74,8 @@ public class UnsignedLongsTest extends TestCase {
0x5a4316b8c153ac4dL, 8L, 100L,
0L, 0x6cf78a4b139a4e2aL, 0xff1a618b7f65ea12L));
}
-
+
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
UnsignedLongs.min();
@@ -133,7 +135,10 @@ public class UnsignedLongsTest extends TestCase {
assertEquals(0xff1a618b7f65ea12L, UnsignedLongs.parseUnsignedLong("18382112080831834642"));
assertEquals(0x5a4316b8c153ac4dL, UnsignedLongs.parseUnsignedLong("6504067269626408013"));
assertEquals(0x6cf78a4b139a4e2aL, UnsignedLongs.parseUnsignedLong("7851896530399809066"));
+ }
+ @SuppressWarnings("CheckReturnValue")
+ public void testParseLongFails() {
try {
// One more than maximum value
UnsignedLongs.parseUnsignedLong("18446744073709551616");
@@ -152,6 +157,7 @@ public class UnsignedLongsTest extends TestCase {
assertEquals(0L, UnsignedLongs.decode("0"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testDecodeLongFails() {
try {
// One more than maximum value
@@ -182,7 +188,10 @@ public class UnsignedLongsTest extends TestCase {
public void testParseLongWithRadix() {
assertEquals(0xffffffffffffffffL, UnsignedLongs.parseUnsignedLong("ffffffffffffffff", 16));
assertEquals(0x1234567890abcdefL, UnsignedLongs.parseUnsignedLong("1234567890abcdef", 16));
+ }
+ @SuppressWarnings("CheckReturnValue")
+ public void testParseLongWithRadixLimits() {
BigInteger max = BigInteger.ZERO.setBit(64).subtract(ONE);
// loops through all legal radix values.
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
@@ -207,6 +216,7 @@ public class UnsignedLongsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testParseLongThrowsExceptionForInvalidRadix() {
// Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX, inclusive.
try {
diff --git a/guava/src/com/google/common/collect/ComputationException.java b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/CallablesTest.java
similarity index 53%
copy from guava/src/com/google/common/collect/ComputationException.java
copy to guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/CallablesTest.java
index ac80d6a..78afff9 100644
--- a/guava/src/com/google/common/collect/ComputationException.java
+++ b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/CallablesTest.java
@@ -14,25 +14,29 @@
* limitations under the License.
*/
-package com.google.common.collect;
+package com.google.common.util.concurrent;
import com.google.common.annotations.GwtCompatible;
-import javax.annotation.Nullable;
+import junit.framework.TestCase;
+
+import java.util.concurrent.Callable;
/**
- * Wraps an exception that occurred during a computation.
+ * Unit tests for {@link Callables}.
*
- * @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @author Isaac Shum
*/
- at GwtCompatible
-public class ComputationException extends RuntimeException {
- /**
- * Creates a new instance with the given cause.
- */
- public ComputationException(@Nullable Throwable cause) {
- super(cause);
+ at GwtCompatible(emulated = true)
+public class CallablesTest extends TestCase {
+
+ public void testReturning() throws Exception {
+ assertNull(Callables.returning(null).call());
+
+ Object value = new Object();
+ Callable<Object> callable = Callables.returning(value);
+ assertSame(value, callable.call());
+ // Expect the same value on subsequent calls
+ assertSame(value, callable.call());
}
- private static final long serialVersionUID = 0;
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/FutureCallbackTest.java
similarity index 80%
copy from guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java
copy to guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/FutureCallbackTest.java
index 14e0179..c05813f 100644
--- a/guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java
+++ b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/FutureCallbackTest.java
@@ -16,15 +16,15 @@
package com.google.common.util.concurrent;
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Preconditions;
import junit.framework.TestCase;
-import org.mockito.Mockito;
-
import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;
-import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
@@ -34,6 +34,7 @@ import javax.annotation.Nullable;
*
* @author Anthony Zana
*/
+ at GwtCompatible(emulated = true)
public class FutureCallbackTest extends TestCase {
public void testSameThreadSuccess() {
SettableFuture<String> f = SettableFuture.create();
@@ -65,6 +66,7 @@ public class FutureCallbackTest extends TestCase {
FutureCallback<String> callback =
new FutureCallback<String>() {
private boolean called = false;
+
@Override
public void onSuccess(String result) {
fail("Was not expecting onSuccess() to be called.");
@@ -73,7 +75,7 @@ public class FutureCallbackTest extends TestCase {
@Override
public synchronized void onFailure(Throwable t) {
assertFalse(called);
- assertTrue(t instanceof CancellationException);
+ assertThat(t).isInstanceOf(CancellationException.class);
called = true;
}
};
@@ -95,40 +97,6 @@ public class FutureCallbackTest extends TestCase {
Futures.addCallback(f, callback);
}
- public void testOnSuccessThrowsRuntimeException() throws Exception {
- RuntimeException exception = new RuntimeException();
- String result = "result";
- SettableFuture<String> future = SettableFuture.create();
- @SuppressWarnings("unchecked") // Safe for a mock
- FutureCallback<String> callback = Mockito.mock(FutureCallback.class);
- Futures.addCallback(future, callback);
- Mockito.doThrow(exception).when(callback).onSuccess(result);
- future.set(result);
- assertEquals(result, future.get());
- Mockito.verify(callback).onSuccess(result);
- Mockito.verifyNoMoreInteractions(callback);
- }
-
- public void testOnSuccessThrowsError() throws Exception {
- class TestError extends Error {}
- TestError error = new TestError();
- String result = "result";
- SettableFuture<String> future = SettableFuture.create();
- @SuppressWarnings("unchecked") // Safe for a mock
- FutureCallback<String> callback = Mockito.mock(FutureCallback.class);
- Futures.addCallback(future, callback);
- Mockito.doThrow(error).when(callback).onSuccess(result);
- try {
- future.set(result);
- fail("Should have thrown");
- } catch (TestError e) {
- assertSame(error, e);
- }
- assertEquals(result, future.get());
- Mockito.verify(callback).onSuccess(result);
- Mockito.verifyNoMoreInteractions(callback);
- }
-
public void testWildcardFuture() {
SettableFuture<String> settable = SettableFuture.create();
ListenableFuture<?> f = settable;
diff --git a/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/FuturesTest.java b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/FuturesTest.java
new file mode 100644
index 0000000..1299f58
--- /dev/null
+++ b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/FuturesTest.java
@@ -0,0 +1,1518 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.util.concurrent.Futures.allAsList;
+import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.TestPlatform.clearInterrupt;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.collect.Lists;
+import com.google.common.testing.TestLogHandler;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+/**
+ * Unit tests for {@link Futures}.
+ *
+ * @author Nishant Thakkar
+ */
+ at SuppressWarnings("CheckReturnValue")
+ at GwtCompatible(emulated = true)
+public class FuturesTest extends TestCase {
+ private static final Logger aggregateFutureLogger =
+ Logger.getLogger(AggregateFuture.class.getName());
+ private final TestLogHandler aggregateFutureLogHandler = new TestLogHandler();
+
+ private static final String DATA1 = "data";
+ private static final String DATA2 = "more data";
+ private static final String DATA3 = "most data";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ aggregateFutureLogger.addHandler(aggregateFutureLogHandler);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ /*
+ * Clear interrupt for future tests.
+ *
+ * (Ideally we would perform interrupts only in threads that we create, but
+ * it's hard to imagine that anything will break in practice.)
+ */
+ clearInterrupt();
+ aggregateFutureLogger.removeHandler(aggregateFutureLogHandler);
+ super.tearDown();
+ }
+
+ public void testImmediateFuture() throws Exception {
+ ListenableFuture<String> future = Futures.immediateFuture(DATA1);
+
+ // Verify that the proper object is returned without waiting
+ assertSame(DATA1, future.get(0L, TimeUnit.MILLISECONDS));
+ }
+
+ public void testMultipleImmediateFutures() throws Exception {
+ ListenableFuture<String> future1 = Futures.immediateFuture(DATA1);
+ ListenableFuture<String> future2 = Futures.immediateFuture(DATA2);
+
+ // Verify that the proper objects are returned without waiting
+ assertSame(DATA1, future1.get(0L, TimeUnit.MILLISECONDS));
+ assertSame(DATA2, future2.get(0L, TimeUnit.MILLISECONDS));
+ }
+
+ public void testImmediateFailedFuture() throws Exception {
+ Exception exception = new Exception();
+ ListenableFuture<String> future =
+ Futures.immediateFailedFuture(exception);
+
+ try {
+ future.get(0L, TimeUnit.MILLISECONDS);
+ fail("This call was supposed to throw an ExecutionException");
+ } catch (ExecutionException expected) {
+ // This is good and expected
+ assertSame(exception, expected.getCause());
+ }
+ }
+
+ public void testImmediateFailedFuture_cancellationException() throws Exception {
+ CancellationException exception = new CancellationException();
+ ListenableFuture<String> future =
+ Futures.immediateFailedFuture(exception);
+
+ try {
+ future.get(0L, TimeUnit.MILLISECONDS);
+ fail("This call was supposed to throw an ExecutionException");
+ } catch (ExecutionException expected) {
+ // This is good and expected
+ assertSame(exception, expected.getCause());
+ assertFalse(future.isCancelled());
+ }
+ }
+
+ private static class MyException extends Exception {
+
+ }
+
+ // Class hierarchy for generics sanity checks
+ private static class Foo {
+
+ }
+
+ private static class FooChild extends Foo {
+
+ }
+
+ private static class Bar {
+
+ }
+
+ private static class BarChild extends Bar {
+
+ }
+
+ public void testTransform_genericsNull() throws Exception {
+ ListenableFuture<?> nullFuture = Futures.immediateFuture(null);
+ ListenableFuture<?> transformedFuture =
+ Futures.transform(nullFuture, Functions.constant(null));
+ assertNull(transformedFuture.get());
+ }
+
+ public void testTransform_genericsHierarchy() throws Exception {
+ ListenableFuture<FooChild> future = Futures.immediateFuture(null);
+ final BarChild barChild = new BarChild();
+ Function<Foo, BarChild> function = new Function<Foo, BarChild>() {
+ @Override
+ public BarChild apply(Foo unused) {
+ return barChild;
+ }
+ };
+ Bar bar = Futures.transform(future, function).get();
+ assertSame(barChild, bar);
+ }
+
+ public void testTransform_cancelPropagatesToInput() throws Exception {
+ SettableFuture<Foo> input = SettableFuture.create();
+ AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
+ throw new AssertionFailedError("Unexpeted call to apply.");
+ }
+ };
+ assertTrue(Futures.transform(input, function).cancel(false));
+ assertTrue(input.isCancelled());
+ assertFalse(input.wasInterrupted());
+ }
+
+ public void testTransform_interruptPropagatesToInput() throws Exception {
+ SettableFuture<Foo> input = SettableFuture.create();
+ AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
+ throw new AssertionFailedError("Unexpeted call to apply.");
+ }
+ };
+ assertTrue(Futures.transform(input, function).cancel(true));
+ assertTrue(input.isCancelled());
+ assertTrue(input.wasInterrupted());
+ }
+
+ public void testTransform_cancelPropagatesToAsyncOutput() throws Exception {
+ ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
+ final SettableFuture<Bar> secondary = SettableFuture.create();
+ AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
+ return secondary;
+ }
+ };
+ assertTrue(Futures.transform(immediate, function).cancel(false));
+ assertTrue(secondary.isCancelled());
+ assertFalse(secondary.wasInterrupted());
+ }
+
+ public void testTransform_interruptPropagatesToAsyncOutput()
+ throws Exception {
+ ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
+ final SettableFuture<Bar> secondary = SettableFuture.create();
+ AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
+ return secondary;
+ }
+ };
+ assertTrue(Futures.transform(immediate, function).cancel(true));
+ assertTrue(secondary.isCancelled());
+ assertTrue(secondary.wasInterrupted());
+ }
+
+ public void testTransformAsync_cancelPropagatesToInput() throws Exception {
+ SettableFuture<Foo> input = SettableFuture.create();
+ AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
+ throw new AssertionFailedError("Unexpeted call to apply.");
+ }
+ };
+ assertTrue(Futures.transformAsync(input, function).cancel(false));
+ assertTrue(input.isCancelled());
+ assertFalse(input.wasInterrupted());
+ }
+
+ public void testTransformAsync_interruptPropagatesToInput() throws Exception {
+ SettableFuture<Foo> input = SettableFuture.create();
+ AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
+ throw new AssertionFailedError("Unexpeted call to apply.");
+ }
+ };
+ assertTrue(Futures.transformAsync(input, function).cancel(true));
+ assertTrue(input.isCancelled());
+ assertTrue(input.wasInterrupted());
+ }
+
+ public void testTransformAsync_cancelPropagatesToAsyncOutput() throws Exception {
+ ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
+ final SettableFuture<Bar> secondary = SettableFuture.create();
+ AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
+ return secondary;
+ }
+ };
+ assertTrue(Futures.transformAsync(immediate, function).cancel(false));
+ assertTrue(secondary.isCancelled());
+ assertFalse(secondary.wasInterrupted());
+ }
+
+ public void testTransformAsync_interruptPropagatesToAsyncOutput()
+ throws Exception {
+ ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
+ final SettableFuture<Bar> secondary = SettableFuture.create();
+ AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
+ return secondary;
+ }
+ };
+ assertTrue(Futures.transformAsync(immediate, function).cancel(true));
+ assertTrue(secondary.isCancelled());
+ assertTrue(secondary.wasInterrupted());
+ }
+
+ /**
+ * Tests that the function is invoked only once, even if it throws an exception.
+ */
+ public void testTransformValueRemainsMemoized() throws Exception {
+ class Holder {
+
+ int value = 2;
+ }
+ final Holder holder = new Holder();
+
+ // This function adds the holder's value to the input value.
+ Function<Integer, Integer> adder = new Function<Integer, Integer>() {
+ @Override
+ public Integer apply(Integer from) {
+ return from + holder.value;
+ }
+ };
+
+ // Since holder.value is 2, applying 4 should yield 6.
+ assertEquals(6, adder.apply(4).intValue());
+
+ ListenableFuture<Integer> immediateFuture = Futures.immediateFuture(4);
+ Future<Integer> transformedFuture = Futures.transform(immediateFuture, adder);
+
+ // The composed future also yields 6.
+ assertEquals(6, transformedFuture.get().intValue());
+
+ // Repeated calls yield the same value even though the function's behavior
+ // changes
+ holder.value = 3;
+ assertEquals(6, transformedFuture.get().intValue());
+ assertEquals(7, adder.apply(4).intValue());
+
+ // Once more, with feeling.
+ holder.value = 4;
+ assertEquals(6, transformedFuture.get().intValue());
+ assertEquals(8, adder.apply(4).intValue());
+
+ // Memoized get also retains the value.
+ assertEquals(6, transformedFuture.get(1000, TimeUnit.SECONDS).intValue());
+
+ // Unsurprisingly, recomposing the future will return an updated value.
+ assertEquals(8, Futures.transform(immediateFuture, adder).get().intValue());
+
+ // Repeating, with the timeout version
+ assertEquals(8, Futures.transform(immediateFuture, adder).get(
+ 1000, TimeUnit.SECONDS).intValue());
+ }
+
+ static class MyError extends Error {
+
+ }
+
+ static class MyRuntimeException extends RuntimeException {
+
+ }
+
+ // TODO(cpovirk): top-level class?
+ static class ExecutorSpy implements Executor {
+
+ Executor delegate;
+ boolean wasExecuted;
+
+ public ExecutorSpy(Executor delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ delegate.execute(command);
+ wasExecuted = true;
+ }
+ }
+
+ public void testTransform_Executor() throws Exception {
+ Object value = new Object();
+ ExecutorSpy spy = new ExecutorSpy(directExecutor());
+
+ assertFalse(spy.wasExecuted);
+
+ ListenableFuture<Object> future = Futures.transform(
+ Futures.immediateFuture(value),
+ Functions.identity(), spy);
+
+ assertSame(value, future.get());
+ assertTrue(spy.wasExecuted);
+ }
+
+ private static class FunctionSpy<I, O> implements Function<I, O> {
+ private int applyCount;
+ private final Function<I, O> delegate;
+
+ public FunctionSpy(Function<I, O> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public O apply(I input) {
+ applyCount++;
+ return delegate.apply(input);
+ }
+
+ void verifyCallCount(int expected) {
+ assertThat(applyCount).isEqualTo(expected);
+ }
+ }
+
+ private static <I, O> FunctionSpy<I, O> spy(Function<I, O> delegate) {
+ return new FunctionSpy<I, O>(delegate);
+ }
+
+ private static <X extends Throwable, V> Function<X, V> unexpectedFunction() {
+ return new Function<X, V>() {
+ @Override
+ public V apply(X t) {
+ throw newAssertionError("Unexpected fallback", t);
+ }
+ };
+ }
+
+ private static class FutureFallbackSpy<V> implements FutureFallback<V> {
+
+ private int count;
+ private final FutureFallback<V> delegate;
+
+ public FutureFallbackSpy(FutureFallback<V> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public final ListenableFuture<V> create(Throwable t) throws Exception {
+ count++;
+ return delegate.create(t);
+ }
+
+ void verifyCallCount(int expected) {
+ assertThat(count).isEqualTo(expected);
+ }
+ }
+
+ private static <V> FutureFallbackSpy<V> spy(FutureFallback<V> delegate) {
+ return new FutureFallbackSpy<V>(delegate);
+ }
+
+ private static <V> FutureFallback<V> unexpectedFallback() {
+ return new FutureFallback<V>() {
+ @Override
+ public ListenableFuture<V> create(Throwable t) {
+ throw newAssertionError("Unexpected fallback", t);
+ }
+ };
+ }
+
+ private static class AsyncFunctionSpy<X extends Throwable, V> implements AsyncFunction<X, V> {
+ private int count;
+ private final AsyncFunction<X, V> delegate;
+
+ public AsyncFunctionSpy(AsyncFunction<X, V> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public final ListenableFuture<V> apply(X t) throws Exception {
+ count++;
+ return delegate.apply(t);
+ }
+
+ void verifyCallCount(int expected) {
+ assertThat(count).isEqualTo(expected);
+ }
+ }
+
+ private static <X extends Throwable, V> AsyncFunctionSpy<X, V> spy(AsyncFunction<X, V> delegate) {
+ return new AsyncFunctionSpy<X, V>(delegate);
+ }
+
+ private static <X extends Throwable, V> AsyncFunction<X, V> unexpectedAsyncFunction() {
+ return new AsyncFunction<X, V>() {
+ @Override
+ public ListenableFuture<V> apply(X t) {
+ throw newAssertionError("Unexpected fallback", t);
+ }
+ };
+ }
+
+ /** Alternative to AssertionError(String, Throwable), which doesn't exist in GWT 2.6.1. */
+ private static AssertionError newAssertionError(String message, Throwable cause) {
+ AssertionError e = new AssertionError(message);
+ e.initCause(cause);
+ return e;
+ }
+
+ public void testWithFallback_inputDoesNotRaiseException() throws Exception {
+ FutureFallback<Integer> fallback = unexpectedFallback();
+ ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
+ ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(originalFuture, fallback);
+ assertEquals(7, faultToleranteFuture.get().intValue());
+ }
+
+ public void testWithFallback_inputRaisesException() throws Exception {
+ final RuntimeException raisedException = new RuntimeException();
+ FutureFallbackSpy<Integer> fallback = spy(new FutureFallback<Integer>() {
+ @Override
+ public ListenableFuture<Integer> create(Throwable t) throws Exception {
+ assertThat(t).isSameAs(raisedException);
+ return Futures.immediateFuture(20);
+ }
+ });
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+ ListenableFuture<Integer> faultTolerantFuture = Futures.withFallback(failingFuture, fallback);
+ assertEquals(20, faultTolerantFuture.get().intValue());
+ fallback.verifyCallCount(1);
+ }
+
+ public void testWithFallback_fallbackGeneratesRuntimeException() throws Exception {
+ RuntimeException expectedException = new RuntimeException();
+ runExpectedExceptionFallbackTest(expectedException, false);
+ }
+
+ public void testWithFallback_fallbackGeneratesCheckedException() throws Exception {
+ Exception expectedException = new Exception() {
+ };
+ runExpectedExceptionFallbackTest(expectedException, false);
+ }
+
+ public void testWithFallback_fallbackGeneratesError() throws Exception {
+ final Error error = new Error("deliberate");
+ FutureFallback<Integer> fallback = new FutureFallback<Integer>() {
+ @Override
+ public ListenableFuture<Integer> create(Throwable t) throws Exception {
+ throw error;
+ }
+ };
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+ try {
+ Futures.withFallback(failingFuture, fallback).get();
+ fail("An Exception should have been thrown!");
+ } catch (ExecutionException expected) {
+ assertSame(error, expected.getCause());
+ }
+ }
+
+ public void testWithFallback_fallbackReturnsRuntimeException() throws Exception {
+ RuntimeException expectedException = new RuntimeException();
+ runExpectedExceptionFallbackTest(expectedException, true);
+ }
+
+ public void testWithFallback_fallbackReturnsCheckedException() throws Exception {
+ Exception expectedException = new Exception() {
+ };
+ runExpectedExceptionFallbackTest(expectedException, true);
+ }
+
+ private void runExpectedExceptionFallbackTest(
+ final Exception expectedException, final boolean wrapInFuture) throws Exception {
+ FutureFallbackSpy<Integer> fallback = spy(new FutureFallback<Integer>() {
+ @Override
+ public ListenableFuture<Integer> create(Throwable t) throws Exception {
+ if (!wrapInFuture) {
+ throw expectedException;
+ } else {
+ return Futures.immediateFailedFuture(expectedException);
+ }
+ }
+ });
+
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+
+ ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(failingFuture, fallback);
+ try {
+ faultToleranteFuture.get();
+ fail("An Exception should have been thrown!");
+ } catch (ExecutionException ee) {
+ assertSame(expectedException, ee.getCause());
+ }
+ fallback.verifyCallCount(1);
+ }
+
+ public void testWithFallback_fallbackNotReady() throws Exception {
+ ListenableFuture<Integer> primary = immediateFailedFuture(new Exception());
+ final SettableFuture<Integer> secondary = SettableFuture.create();
+ FutureFallback<Integer> fallback = new FutureFallback<Integer>() {
+ @Override
+ public ListenableFuture<Integer> create(Throwable t) {
+ return secondary;
+ }
+ };
+ ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
+ secondary.set(1);
+ assertEquals(1, (int) derived.get());
+ }
+
+ public void testWithFallback_resultInterruptedBeforeFallback() throws Exception {
+ SettableFuture<Integer> primary = SettableFuture.create();
+ FutureFallback<Integer> fallback = unexpectedFallback();
+ ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
+ derived.cancel(true);
+ assertTrue(primary.isCancelled());
+ assertTrue(primary.wasInterrupted());
+ }
+
+ public void testWithFallback_resultCancelledBeforeFallback() throws Exception {
+ SettableFuture<Integer> primary = SettableFuture.create();
+ FutureFallback<Integer> fallback = unexpectedFallback();
+ ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
+ derived.cancel(false);
+ assertTrue(primary.isCancelled());
+ assertFalse(primary.wasInterrupted());
+ }
+
+ public void testWithFallback_nullInsteadOfFuture() throws Exception {
+ ListenableFuture<Integer> inputFuture = immediateFailedFuture(new Exception());
+ ListenableFuture<?> chainedFuture =
+ Futures.withFallback(inputFuture, new FutureFallback<Integer>() {
+ @Override
+ public ListenableFuture<Integer> create(Throwable t) {
+ return null;
+ }
+ });
+ try {
+ chainedFuture.get();
+ fail();
+ } catch (ExecutionException expected) {
+ NullPointerException cause = (NullPointerException) expected.getCause();
+ assertThat(cause).hasMessage("FutureFallback.create returned null instead of a Future. "
+ + "Did you mean to return immediateFuture(null)?");
+ }
+ }
+
+ // catchingAsync tests cloned from the old withFallback tests:
+
+ public void testCatchingAsync_inputDoesNotRaiseException() throws Exception {
+ AsyncFunction<Throwable, Integer> fallback = unexpectedAsyncFunction();
+ ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
+ ListenableFuture<Integer> faultToleranteFuture =
+ Futures.catchingAsync(originalFuture, Throwable.class, fallback);
+ assertEquals(7, faultToleranteFuture.get().intValue());
+ }
+
+ public void testCatchingAsync_inputRaisesException() throws Exception {
+ final RuntimeException raisedException = new RuntimeException();
+ AsyncFunctionSpy<Throwable, Integer> fallback = spy(new AsyncFunction<Throwable, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(Throwable t) throws Exception {
+ assertThat(t).isSameAs(raisedException);
+ return Futures.immediateFuture(20);
+ }
+ });
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+ ListenableFuture<Integer> faultTolerantFuture =
+ Futures.catchingAsync(failingFuture, Throwable.class, fallback);
+ assertEquals(20, faultTolerantFuture.get().intValue());
+ fallback.verifyCallCount(1);
+ }
+
+ public void testCatchingAsync_fallbackGeneratesRuntimeException() throws Exception {
+ RuntimeException expectedException = new RuntimeException();
+ runExpectedExceptionCatchingAsyncTest(expectedException, false);
+ }
+
+ public void testCatchingAsync_fallbackGeneratesCheckedException() throws Exception {
+ Exception expectedException = new Exception() {
+ };
+ runExpectedExceptionCatchingAsyncTest(expectedException, false);
+ }
+
+ public void testCatchingAsync_fallbackGeneratesError() throws Exception {
+ final Error error = new Error("deliberate");
+ AsyncFunction<Throwable, Integer> fallback = new AsyncFunction<Throwable, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(Throwable t) throws Exception {
+ throw error;
+ }
+ };
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+ try {
+ Futures.catchingAsync(failingFuture, Throwable.class, fallback).get();
+ fail("An Exception should have been thrown!");
+ } catch (ExecutionException expected) {
+ assertSame(error, expected.getCause());
+ }
+ }
+
+ public void testCatchingAsync_fallbackReturnsRuntimeException() throws Exception {
+ RuntimeException expectedException = new RuntimeException();
+ runExpectedExceptionCatchingAsyncTest(expectedException, true);
+ }
+
+ public void testCatchingAsync_fallbackReturnsCheckedException() throws Exception {
+ Exception expectedException = new Exception() {
+ };
+ runExpectedExceptionCatchingAsyncTest(expectedException, true);
+ }
+
+ private void runExpectedExceptionCatchingAsyncTest(
+ final Exception expectedException, final boolean wrapInFuture) throws Exception {
+ AsyncFunctionSpy<Throwable, Integer> fallback = spy(new AsyncFunction<Throwable, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(Throwable t) throws Exception {
+ if (!wrapInFuture) {
+ throw expectedException;
+ } else {
+ return Futures.immediateFailedFuture(expectedException);
+ }
+ }
+ });
+
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+
+ ListenableFuture<Integer> faultToleranteFuture =
+ Futures.catchingAsync(failingFuture, Throwable.class, fallback);
+ try {
+ faultToleranteFuture.get();
+ fail("An Exception should have been thrown!");
+ } catch (ExecutionException ee) {
+ assertSame(expectedException, ee.getCause());
+ }
+ fallback.verifyCallCount(1);
+ }
+
+ public void testCatchingAsync_fallbackNotReady() throws Exception {
+ ListenableFuture<Integer> primary = immediateFailedFuture(new Exception());
+ final SettableFuture<Integer> secondary = SettableFuture.create();
+ AsyncFunction<Throwable, Integer> fallback = new AsyncFunction<Throwable, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(Throwable t) {
+ return secondary;
+ }
+ };
+ ListenableFuture<Integer> derived = Futures.catchingAsync(primary, Throwable.class, fallback);
+ secondary.set(1);
+ assertEquals(1, (int) derived.get());
+ }
+
+ public void testCatchingAsync_resultInterruptedBeforeFallback() throws Exception {
+ SettableFuture<Integer> primary = SettableFuture.create();
+ AsyncFunction<Throwable, Integer> fallback = unexpectedAsyncFunction();
+ ListenableFuture<Integer> derived = Futures.catchingAsync(primary, Throwable.class, fallback);
+ derived.cancel(true);
+ assertTrue(primary.isCancelled());
+ assertTrue(primary.wasInterrupted());
+ }
+
+ public void testCatchingAsync_resultCancelledBeforeFallback() throws Exception {
+ SettableFuture<Integer> primary = SettableFuture.create();
+ AsyncFunction<Throwable, Integer> fallback = unexpectedAsyncFunction();
+ ListenableFuture<Integer> derived = Futures.catchingAsync(primary, Throwable.class, fallback);
+ derived.cancel(false);
+ assertTrue(primary.isCancelled());
+ assertFalse(primary.wasInterrupted());
+ }
+
+ public void testCatchingAsync_nullInsteadOfFuture() throws Exception {
+ ListenableFuture<Integer> inputFuture = immediateFailedFuture(new Exception());
+ ListenableFuture<?> chainedFuture = Futures.catchingAsync(inputFuture, Throwable.class,
+ new AsyncFunction<Throwable, Integer>() {
+ @Override
+ @SuppressWarnings("AsyncFunctionReturnsNull")
+ public ListenableFuture<Integer> apply(Throwable t) {
+ return null;
+ }
+ });
+ try {
+ chainedFuture.get();
+ fail();
+ } catch (ExecutionException expected) {
+ NullPointerException cause = (NullPointerException) expected.getCause();
+ assertThat(cause).hasMessage("AsyncFunction.apply returned null instead of a Future. "
+ + "Did you mean to return immediateFuture(null)?");
+ }
+ }
+
+ // catching tests cloned from the old withFallback tests:
+
+ public void testCatching_inputDoesNotRaiseException() throws Exception {
+ Function<Throwable, Integer> fallback = unexpectedFunction();
+ ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
+ ListenableFuture<Integer> faultToleranteFuture =
+ Futures.catching(originalFuture, Throwable.class, fallback);
+ assertEquals(7, faultToleranteFuture.get().intValue());
+ }
+
+ public void testCatching_inputRaisesException() throws Exception {
+ final RuntimeException raisedException = new RuntimeException();
+ FunctionSpy<Throwable, Integer> fallback = spy(new Function<Throwable, Integer>() {
+ @Override
+ public Integer apply(Throwable t) {
+ assertThat(t).isSameAs(raisedException);
+ return 20;
+ }
+ });
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+ ListenableFuture<Integer> faultTolerantFuture =
+ Futures.catching(failingFuture, Throwable.class, fallback);
+ assertEquals(20, faultTolerantFuture.get().intValue());
+ fallback.verifyCallCount(1);
+ }
+
+ public void testCatching_fallbackGeneratesRuntimeException() throws Exception {
+ RuntimeException expectedException = new RuntimeException();
+ runExpectedExceptionCatchingTest(expectedException);
+ }
+
+ /*
+ * catching() uses a plain Function, so there's no
+ * testCatching_fallbackGeneratesCheckedException().
+ */
+
+ public void testCatching_fallbackGeneratesError() throws Exception {
+ final Error error = new Error("deliberate");
+ Function<Throwable, Integer> fallback = new Function<Throwable, Integer>() {
+ @Override
+ public Integer apply(Throwable t) {
+ throw error;
+ }
+ };
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+ try {
+ Futures.catching(failingFuture, Throwable.class, fallback).get();
+ fail("An Exception should have been thrown!");
+ } catch (ExecutionException expected) {
+ assertSame(error, expected.getCause());
+ }
+ }
+
+ /*
+ * catching() uses a plain Function, so there's no testCatching_fallbackReturnsRuntimeException()
+ * or testCatching_fallbackReturnsCheckedException().
+ */
+
+ private void runExpectedExceptionCatchingTest(final RuntimeException expectedException)
+ throws Exception {
+ FunctionSpy<Throwable, Integer> fallback = spy(new Function<Throwable, Integer>() {
+ @Override
+ public Integer apply(Throwable t) {
+ throw expectedException;
+ }
+ });
+
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+
+ ListenableFuture<Integer> faultToleranteFuture =
+ Futures.catching(failingFuture, Throwable.class, fallback);
+ try {
+ faultToleranteFuture.get();
+ fail("An Exception should have been thrown!");
+ } catch (ExecutionException ee) {
+ assertSame(expectedException, ee.getCause());
+ }
+ fallback.verifyCallCount(1);
+ }
+
+ // catching() uses a plain Function, so there's no testCatching_fallbackNotReady().
+
+ public void testCatching_resultInterruptedBeforeFallback() throws Exception {
+ SettableFuture<Integer> primary = SettableFuture.create();
+ Function<Throwable, Integer> fallback = unexpectedFunction();
+ ListenableFuture<Integer> derived = Futures.catching(primary, Throwable.class, fallback);
+ derived.cancel(true);
+ assertTrue(primary.isCancelled());
+ assertTrue(primary.wasInterrupted());
+ }
+
+ public void testCatching_resultCancelledBeforeFallback() throws Exception {
+ SettableFuture<Integer> primary = SettableFuture.create();
+ Function<Throwable, Integer> fallback = unexpectedFunction();
+ ListenableFuture<Integer> derived = Futures.catching(primary, Throwable.class, fallback);
+ derived.cancel(false);
+ assertTrue(primary.isCancelled());
+ assertFalse(primary.wasInterrupted());
+ }
+
+ // catching() uses a plain Function, so there's no testCatching_resultCancelledAfterFallback().
+
+ // catching() uses a plain Function, so there's no testCatching_nullInsteadOfFuture().
+
+ // Some tests of the exceptionType parameter:
+
+ public void testCatching_Throwable() throws Exception {
+ Function<Throwable, Integer> fallback = functionReturningOne();
+ ListenableFuture<Integer> originalFuture = immediateFailedFuture(new IOException());
+ ListenableFuture<Integer> faultTolerantFuture =
+ Futures.catching(originalFuture, Throwable.class, fallback);
+ assertEquals(1, (int) faultTolerantFuture.get());
+ }
+
+ public void testCatchingAsync_Throwable() throws Exception {
+ AsyncFunction<Throwable, Integer> fallback = asyncFunctionReturningOne();
+ ListenableFuture<Integer> originalFuture = immediateFailedFuture(new IOException());
+ ListenableFuture<Integer> faultTolerantFuture =
+ Futures.catchingAsync(originalFuture, Throwable.class, fallback);
+ assertEquals(1, (int) faultTolerantFuture.get());
+ }
+
+ private <X extends Throwable> Function<X, Integer> functionReturningOne() {
+ return new Function<X, Integer>() {
+ @Override
+ public Integer apply(X t) {
+ return 1;
+ }
+ };
+ }
+
+ private <X extends Throwable> AsyncFunction<X, Integer> asyncFunctionReturningOne() {
+ return new AsyncFunction<X, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(X t) {
+ return immediateFuture(1);
+ }
+ };
+ }
+
+ private static <I, O> AsyncFunction<I, O> constantAsyncFunction(
+ final ListenableFuture<O> output) {
+ return new AsyncFunction<I, O>() {
+ @Override
+ public ListenableFuture<O> apply(I input) {
+ return output;
+ }
+ };
+ }
+
+ public void testTransform_genericsWildcard_AsyncFunction() throws Exception {
+ ListenableFuture<?> nullFuture = immediateFuture(null);
+ ListenableFuture<?> chainedFuture =
+ Futures.transform(nullFuture, constantAsyncFunction(nullFuture));
+ assertNull(chainedFuture.get());
+ }
+
+ public void testTransform_genericsHierarchy_AsyncFunction() throws Exception {
+ ListenableFuture<FooChild> future = Futures.immediateFuture(null);
+ final BarChild barChild = new BarChild();
+ AsyncFunction<Foo, BarChild> function =
+ new AsyncFunction<Foo, BarChild>() {
+ @Override
+ public AbstractFuture<BarChild> apply(Foo unused) {
+ AbstractFuture<BarChild> future = new AbstractFuture<BarChild>() {
+ };
+ future.set(barChild);
+ return future;
+ }
+ };
+ Bar bar = Futures.transform(future, function).get();
+ assertSame(barChild, bar);
+ }
+
+ public void testTransform_asyncFunction_error() throws InterruptedException {
+ final Error error = new Error("deliberate");
+ AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(String input) {
+ throw error;
+ }
+ };
+ SettableFuture<String> inputFuture = SettableFuture.create();
+ ListenableFuture<Integer> outputFuture = Futures.transform(inputFuture, function);
+ inputFuture.set("value");
+ try {
+ outputFuture.get();
+ fail("should have thrown error");
+ } catch (ExecutionException e) {
+ assertSame(error, e.getCause());
+ }
+ }
+
+ public void testTransform_asyncFunction_nullInsteadOfFuture() throws Exception {
+ ListenableFuture<?> inputFuture = immediateFuture("a");
+ ListenableFuture<?> chainedFuture =
+ Futures.transform(inputFuture, constantAsyncFunction(null));
+ try {
+ chainedFuture.get();
+ fail();
+ } catch (ExecutionException expected) {
+ NullPointerException cause = (NullPointerException) expected.getCause();
+ assertThat(cause).hasMessage("AsyncFunction.apply returned null instead of a Future. "
+ + "Did you mean to return immediateFuture(null)?");
+ }
+ }
+
+ public void testTransformAsync_genericsWildcard_AsyncFunction() throws Exception {
+ ListenableFuture<?> nullFuture = immediateFuture(null);
+ ListenableFuture<?> chainedFuture =
+ Futures.transformAsync(nullFuture, constantAsyncFunction(nullFuture));
+ assertNull(chainedFuture.get());
+ }
+
+ public void testTransformAsync_genericsHierarchy_AsyncFunction() throws Exception {
+ ListenableFuture<FooChild> future = Futures.immediateFuture(null);
+ final BarChild barChild = new BarChild();
+ AsyncFunction<Foo, BarChild> function =
+ new AsyncFunction<Foo, BarChild>() {
+ @Override
+ public AbstractFuture<BarChild> apply(Foo unused) {
+ AbstractFuture<BarChild> future = new AbstractFuture<BarChild>() {
+ };
+ future.set(barChild);
+ return future;
+ }
+ };
+ Bar bar = Futures.transformAsync(future, function).get();
+ assertSame(barChild, bar);
+ }
+
+ public void testTransformAsync_asyncFunction_error() throws InterruptedException {
+ final Error error = new Error("deliberate");
+ AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(String input) {
+ throw error;
+ }
+ };
+ SettableFuture<String> inputFuture = SettableFuture.create();
+ ListenableFuture<Integer> outputFuture = Futures.transformAsync(inputFuture, function);
+ inputFuture.set("value");
+ try {
+ outputFuture.get();
+ fail("should have thrown error");
+ } catch (ExecutionException e) {
+ assertSame(error, e.getCause());
+ }
+ }
+
+ public void testTransformAsync_asyncFunction_nullInsteadOfFuture() throws Exception {
+ ListenableFuture<?> inputFuture = immediateFuture("a");
+ ListenableFuture<?> chainedFuture =
+ Futures.transformAsync(inputFuture, constantAsyncFunction(null));
+ try {
+ chainedFuture.get();
+ fail();
+ } catch (ExecutionException expected) {
+ NullPointerException cause = (NullPointerException) expected.getCause();
+ assertThat(cause).hasMessage("AsyncFunction.apply returned null instead of a Future. "
+ + "Did you mean to return immediateFuture(null)?");
+ }
+ }
+
+ public void testDereference_genericsWildcard() throws Exception {
+ ListenableFuture<?> inner = Futures.immediateFuture(null);
+ ListenableFuture<ListenableFuture<?>> outer =
+ Futures.<ListenableFuture<?>>immediateFuture(inner);
+ ListenableFuture<?> dereferenced = Futures.dereference(outer);
+ assertNull(dereferenced.get());
+ }
+
+ public void testDereference_genericsHierarchy() throws Exception {
+ FooChild fooChild = new FooChild();
+ ListenableFuture<FooChild> inner = Futures.immediateFuture(fooChild);
+ ListenableFuture<ListenableFuture<FooChild>> outer = Futures.immediateFuture(inner);
+ ListenableFuture<Foo> dereferenced = Futures.<Foo>dereference(outer);
+ assertSame(fooChild, dereferenced.get());
+ }
+
+ public void testDereference_resultCancelsOuter() throws Exception {
+ ListenableFuture<ListenableFuture<Foo>> outer = SettableFuture.create();
+ ListenableFuture<Foo> dereferenced = Futures.dereference(outer);
+ dereferenced.cancel(true);
+ assertTrue(outer.isCancelled());
+ }
+
+ public void testDereference_resultCancelsInner() throws Exception {
+ ListenableFuture<Foo> inner = SettableFuture.create();
+ ListenableFuture<ListenableFuture<Foo>> outer = Futures.immediateFuture(inner);
+ ListenableFuture<Foo> dereferenced = Futures.dereference(outer);
+ dereferenced.cancel(true);
+ assertTrue(inner.isCancelled());
+ }
+
+ public void testDereference_outerCancelsResult() throws Exception {
+ ListenableFuture<ListenableFuture<Foo>> outer = SettableFuture.create();
+ ListenableFuture<Foo> dereferenced = Futures.dereference(outer);
+ outer.cancel(true);
+ assertTrue(dereferenced.isCancelled());
+ }
+
+ public void testDereference_innerCancelsResult() throws Exception {
+ ListenableFuture<Foo> inner = SettableFuture.create();
+ ListenableFuture<ListenableFuture<Foo>> outer = Futures.immediateFuture(inner);
+ ListenableFuture<Foo> dereferenced = Futures.dereference(outer);
+ inner.cancel(true);
+ assertTrue(dereferenced.isCancelled());
+ }
+
+ /**
+ * Runnable which can be called a single time, and only after {@link #expectCall} is called.
+ */
+ // TODO(cpovirk): top-level class?
+ static class SingleCallListener implements Runnable {
+
+ private boolean expectCall = false;
+ private final CountDownLatch calledCountDown =
+ new CountDownLatch(1);
+
+ @Override
+ public void run() {
+ assertTrue("Listener called before it was expected", expectCall);
+ assertFalse("Listener called more than once", wasCalled());
+ calledCountDown.countDown();
+ }
+
+ public void expectCall() {
+ assertFalse("expectCall is already true", expectCall);
+ expectCall = true;
+ }
+
+ public boolean wasCalled() {
+ return calledCountDown.getCount() == 0;
+ }
+
+ public void waitForCall() throws InterruptedException {
+ assertTrue("expectCall is false", expectCall);
+ calledCountDown.await();
+ }
+ }
+
+ public void testAllAsList() throws Exception {
+ // Create input and output
+ SettableFuture<String> future1 = SettableFuture.create();
+ SettableFuture<String> future2 = SettableFuture.create();
+ SettableFuture<String> future3 = SettableFuture.create();
+ @SuppressWarnings("unchecked") // array is never modified
+ ListenableFuture<List<String>> compound =
+ Futures.allAsList(future1, future2, future3);
+
+ // Attach a listener
+ SingleCallListener listener = new SingleCallListener();
+ compound.addListener(listener, directExecutor());
+
+ // Satisfy each input and check the output
+ assertFalse(compound.isDone());
+ future1.set(DATA1);
+ assertFalse(compound.isDone());
+ future2.set(DATA2);
+ assertFalse(compound.isDone());
+ listener.expectCall();
+ future3.set(DATA3);
+ assertTrue(compound.isDone());
+ assertTrue(listener.wasCalled());
+
+ List<String> results = compound.get();
+ assertThat(results).containsExactly(DATA1, DATA2, DATA3).inOrder();
+ }
+
+ public void testAllAsList_emptyArray() throws Exception {
+ SingleCallListener listener = new SingleCallListener();
+ listener.expectCall();
+ @SuppressWarnings("unchecked") // array is never modified
+ ListenableFuture<List<String>> compound = Futures.allAsList();
+ compound.addListener(listener, directExecutor());
+ assertTrue(compound.isDone());
+ assertTrue(compound.get().isEmpty());
+ assertTrue(listener.wasCalled());
+ }
+
+ public void testAllAsList_failure() throws Exception {
+ SingleCallListener listener = new SingleCallListener();
+ SettableFuture<String> future1 = SettableFuture.create();
+ SettableFuture<String> future2 = SettableFuture.create();
+ @SuppressWarnings("unchecked") // array is never modified
+ ListenableFuture<List<String>> compound =
+ Futures.allAsList(future1, future2);
+ compound.addListener(listener, directExecutor());
+
+ listener.expectCall();
+ Throwable exception = new Throwable("failed1");
+ future1.setException(exception);
+ assertTrue(compound.isDone());
+ assertTrue(listener.wasCalled());
+ future2.set("result2");
+
+ try {
+ compound.get();
+ fail("Expected exception not thrown");
+ } catch (ExecutionException e) {
+ assertSame(exception, e.getCause());
+ }
+ }
+
+ public void testAllAsList_cancelled() throws Exception {
+ SingleCallListener listener = new SingleCallListener();
+ SettableFuture<String> future1 = SettableFuture.create();
+ SettableFuture<String> future2 = SettableFuture.create();
+ @SuppressWarnings("unchecked") // array is never modified
+ ListenableFuture<List<String>> compound =
+ Futures.allAsList(future1, future2);
+ compound.addListener(listener, directExecutor());
+
+ listener.expectCall();
+ future1.cancel(true);
+ assertTrue(compound.isDone());
+ assertTrue(listener.wasCalled());
+ future2.setException(new Throwable("failed2"));
+
+ try {
+ compound.get();
+ fail("Expected exception not thrown");
+ } catch (CancellationException e) {
+ // Expected
+ }
+ }
+
+ public void testAllAsList_resultCancelled() throws Exception {
+ SettableFuture<String> future1 = SettableFuture.create();
+ SettableFuture<String> future2 = SettableFuture.create();
+ @SuppressWarnings("unchecked") // array is never modified
+ ListenableFuture<List<String>> compound =
+ Futures.allAsList(future1, future2);
+
+ future2.set(DATA2);
+ assertFalse(compound.isDone());
+ assertTrue(compound.cancel(false));
+ assertTrue(compound.isCancelled());
+ assertTrue(future1.isCancelled());
+ assertFalse(future1.wasInterrupted());
+ }
+
+ public void testAllAsList_resultCancelledInterrupted_withSecondaryListFuture()
+ throws Exception {
+ SettableFuture<String> future1 = SettableFuture.create();
+ SettableFuture<String> future2 = SettableFuture.create();
+ ListenableFuture<List<String>> compound =
+ Futures.allAsList(future1, future2);
+ // There was a bug where the event listener for the combined future would
+ // result in the sub-futures being cancelled without being interrupted.
+ ListenableFuture<List<String>> otherCompound =
+ Futures.allAsList(future1, future2);
+
+ assertTrue(compound.cancel(true));
+ assertTrue(future1.isCancelled());
+ assertTrue(future1.wasInterrupted());
+ assertTrue(future2.isCancelled());
+ assertTrue(future2.wasInterrupted());
+ assertTrue(otherCompound.isCancelled());
+ }
+
+ public void testAllAsList_resultCancelled_withSecondaryListFuture()
+ throws Exception {
+ SettableFuture<String> future1 = SettableFuture.create();
+ SettableFuture<String> future2 = SettableFuture.create();
+ ListenableFuture<List<String>> compound =
+ Futures.allAsList(future1, future2);
+ // This next call is "unused," but it is an important part of the test. Don't remove it!
+ Futures.allAsList(future1, future2);
+
+ assertTrue(compound.cancel(false));
+ assertTrue(future1.isCancelled());
+ assertFalse(future1.wasInterrupted());
+ assertTrue(future2.isCancelled());
+ assertFalse(future2.wasInterrupted());
+ }
+
+ public void testAllAsList_resultInterrupted() throws Exception {
+ SettableFuture<String> future1 = SettableFuture.create();
+ SettableFuture<String> future2 = SettableFuture.create();
+ @SuppressWarnings("unchecked") // array is never modified
+ ListenableFuture<List<String>> compound =
+ Futures.allAsList(future1, future2);
+
+ future2.set(DATA2);
+ assertFalse(compound.isDone());
+ assertTrue(compound.cancel(true));
+ assertTrue(compound.isCancelled());
+ assertTrue(future1.isCancelled());
+ assertTrue(future1.wasInterrupted());
+ }
+
+ /**
+ * Test the case where the futures are fulfilled prior to constructing the ListFuture. There was
+ * a bug where the loop that connects a Listener to each of the futures would die on the last
+ * loop-check as done() on ListFuture nulled out the variable being looped over (the list of
+ * futures).
+ */
+ public void testAllAsList_doneFutures() throws Exception {
+ // Create input and output
+ SettableFuture<String> future1 = SettableFuture.create();
+ SettableFuture<String> future2 = SettableFuture.create();
+ SettableFuture<String> future3 = SettableFuture.create();
+
+ // Satisfy each input prior to creating compound and check the output
+ future1.set(DATA1);
+ future2.set(DATA2);
+ future3.set(DATA3);
+
+ @SuppressWarnings("unchecked") // array is never modified
+ ListenableFuture<List<String>> compound =
+ Futures.allAsList(future1, future2, future3);
+
+ // Attach a listener
+ SingleCallListener listener = new SingleCallListener();
+ listener.expectCall();
+ compound.addListener(listener, directExecutor());
+
+ assertTrue(compound.isDone());
+ assertTrue(listener.wasCalled());
+
+ List<String> results = compound.get();
+ assertThat(results).containsExactly(DATA1, DATA2, DATA3).inOrder();
+ }
+
+ /**
+ * A single non-error failure is not logged because it is reported via the output future.
+ */
+ @SuppressWarnings("unchecked")
+ public void testAllAsList_logging_exception() throws Exception {
+ try {
+ Futures.allAsList(immediateFailedFuture(new MyException())).get();
+ fail();
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isInstanceOf(MyException.class);
+ assertEquals(
+ "Nothing should be logged", 0, aggregateFutureLogHandler.getStoredLogRecords().size());
+ }
+ }
+
+ /**
+ * Ensure that errors are always logged.
+ */
+ @SuppressWarnings("unchecked")
+ public void testAllAsList_logging_error() throws Exception {
+ try {
+ Futures.allAsList(immediateFailedFuture(new MyError())).get();
+ fail();
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isInstanceOf(MyError.class);
+ List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+ assertThat(logged).hasSize(1); // errors are always logged
+ assertThat(logged.get(0).getThrown()).isInstanceOf(MyError.class);
+ }
+ }
+
+ /**
+ * All as list will log extra exceptions that have already occurred.
+ */
+ @SuppressWarnings("unchecked")
+ public void testAllAsList_logging_multipleExceptions_alreadyDone() throws Exception {
+ try {
+ Futures.allAsList(immediateFailedFuture(new MyException()),
+ immediateFailedFuture(new MyException())).get();
+ fail();
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isInstanceOf(MyException.class);
+ List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+ assertThat(logged).hasSize(1); // the second failure is logged
+ assertThat(logged.get(0).getThrown()).isInstanceOf(MyException.class);
+ }
+ }
+
+ /**
+ * All as list will log extra exceptions that occur later.
+ */
+ @SuppressWarnings("unchecked")
+ public void testAllAsList_logging_multipleExceptions_doneLater() throws Exception {
+ SettableFuture<Object> future1 = SettableFuture.create();
+ SettableFuture<Object> future2 = SettableFuture.create();
+ SettableFuture<Object> future3 = SettableFuture.create();
+ ListenableFuture<List<Object>> all = Futures.allAsList(future1, future2, future3);
+
+ future1.setException(new MyException());
+ future2.setException(new MyException());
+ future3.setException(new MyException());
+
+ try {
+ all.get();
+ } catch (ExecutionException e) {
+ List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+ assertThat(logged).hasSize(2); // failures after the first are logged
+ assertThat(logged.get(0).getThrown()).isInstanceOf(MyException.class);
+ assertThat(logged.get(1).getThrown()).isInstanceOf(MyException.class);
+ }
+ }
+
+ /**
+ * The same exception happening on multiple futures should not be logged.
+ */
+ @SuppressWarnings("unchecked")
+ public void testAllAsList_logging_same_exception() throws Exception {
+ try {
+ MyException sameInstance = new MyException();
+ Futures.allAsList(immediateFailedFuture(sameInstance),
+ immediateFailedFuture(sameInstance)).get();
+ fail();
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isInstanceOf(MyException.class);
+ assertEquals(
+ "Nothing should be logged", 0, aggregateFutureLogHandler.getStoredLogRecords().size());
+ }
+ }
+
+ public void testAllAsList_logging_seenExceptionUpdateRace() throws Exception {
+ final MyException sameInstance = new MyException();
+ SettableFuture<Object> firstFuture = SettableFuture.create();
+ final SettableFuture<Object> secondFuture = SettableFuture.create();
+ ListenableFuture<List<Object>> bulkFuture = allAsList(firstFuture, secondFuture);
+
+ bulkFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ /*
+ * firstFuture just completed, but AggregateFuture hasn't yet had time to record the
+ * exception in seenExceptions. When we complete secondFuture with the same exception,
+ * we want for AggregateFuture to still detect that it's been previously seen.
+ */
+ secondFuture.setException(sameInstance);
+ }
+ }, directExecutor());
+ firstFuture.setException(sameInstance);
+
+ try {
+ bulkFuture.get();
+ fail();
+ } catch (ExecutionException expected) {
+ assertThat(expected.getCause()).isInstanceOf(MyException.class);
+ assertThat(aggregateFutureLogHandler.getStoredLogRecords()).isEmpty();
+ }
+ }
+
+ public void testAllAsList_logging_seenExceptionUpdateCancelRace() throws Exception {
+ final MyException subsequentFailure = new MyException();
+ SettableFuture<Object> firstFuture = SettableFuture.create();
+ final SettableFuture<Object> secondFuture = SettableFuture.create();
+ ListenableFuture<List<Object>> bulkFuture = allAsList(firstFuture, secondFuture);
+
+ bulkFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ /*
+ * This is similar to the above test, but this time we're making sure that we recognize that
+ * the output Future is done early not because of an exception but because of a
+ * cancellation.
+ */
+ secondFuture.setException(subsequentFailure);
+ }
+ }, directExecutor());
+ firstFuture.cancel(false);
+
+ try {
+ bulkFuture.get();
+ fail();
+ } catch (CancellationException expected) {
+ assertThat(getOnlyElement(aggregateFutureLogHandler.getStoredLogRecords()).getThrown())
+ .isSameAs(subsequentFailure);
+ }
+ }
+
+ /**
+ * Different exceptions happening on multiple futures with the same cause should not be logged.
+ */
+ @SuppressWarnings("unchecked")
+ public void testAllAsList_logging_same_cause() throws Exception {
+ try {
+ MyException exception1 = new MyException();
+ MyException exception2 = new MyException();
+ MyException exception3 = new MyException();
+
+ MyException sameInstance = new MyException();
+ exception1.initCause(sameInstance);
+ exception2.initCause(sameInstance);
+ exception3.initCause(exception2);
+ Futures.allAsList(immediateFailedFuture(exception1),
+ immediateFailedFuture(exception3)).get();
+ fail();
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isInstanceOf(MyException.class);
+ assertEquals(
+ "Nothing should be logged", 0, aggregateFutureLogHandler.getStoredLogRecords().size());
+ }
+ }
+
+ private static String createCombinedResult(Integer i, Boolean b) {
+ return "-" + i + "-" + b;
+ }
+
+ /*
+ * TODO(cpovirk): maybe pass around TestFuture instances instead of
+ * ListenableFuture instances
+ */
+
+ /**
+ * Non-Error exceptions are never logged.
+ */
+ @SuppressWarnings("unchecked")
+ public void testSuccessfulAsList_logging_exception() throws Exception {
+ assertEquals(Lists.newArrayList((Object) null),
+ Futures.successfulAsList(
+ immediateFailedFuture(new MyException())).get());
+ assertEquals("Nothing should be logged", 0,
+ aggregateFutureLogHandler.getStoredLogRecords().size());
+
+ // Not even if there are a bunch of failures.
+ assertEquals(Lists.newArrayList(null, null, null),
+ Futures.successfulAsList(
+ immediateFailedFuture(new MyException()),
+ immediateFailedFuture(new MyException()),
+ immediateFailedFuture(new MyException())).get());
+ assertEquals("Nothing should be logged", 0,
+ aggregateFutureLogHandler.getStoredLogRecords().size());
+ }
+
+ /**
+ * Ensure that errors are always logged.
+ */
+ @SuppressWarnings("unchecked")
+ public void testSuccessfulAsList_logging_error() throws Exception {
+ assertEquals(Lists.newArrayList((Object) null),
+ Futures.successfulAsList(
+ immediateFailedFuture(new MyError())).get());
+ List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+ assertThat(logged).hasSize(1); // errors are always logged
+ assertThat(logged.get(0).getThrown()).isInstanceOf(MyError.class);
+ }
+
+ // Mostly an example of how it would look like to use a list of mixed types
+
+ static AssertionFailedError failureWithCause(Throwable cause, String message) {
+ AssertionFailedError failure = new AssertionFailedError(message);
+ failure.initCause(cause);
+ return failure;
+ }
+
+ /**
+ * A future that throws a runtime exception from get.
+ */
+ static class BuggyFuture extends AbstractFuture<String> {
+
+ @Override
+ public String get() {
+ throw new RuntimeException();
+ }
+
+ @Override
+ public boolean set(String v) {
+ return super.set(v);
+ }
+ }
+
+ // This test covers a bug where an Error thrown from a callback could cause the TimeoutFuture to
+ // never complete when timing out. Notably, nothing would get logged since the Error would get
+ // stuck in the ScheduledFuture inside of TimeoutFuture and nothing ever calls get on it.
+
+ // Simulate a timeout that fires before the call the SES.schedule returns but the future is
+ // already completed.
+}
diff --git a/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/TestPlatform.java b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/TestPlatform.java
new file mode 100644
index 0000000..54fa63e
--- /dev/null
+++ b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/TestPlatform.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.truth.Truth.assertThat;
+import static junit.framework.Assert.fail;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Methods factored out so that they can be emulated differently in GWT.
+ */
+ at GwtCompatible(emulated = true)
+final class TestPlatform {
+ static void verifyGetOnPendingFuture(Future<?> future) {
+ try {
+ future.get();
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalStateException.class);
+ assertThat(e).hasMessage("Cannot get() on a pending future.");
+ }
+ }
+
+ static void verifyTimedGetOnPendingFuture(Future<?> future) {
+ try {
+ future.get(0, TimeUnit.SECONDS);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalStateException.class);
+ assertThat(e).hasMessage("Cannot get() on a pending future.");
+ }
+ }
+
+ static void verifyThreadWasNotInterrupted() {
+ // There is no thread interruption in GWT, so there's nothing to do.
+ }
+
+ static void clearInterrupt() {
+ // There is no thread interruption in GWT, so there's nothing to do.
+ }
+
+ private TestPlatform() {}
+}
diff --git a/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/TrustedListenableFutureTaskTest.java b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/TrustedListenableFutureTaskTest.java
new file mode 100644
index 0000000..0510e13
--- /dev/null
+++ b/guava-gwt/test-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/TrustedListenableFutureTaskTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.util.concurrent.Callables.returning;
+import static com.google.common.util.concurrent.TestPlatform.verifyThreadWasNotInterrupted;
+
+import com.google.common.annotations.GwtCompatible;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Test case for {@link TrustedListenableFutureTask}.
+ */
+ at GwtCompatible(emulated = true)
+public class TrustedListenableFutureTaskTest extends TestCase {
+
+ public void testSuccessful() throws Exception {
+ TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(returning(2));
+ assertFalse(task.isDone());
+ task.run();
+ assertTrue(task.isDone());
+ assertFalse(task.isCancelled());
+ assertEquals(2, task.get().intValue());
+ }
+
+ public void testCancelled() throws Exception {
+ TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(returning(2));
+ assertFalse(task.isDone());
+ task.cancel(false);
+ assertTrue(task.isDone());
+ assertTrue(task.isCancelled());
+ assertFalse(task.wasInterrupted());
+ try {
+ task.get();
+ fail();
+ } catch (CancellationException expected) {
+ }
+ verifyThreadWasNotInterrupted();
+ }
+
+ public void testFailed() throws Exception {
+ final Exception e = new Exception();
+ TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(
+ new Callable<Integer>() {
+ @Override public Integer call() throws Exception {
+ throw e;
+ }
+ });
+ task.run();
+ assertTrue(task.isDone());
+ assertFalse(task.isCancelled());
+ try {
+ task.get();
+ fail();
+ } catch (ExecutionException executionException) {
+ assertEquals(e, executionException.getCause());
+ }
+ }
+}
+
diff --git a/guava-gwt/test/com/google/common/base/StopwatchTest_gwt.java b/guava-gwt/test/com/google/common/base/StopwatchTest_gwt.java
index 8372cbf..af16639 100644
--- a/guava-gwt/test/com/google/common/base/StopwatchTest_gwt.java
+++ b/guava-gwt/test/com/google/common/base/StopwatchTest_gwt.java
@@ -28,26 +28,6 @@ public void testCreateUnstarted() throws Exception {
testCase.testCreateUnstarted();
}
-public void testElapsedMillis() throws Exception {
- com.google.common.base.StopwatchTest testCase = new com.google.common.base.StopwatchTest();
- testCase.testElapsedMillis();
-}
-
-public void testElapsedMillis_multipleSegments() throws Exception {
- com.google.common.base.StopwatchTest testCase = new com.google.common.base.StopwatchTest();
- testCase.testElapsedMillis_multipleSegments();
-}
-
-public void testElapsedMillis_notRunning() throws Exception {
- com.google.common.base.StopwatchTest testCase = new com.google.common.base.StopwatchTest();
- testCase.testElapsedMillis_notRunning();
-}
-
-public void testElapsedMillis_whileRunning() throws Exception {
- com.google.common.base.StopwatchTest testCase = new com.google.common.base.StopwatchTest();
- testCase.testElapsedMillis_whileRunning();
-}
-
public void testElapsed_micros() throws Exception {
com.google.common.base.StopwatchTest testCase = new com.google.common.base.StopwatchTest();
testCase.testElapsed_micros();
diff --git a/guava-gwt/test/com/google/common/base/Utf8Test_gwt.java b/guava-gwt/test/com/google/common/base/Utf8Test_gwt.java
index 96c65d4..f844ec5 100644
--- a/guava-gwt/test/com/google/common/base/Utf8Test_gwt.java
+++ b/guava-gwt/test/com/google/common/base/Utf8Test_gwt.java
@@ -28,6 +28,11 @@ public void testEncodedLength_validStrings() throws Exception {
testCase.testEncodedLength_validStrings();
}
+public void testEncodedLength_validStrings2() throws Exception {
+ com.google.common.base.Utf8Test testCase = new com.google.common.base.Utf8Test();
+ testCase.testEncodedLength_validStrings2();
+}
+
public void testIsWellFormed_4BytesSamples() throws Exception {
com.google.common.base.Utf8Test testCase = new com.google.common.base.Utf8Test();
testCase.testIsWellFormed_4BytesSamples();
diff --git a/guava-gwt/test/com/google/common/base/testModule.gwt.xml b/guava-gwt/test/com/google/common/base/testModule.gwt.xml
index 6dcc754..afefbb8 100644
--- a/guava-gwt/test/com/google/common/base/testModule.gwt.xml
+++ b/guava-gwt/test/com/google/common/base/testModule.gwt.xml
@@ -2,10 +2,10 @@
<module>
<inherits name="com.google.gwt.user.User"/>
<inherits name="com.google.gwt.junit.JUnit"/>
+ <inherits name="com.google.common.annotations.Annotations"/>
<inherits name="com.google.common.base.Base"/>
<inherits name="com.google.common.collect.Collect"/>
<inherits name="com.google.common.testing.Testing"/>
- <inherits name="com.google.common.annotations.Annotations"/>
<inherits name="com.google.common.truth.Truth"/>
<entry-point class="com.google.common.base.TestModuleEntryPoint"/>
diff --git a/guava-gwt/test/com/google/common/cache/CacheBuilderTest_gwt.java b/guava-gwt/test/com/google/common/cache/CacheBuilderTest_gwt.java
index 9aaf37e..7aa24af 100644
--- a/guava-gwt/test/com/google/common/cache/CacheBuilderTest_gwt.java
+++ b/guava-gwt/test/com/google/common/cache/CacheBuilderTest_gwt.java
@@ -107,4 +107,9 @@ public void testTimeToLive_small() throws Exception {
com.google.common.cache.CacheBuilderTest testCase = new com.google.common.cache.CacheBuilderTest();
testCase.testTimeToLive_small();
}
+
+public void testValuesIsNotASet() throws Exception {
+ com.google.common.cache.CacheBuilderTest testCase = new com.google.common.cache.CacheBuilderTest();
+ testCase.testValuesIsNotASet();
+}
}
diff --git a/guava-gwt/test/com/google/common/collect/ComparisonChainTest_gwt.java b/guava-gwt/test/com/google/common/collect/ComparisonChainTest_gwt.java
index 9582390..795d238 100644
--- a/guava-gwt/test/com/google/common/collect/ComparisonChainTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/ComparisonChainTest_gwt.java
@@ -18,6 +18,11 @@ public class ComparisonChainTest_gwt extends com.google.gwt.junit.client.GWTTest
@Override public String getModuleName() {
return "com.google.common.collect.testModule";
}
+public void testCompareBooleans() throws Exception {
+ com.google.common.collect.ComparisonChainTest testCase = new com.google.common.collect.ComparisonChainTest();
+ testCase.testCompareBooleans();
+}
+
public void testCompareFalseFirst() throws Exception {
com.google.common.collect.ComparisonChainTest testCase = new com.google.common.collect.ComparisonChainTest();
testCase.testCompareFalseFirst();
diff --git a/guava-gwt/test/com/google/common/collect/EvictingQueueTest_gwt.java b/guava-gwt/test/com/google/common/collect/EvictingQueueTest_gwt.java
new file mode 100644
index 0000000..ad403c8
--- /dev/null
+++ b/guava-gwt/test/com/google/common/collect/EvictingQueueTest_gwt.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.common.collect;
+public class EvictingQueueTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+ at Override public String getModuleName() {
+ return "com.google.common.collect.testModule";
+}
+public void testAddAll() throws Exception {
+ com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+ testCase.testAddAll();
+}
+
+public void testCreateWithNegativeSize() throws Exception {
+ com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+ testCase.testCreateWithNegativeSize();
+}
+
+public void testCreateWithZeroSize() throws Exception {
+ com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+ testCase.testCreateWithZeroSize();
+}
+
+public void testEvictingAfterOne() throws Exception {
+ com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+ testCase.testEvictingAfterOne();
+}
+
+public void testEvictingAfterThree() throws Exception {
+ com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+ testCase.testEvictingAfterThree();
+}
+
+public void testRemainingCapacity_maxSize0() throws Exception {
+ com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+ testCase.testRemainingCapacity_maxSize0();
+}
+
+public void testRemainingCapacity_maxSize1() throws Exception {
+ com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+ testCase.testRemainingCapacity_maxSize1();
+}
+
+public void testRemainingCapacity_maxSize3() throws Exception {
+ com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+ testCase.testRemainingCapacity_maxSize3();
+}
+
+public void testSerialization() throws Exception {
+ com.google.common.collect.EvictingQueueTest testCase = new com.google.common.collect.EvictingQueueTest();
+ testCase.testSerialization();
+}
+}
diff --git a/guava-gwt/test/com/google/common/collect/HashBiMapTest_gwt.java b/guava-gwt/test/com/google/common/collect/HashBiMapTest_gwt.java
index a5b2aba..38ca4f3 100644
--- a/guava-gwt/test/com/google/common/collect/HashBiMapTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/HashBiMapTest_gwt.java
@@ -28,6 +28,11 @@ public void testBiMapEntrySetIteratorRemove() throws Exception {
testCase.testBiMapEntrySetIteratorRemove();
}
+public void testInverseEntrySetValue() throws Exception {
+ com.google.common.collect.HashBiMapTest testCase = new com.google.common.collect.HashBiMapTest();
+ testCase.testInverseEntrySetValue();
+}
+
public void testMapConstructor() throws Exception {
com.google.common.collect.HashBiMapTest testCase = new com.google.common.collect.HashBiMapTest();
testCase.testMapConstructor();
diff --git a/guava-gwt/test/com/google/common/collect/ImmutableBiMapTest_gwt.java b/guava-gwt/test/com/google/common/collect/ImmutableBiMapTest_gwt.java
index c215361..edb69b6 100644
--- a/guava-gwt/test/com/google/common/collect/ImmutableBiMapTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/ImmutableBiMapTest_gwt.java
@@ -78,6 +78,26 @@ public void testBuilderReuse__CreationTests() throws Exception {
testCase.testBuilderReuse();
}
+public void testBuilder_orderEntriesByValue__CreationTests() throws Exception {
+ com.google.common.collect.ImmutableBiMapTest.CreationTests testCase = new com.google.common.collect.ImmutableBiMapTest.CreationTests();
+ testCase.testBuilder_orderEntriesByValue();
+}
+
+public void testBuilder_orderEntriesByValueAfterExactSizeBuild__CreationTests() throws Exception {
+ com.google.common.collect.ImmutableBiMapTest.CreationTests testCase = new com.google.common.collect.ImmutableBiMapTest.CreationTests();
+ testCase.testBuilder_orderEntriesByValueAfterExactSizeBuild();
+}
+
+public void testBuilder_orderEntriesByValue_usedTwiceFails__CreationTests() throws Exception {
+ com.google.common.collect.ImmutableBiMapTest.CreationTests testCase = new com.google.common.collect.ImmutableBiMapTest.CreationTests();
+ testCase.testBuilder_orderEntriesByValue_usedTwiceFails();
+}
+
+public void testBuilder_withImmutableEntry__CreationTests() throws Exception {
+ com.google.common.collect.ImmutableBiMapTest.CreationTests testCase = new com.google.common.collect.ImmutableBiMapTest.CreationTests();
+ testCase.testBuilder_withImmutableEntry();
+}
+
public void testCopyOf__CreationTests() throws Exception {
com.google.common.collect.ImmutableBiMapTest.CreationTests testCase = new com.google.common.collect.ImmutableBiMapTest.CreationTests();
testCase.testCopyOf();
diff --git a/guava-gwt/test/com/google/common/collect/ImmutableMapTest_gwt.java b/guava-gwt/test/com/google/common/collect/ImmutableMapTest_gwt.java
index 8103049..6f17c67 100644
--- a/guava-gwt/test/com/google/common/collect/ImmutableMapTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/ImmutableMapTest_gwt.java
@@ -108,6 +108,21 @@ public void testBuilderReuse__CreationTests() throws Exception {
testCase.testBuilderReuse();
}
+public void testBuilder_orderEntriesByValue__CreationTests() throws Exception {
+ com.google.common.collect.ImmutableMapTest.CreationTests testCase = new com.google.common.collect.ImmutableMapTest.CreationTests();
+ testCase.testBuilder_orderEntriesByValue();
+}
+
+public void testBuilder_orderEntriesByValueAfterExactSizeBuild__CreationTests() throws Exception {
+ com.google.common.collect.ImmutableMapTest.CreationTests testCase = new com.google.common.collect.ImmutableMapTest.CreationTests();
+ testCase.testBuilder_orderEntriesByValueAfterExactSizeBuild();
+}
+
+public void testBuilder_orderEntriesByValue_usedTwiceFails__CreationTests() throws Exception {
+ com.google.common.collect.ImmutableMapTest.CreationTests testCase = new com.google.common.collect.ImmutableMapTest.CreationTests();
+ testCase.testBuilder_orderEntriesByValue_usedTwiceFails();
+}
+
public void testBuilder_withImmutableEntry__CreationTests() throws Exception {
com.google.common.collect.ImmutableMapTest.CreationTests testCase = new com.google.common.collect.ImmutableMapTest.CreationTests();
testCase.testBuilder_withImmutableEntry();
diff --git a/guava-gwt/test/com/google/common/collect/ImmutableSortedMapTest_gwt.java b/guava-gwt/test/com/google/common/collect/ImmutableSortedMapTest_gwt.java
index 49cbaea..cf99a03 100644
--- a/guava-gwt/test/com/google/common/collect/ImmutableSortedMapTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/ImmutableSortedMapTest_gwt.java
@@ -128,6 +128,11 @@ public void testBuilderReverseOrder__CreationTests() throws Exception {
testCase.testBuilderReverseOrder();
}
+public void testBuilder_orderEntriesByValueFails__CreationTests() throws Exception {
+ com.google.common.collect.ImmutableSortedMapTest.CreationTests testCase = new com.google.common.collect.ImmutableSortedMapTest.CreationTests();
+ testCase.testBuilder_orderEntriesByValueFails();
+}
+
public void testBuilder_withImmutableEntry__CreationTests() throws Exception {
com.google.common.collect.ImmutableSortedMapTest.CreationTests testCase = new com.google.common.collect.ImmutableSortedMapTest.CreationTests();
testCase.testBuilder_withImmutableEntry();
diff --git a/guava-gwt/test/com/google/common/collect/IteratorsTest_gwt.java b/guava-gwt/test/com/google/common/collect/IteratorsTest_gwt.java
index 9089b3e..725b278 100644
--- a/guava-gwt/test/com/google/common/collect/IteratorsTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/IteratorsTest_gwt.java
@@ -123,6 +123,11 @@ public void testCycleRemoveAfterHasNext() throws Exception {
testCase.testCycleRemoveAfterHasNext();
}
+public void testCycleRemoveAfterHasNextExtraPicky() throws Exception {
+ com.google.common.collect.IteratorsTest testCase = new com.google.common.collect.IteratorsTest();
+ testCase.testCycleRemoveAfterHasNextExtraPicky();
+}
+
public void testCycleRemoveSameElementTwice() throws Exception {
com.google.common.collect.IteratorsTest testCase = new com.google.common.collect.IteratorsTest();
testCase.testCycleRemoveSameElementTwice();
diff --git a/guava-gwt/test/com/google/common/collect/OrderingTest_gwt.java b/guava-gwt/test/com/google/common/collect/OrderingTest_gwt.java
index e648992..576fc46 100644
--- a/guava-gwt/test/com/google/common/collect/OrderingTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/OrderingTest_gwt.java
@@ -43,6 +43,11 @@ public void testCombinationsExhaustively_startingFromNatural() throws Exception
testCase.testCombinationsExhaustively_startingFromNatural();
}
+public void testComplicatedOrderingExample() throws Exception {
+ com.google.common.collect.OrderingTest testCase = new com.google.common.collect.OrderingTest();
+ testCase.testComplicatedOrderingExample();
+}
+
public void testCompound_instance() throws Exception {
com.google.common.collect.OrderingTest testCase = new com.google.common.collect.OrderingTest();
testCase.testCompound_instance();
diff --git a/guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java b/guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java
index 90022e9..ef380ef 100644
--- a/guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java
+++ b/guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java
@@ -18,6 +18,36 @@ public class HelpersTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
@Override public String getModuleName() {
return "com.google.common.collect.testing.testModule";
}
+public void testAssertContains() throws Exception {
+ com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
+ testCase.testAssertContains();
+}
+
+public void testAssertContainsAllOf() throws Exception {
+ com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
+ testCase.testAssertContainsAllOf();
+}
+
+public void testAssertContentsInOrder() throws Exception {
+ com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
+ testCase.testAssertContentsInOrder();
+}
+
+public void testAssertEqualInOrder() throws Exception {
+ com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
+ testCase.testAssertEqualInOrder();
+}
+
+public void testIsEmpty_iterable() throws Exception {
+ com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
+ testCase.testIsEmpty_iterable();
+}
+
+public void testIsEmpty_map() throws Exception {
+ com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
+ testCase.testIsEmpty_map();
+}
+
public void testNullsBeforeB() throws Exception {
com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
testCase.testNullsBeforeB();
diff --git a/guava-gwt/test/com/google/common/collect/testing/Testing.gwt.xml b/guava-gwt/test/com/google/common/collect/testing/Testing.gwt.xml
index 184e212..6c1afa1 100644
--- a/guava-gwt/test/com/google/common/collect/testing/Testing.gwt.xml
+++ b/guava-gwt/test/com/google/common/collect/testing/Testing.gwt.xml
@@ -19,9 +19,9 @@
<inherits name="com.google.common.annotations.Annotations"/>
<inherits name="com.google.common.testing.Testing"/>
-
- <inherits name="com.google.common.truth.Truth"/>
+ <inherits name="java.lang.Lang"/>
+
<inherits name="com.google.gwt.core.Core"/>
</module>
diff --git a/guava-gwt/test/com/google/common/collect/testing/google/Google.gwt.xml b/guava-gwt/test/com/google/common/collect/testing/google/Google.gwt.xml
index 6f4c380..304b05a 100644
--- a/guava-gwt/test/com/google/common/collect/testing/google/Google.gwt.xml
+++ b/guava-gwt/test/com/google/common/collect/testing/google/Google.gwt.xml
@@ -28,6 +28,5 @@
<inherits name="com.google.common.collect.testing.Testing"/>
<inherits name="com.google.common.primitives.Primitives"/>
<inherits name="com.google.common.testing.Testing"/>
-<inherits name="com.google.common.truth.Truth"/>
<inherits name="com.google.gwt.core.Core"/>
</module>
diff --git a/guava-gwt/test/com/google/common/io/BaseEncodingTest_gwt.java b/guava-gwt/test/com/google/common/io/BaseEncodingTest_gwt.java
index c8f61ae..37deb9d 100644
--- a/guava-gwt/test/com/google/common/io/BaseEncodingTest_gwt.java
+++ b/guava-gwt/test/com/google/common/io/BaseEncodingTest_gwt.java
@@ -28,6 +28,16 @@ public void testBase16() throws Exception {
testCase.testBase16();
}
+public void testBase16InvalidDecodings() throws Exception {
+ com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
+ testCase.testBase16InvalidDecodings();
+}
+
+public void testBase16Offset() throws Exception {
+ com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
+ testCase.testBase16Offset();
+}
+
public void testBase16UpperCaseIsNoOp() throws Exception {
com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
testCase.testBase16UpperCaseIsNoOp();
@@ -73,6 +83,11 @@ public void testBase32LenientPadding() throws Exception {
testCase.testBase32LenientPadding();
}
+public void testBase32Offset() throws Exception {
+ com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
+ testCase.testBase32Offset();
+}
+
public void testBase32UpperCaseIsNoOp() throws Exception {
com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
testCase.testBase32UpperCaseIsNoOp();
@@ -108,6 +123,11 @@ public void testBase64LenientPadding() throws Exception {
testCase.testBase64LenientPadding();
}
+public void testBase64Offset() throws Exception {
+ com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
+ testCase.testBase64Offset();
+}
+
public void testBase64OmitPadding() throws Exception {
com.google.common.io.BaseEncodingTest testCase = new com.google.common.io.BaseEncodingTest();
testCase.testBase64OmitPadding();
diff --git a/guava-gwt/test/com/google/common/io/testModule.gwt.xml b/guava-gwt/test/com/google/common/io/testModule.gwt.xml
index 088e68d..9af7456 100644
--- a/guava-gwt/test/com/google/common/io/testModule.gwt.xml
+++ b/guava-gwt/test/com/google/common/io/testModule.gwt.xml
@@ -7,6 +7,7 @@
<inherits name="com.google.common.collect.Collect"/>
<inherits name="com.google.common.io.Io"/>
<inherits name="com.google.common.math.Math"/>
+ <inherits name="com.google.common.truth.Truth"/>
<entry-point class="com.google.common.io.TestModuleEntryPoint"/>
<source path=""/>
diff --git a/guava-gwt/test/com/google/common/math/testModule.gwt.xml b/guava-gwt/test/com/google/common/math/testModule.gwt.xml
index 91255e3..afbc79c 100644
--- a/guava-gwt/test/com/google/common/math/testModule.gwt.xml
+++ b/guava-gwt/test/com/google/common/math/testModule.gwt.xml
@@ -11,7 +11,7 @@
<entry-point class="com.google.common.math.TestModuleEntryPoint"/>
<source path=""/>
-
+
<super-source path="super"/>
</module>
diff --git a/guava-gwt/test/com/google/common/net/testModule.gwt.xml b/guava-gwt/test/com/google/common/net/testModule.gwt.xml
index bc826a6..5e49aa2 100644
--- a/guava-gwt/test/com/google/common/net/testModule.gwt.xml
+++ b/guava-gwt/test/com/google/common/net/testModule.gwt.xml
@@ -13,7 +13,7 @@
<entry-point class="com.google.common.net.TestModuleEntryPoint"/>
<source path=""/>
-
+
<super-source path="super"/>
</module>
diff --git a/guava-gwt/test/com/google/common/primitives/IntsTest_gwt.java b/guava-gwt/test/com/google/common/primitives/IntsTest_gwt.java
index 7021487..25b1e28 100644
--- a/guava-gwt/test/com/google/common/primitives/IntsTest_gwt.java
+++ b/guava-gwt/test/com/google/common/primitives/IntsTest_gwt.java
@@ -167,4 +167,19 @@ public void testTryParse() throws Exception {
com.google.common.primitives.IntsTest testCase = new com.google.common.primitives.IntsTest();
testCase.testTryParse();
}
+
+public void testTryParse_radix() throws Exception {
+ com.google.common.primitives.IntsTest testCase = new com.google.common.primitives.IntsTest();
+ testCase.testTryParse_radix();
+}
+
+public void testTryParse_radixTooBig() throws Exception {
+ com.google.common.primitives.IntsTest testCase = new com.google.common.primitives.IntsTest();
+ testCase.testTryParse_radixTooBig();
+}
+
+public void testTryParse_radixTooSmall() throws Exception {
+ com.google.common.primitives.IntsTest testCase = new com.google.common.primitives.IntsTest();
+ testCase.testTryParse_radixTooSmall();
+}
}
diff --git a/guava-gwt/test/com/google/common/primitives/LongsTest_gwt.java b/guava-gwt/test/com/google/common/primitives/LongsTest_gwt.java
index b865b9e..928cead 100644
--- a/guava-gwt/test/com/google/common/primitives/LongsTest_gwt.java
+++ b/guava-gwt/test/com/google/common/primitives/LongsTest_gwt.java
@@ -73,6 +73,11 @@ public void testFromByteArray() throws Exception {
testCase.testFromByteArray();
}
+public void testFromByteArrayFails() throws Exception {
+ com.google.common.primitives.LongsTest testCase = new com.google.common.primitives.LongsTest();
+ testCase.testFromByteArrayFails();
+}
+
public void testFromBytes() throws Exception {
com.google.common.primitives.LongsTest testCase = new com.google.common.primitives.LongsTest();
testCase.testFromBytes();
@@ -172,4 +177,19 @@ public void testTryParse() throws Exception {
com.google.common.primitives.LongsTest testCase = new com.google.common.primitives.LongsTest();
testCase.testTryParse();
}
+
+public void testTryParse_radix() throws Exception {
+ com.google.common.primitives.LongsTest testCase = new com.google.common.primitives.LongsTest();
+ testCase.testTryParse_radix();
+}
+
+public void testTryParse_radixTooBig() throws Exception {
+ com.google.common.primitives.LongsTest testCase = new com.google.common.primitives.LongsTest();
+ testCase.testTryParse_radixTooBig();
+}
+
+public void testTryParse_radixTooSmall() throws Exception {
+ com.google.common.primitives.LongsTest testCase = new com.google.common.primitives.LongsTest();
+ testCase.testTryParse_radixTooSmall();
+}
}
diff --git a/guava-gwt/test/com/google/common/primitives/UnsignedIntsTest_gwt.java b/guava-gwt/test/com/google/common/primitives/UnsignedIntsTest_gwt.java
index 394001e..818b46e 100644
--- a/guava-gwt/test/com/google/common/primitives/UnsignedIntsTest_gwt.java
+++ b/guava-gwt/test/com/google/common/primitives/UnsignedIntsTest_gwt.java
@@ -73,6 +73,11 @@ public void testParseInt() throws Exception {
testCase.testParseInt();
}
+public void testParseIntFail() throws Exception {
+ com.google.common.primitives.UnsignedIntsTest testCase = new com.google.common.primitives.UnsignedIntsTest();
+ testCase.testParseIntFail();
+}
+
public void testParseIntThrowsExceptionForInvalidRadix() throws Exception {
com.google.common.primitives.UnsignedIntsTest testCase = new com.google.common.primitives.UnsignedIntsTest();
testCase.testParseIntThrowsExceptionForInvalidRadix();
@@ -83,6 +88,11 @@ public void testParseIntWithRadix() throws Exception {
testCase.testParseIntWithRadix();
}
+public void testParseIntWithRadixLimits() throws Exception {
+ com.google.common.primitives.UnsignedIntsTest testCase = new com.google.common.primitives.UnsignedIntsTest();
+ testCase.testParseIntWithRadixLimits();
+}
+
public void testRemainder() throws Exception {
com.google.common.primitives.UnsignedIntsTest testCase = new com.google.common.primitives.UnsignedIntsTest();
testCase.testRemainder();
diff --git a/guava-gwt/test/com/google/common/primitives/UnsignedLongsTest_gwt.java b/guava-gwt/test/com/google/common/primitives/UnsignedLongsTest_gwt.java
index 13374a5..0b4aca5 100644
--- a/guava-gwt/test/com/google/common/primitives/UnsignedLongsTest_gwt.java
+++ b/guava-gwt/test/com/google/common/primitives/UnsignedLongsTest_gwt.java
@@ -73,6 +73,11 @@ public void testParseLong() throws Exception {
testCase.testParseLong();
}
+public void testParseLongFails() throws Exception {
+ com.google.common.primitives.UnsignedLongsTest testCase = new com.google.common.primitives.UnsignedLongsTest();
+ testCase.testParseLongFails();
+}
+
public void testParseLongThrowsExceptionForInvalidRadix() throws Exception {
com.google.common.primitives.UnsignedLongsTest testCase = new com.google.common.primitives.UnsignedLongsTest();
testCase.testParseLongThrowsExceptionForInvalidRadix();
@@ -83,6 +88,11 @@ public void testParseLongWithRadix() throws Exception {
testCase.testParseLongWithRadix();
}
+public void testParseLongWithRadixLimits() throws Exception {
+ com.google.common.primitives.UnsignedLongsTest testCase = new com.google.common.primitives.UnsignedLongsTest();
+ testCase.testParseLongWithRadixLimits();
+}
+
public void testRemainder() throws Exception {
com.google.common.primitives.UnsignedLongsTest testCase = new com.google.common.primitives.UnsignedLongsTest();
testCase.testRemainder();
diff --git a/guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java b/guava-gwt/test/com/google/common/util/concurrent/CallablesTest_gwt.java
similarity index 63%
copy from guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java
copy to guava-gwt/test/com/google/common/util/concurrent/CallablesTest_gwt.java
index 90022e9..f055cf3 100644
--- a/guava-gwt/test/com/google/common/collect/testing/HelpersTest_gwt.java
+++ b/guava-gwt/test/com/google/common/util/concurrent/CallablesTest_gwt.java
@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.google.common.collect.testing;
-public class HelpersTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+package com.google.common.util.concurrent;
+public class CallablesTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
@Override public String getModuleName() {
- return "com.google.common.collect.testing.testModule";
+ return "com.google.common.util.concurrent.testModule";
}
-public void testNullsBeforeB() throws Exception {
- com.google.common.collect.testing.HelpersTest testCase = new com.google.common.collect.testing.HelpersTest();
- testCase.testNullsBeforeB();
+public void testReturning() throws Exception {
+ com.google.common.util.concurrent.CallablesTest testCase = new com.google.common.util.concurrent.CallablesTest();
+ testCase.testReturning();
}
}
diff --git a/guava-gwt/test/com/google/common/util/concurrent/FutureCallbackTest_gwt.java b/guava-gwt/test/com/google/common/util/concurrent/FutureCallbackTest_gwt.java
new file mode 100644
index 0000000..e960766
--- /dev/null
+++ b/guava-gwt/test/com/google/common/util/concurrent/FutureCallbackTest_gwt.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.common.util.concurrent;
+public class FutureCallbackTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+ at Override public String getModuleName() {
+ return "com.google.common.util.concurrent.testModule";
+}
+public void testCancel() throws Exception {
+ com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+ testCase.testCancel();
+}
+
+public void testExecutorSuccess() throws Exception {
+ com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+ testCase.testExecutorSuccess();
+}
+
+public void testRuntimeExeceptionFromGet() throws Exception {
+ com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+ testCase.testRuntimeExeceptionFromGet();
+}
+
+public void testSameThreadExecutionException() throws Exception {
+ com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+ testCase.testSameThreadExecutionException();
+}
+
+public void testSameThreadSuccess() throws Exception {
+ com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+ testCase.testSameThreadSuccess();
+}
+
+public void testThrowErrorFromGet() throws Exception {
+ com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+ testCase.testThrowErrorFromGet();
+}
+
+public void testWildcardFuture() throws Exception {
+ com.google.common.util.concurrent.FutureCallbackTest testCase = new com.google.common.util.concurrent.FutureCallbackTest();
+ testCase.testWildcardFuture();
+}
+}
diff --git a/guava-gwt/test/com/google/common/util/concurrent/FuturesTest_gwt.java b/guava-gwt/test/com/google/common/util/concurrent/FuturesTest_gwt.java
new file mode 100644
index 0000000..0bdb8e4
--- /dev/null
+++ b/guava-gwt/test/com/google/common/util/concurrent/FuturesTest_gwt.java
@@ -0,0 +1,2153 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.common.util.concurrent;
+public class FuturesTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+ at Override public String getModuleName() {
+ return "com.google.common.util.concurrent.testModule";
+}
+public void testAllAsList() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_cancelled() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_cancelled();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_doneFutures() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_doneFutures();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_emptyArray() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_emptyArray();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_failure() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_failure();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_logging_error() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_logging_error();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_logging_exception() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_logging_exception();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_logging_multipleExceptions_alreadyDone() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_logging_multipleExceptions_alreadyDone();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_logging_multipleExceptions_doneLater() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_logging_multipleExceptions_doneLater();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_logging_same_cause() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_logging_same_cause();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_logging_same_exception() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_logging_same_exception();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_logging_seenExceptionUpdateCancelRace() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_logging_seenExceptionUpdateCancelRace();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_logging_seenExceptionUpdateRace() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_logging_seenExceptionUpdateRace();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_resultCancelled() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_resultCancelled();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_resultCancelledInterrupted_withSecondaryListFuture() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_resultCancelledInterrupted_withSecondaryListFuture();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_resultCancelled_withSecondaryListFuture() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_resultCancelled_withSecondaryListFuture();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testAllAsList_resultInterrupted() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testAllAsList_resultInterrupted();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatchingAsync_Throwable() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatchingAsync_Throwable();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatchingAsync_fallbackGeneratesCheckedException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatchingAsync_fallbackGeneratesCheckedException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatchingAsync_fallbackGeneratesError() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatchingAsync_fallbackGeneratesError();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatchingAsync_fallbackGeneratesRuntimeException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatchingAsync_fallbackGeneratesRuntimeException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatchingAsync_fallbackNotReady() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatchingAsync_fallbackNotReady();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatchingAsync_fallbackReturnsCheckedException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatchingAsync_fallbackReturnsCheckedException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatchingAsync_fallbackReturnsRuntimeException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatchingAsync_fallbackReturnsRuntimeException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatchingAsync_inputDoesNotRaiseException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatchingAsync_inputDoesNotRaiseException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatchingAsync_inputRaisesException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatchingAsync_inputRaisesException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatchingAsync_nullInsteadOfFuture() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatchingAsync_nullInsteadOfFuture();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatchingAsync_resultCancelledBeforeFallback() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatchingAsync_resultCancelledBeforeFallback();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatchingAsync_resultInterruptedBeforeFallback() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatchingAsync_resultInterruptedBeforeFallback();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatching_Throwable() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatching_Throwable();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatching_fallbackGeneratesError() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatching_fallbackGeneratesError();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatching_fallbackGeneratesRuntimeException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatching_fallbackGeneratesRuntimeException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatching_inputDoesNotRaiseException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatching_inputDoesNotRaiseException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatching_inputRaisesException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatching_inputRaisesException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatching_resultCancelledBeforeFallback() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatching_resultCancelledBeforeFallback();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testCatching_resultInterruptedBeforeFallback() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testCatching_resultInterruptedBeforeFallback();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testDereference_genericsHierarchy() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testDereference_genericsHierarchy();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testDereference_genericsWildcard() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testDereference_genericsWildcard();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testDereference_innerCancelsResult() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testDereference_innerCancelsResult();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testDereference_outerCancelsResult() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testDereference_outerCancelsResult();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testDereference_resultCancelsInner() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testDereference_resultCancelsInner();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testDereference_resultCancelsOuter() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testDereference_resultCancelsOuter();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testImmediateFailedFuture() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testImmediateFailedFuture();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testImmediateFailedFuture_cancellationException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testImmediateFailedFuture_cancellationException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testImmediateFuture() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testImmediateFuture();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testMultipleImmediateFutures() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testMultipleImmediateFutures();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testSuccessfulAsList_logging_error() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testSuccessfulAsList_logging_error();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testSuccessfulAsList_logging_exception() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testSuccessfulAsList_logging_exception();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransformAsync_asyncFunction_error() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransformAsync_asyncFunction_error();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransformAsync_asyncFunction_nullInsteadOfFuture() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransformAsync_asyncFunction_nullInsteadOfFuture();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransformAsync_cancelPropagatesToAsyncOutput() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransformAsync_cancelPropagatesToAsyncOutput();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransformAsync_cancelPropagatesToInput() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransformAsync_cancelPropagatesToInput();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransformAsync_genericsHierarchy_AsyncFunction() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransformAsync_genericsHierarchy_AsyncFunction();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransformAsync_genericsWildcard_AsyncFunction() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransformAsync_genericsWildcard_AsyncFunction();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransformAsync_interruptPropagatesToAsyncOutput() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransformAsync_interruptPropagatesToAsyncOutput();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransformAsync_interruptPropagatesToInput() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransformAsync_interruptPropagatesToInput();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransformValueRemainsMemoized() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransformValueRemainsMemoized();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransform_Executor() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransform_Executor();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransform_asyncFunction_error() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransform_asyncFunction_error();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransform_asyncFunction_nullInsteadOfFuture() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransform_asyncFunction_nullInsteadOfFuture();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransform_cancelPropagatesToAsyncOutput() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransform_cancelPropagatesToAsyncOutput();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransform_cancelPropagatesToInput() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransform_cancelPropagatesToInput();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransform_genericsHierarchy() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransform_genericsHierarchy();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransform_genericsHierarchy_AsyncFunction() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransform_genericsHierarchy_AsyncFunction();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransform_genericsNull() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransform_genericsNull();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransform_genericsWildcard_AsyncFunction() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransform_genericsWildcard_AsyncFunction();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransform_interruptPropagatesToAsyncOutput() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransform_interruptPropagatesToAsyncOutput();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testTransform_interruptPropagatesToInput() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testTransform_interruptPropagatesToInput();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testWithFallback_fallbackGeneratesCheckedException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testWithFallback_fallbackGeneratesCheckedException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testWithFallback_fallbackGeneratesError() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testWithFallback_fallbackGeneratesError();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testWithFallback_fallbackGeneratesRuntimeException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testWithFallback_fallbackGeneratesRuntimeException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testWithFallback_fallbackNotReady() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testWithFallback_fallbackNotReady();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testWithFallback_fallbackReturnsCheckedException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testWithFallback_fallbackReturnsCheckedException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testWithFallback_fallbackReturnsRuntimeException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testWithFallback_fallbackReturnsRuntimeException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testWithFallback_inputDoesNotRaiseException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testWithFallback_inputDoesNotRaiseException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testWithFallback_inputRaisesException() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testWithFallback_inputRaisesException();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testWithFallback_nullInsteadOfFuture() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testWithFallback_nullInsteadOfFuture();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testWithFallback_resultCancelledBeforeFallback() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testWithFallback_resultCancelledBeforeFallback();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+
+public void testWithFallback_resultInterruptedBeforeFallback() throws Exception {
+ com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
+ testCase.setUp();
+ Throwable failure = null;
+ try {
+ testCase.testWithFallback_resultInterruptedBeforeFallback();
+ } catch (Throwable t) {
+ failure = t;
+ }
+ try {
+ testCase.tearDown();
+ } catch (Throwable t) {
+ if (failure == null) {
+ failure = t;
+ }
+ }
+ if (failure instanceof Exception) {
+ throw (Exception) failure;
+ }
+ if (failure instanceof Error) {
+ throw (Error) failure;
+ }
+ if (failure != null) {
+ throw new RuntimeException(failure);
+ }
+}
+}
diff --git a/guava-gwt/test/com/google/common/util/concurrent/TrustedInputFutureTest_gwt.java b/guava-gwt/test/com/google/common/util/concurrent/TrustedInputFutureTest_gwt.java
new file mode 100644
index 0000000..a1b62cf
--- /dev/null
+++ b/guava-gwt/test/com/google/common/util/concurrent/TrustedInputFutureTest_gwt.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.common.util.concurrent;
+public class TrustedInputFutureTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+ at Override public String getModuleName() {
+ return "com.google.common.util.concurrent.testModule";
+}
+public void testCanceled() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testCanceled();
+}
+
+public void testFailed() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testFailed();
+}
+
+public void testInterrupted() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testInterrupted();
+}
+
+public void testListenLaterCancelled() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterCancelled();
+}
+
+public void testListenLaterFailed() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterFailed();
+}
+
+public void testListenLaterInterrupted() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterInterrupted();
+}
+
+public void testListenLaterSetAsynchronously() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronously();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateCancelled() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronouslyLaterDelegateCancelled();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateFailed() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronouslyLaterDelegateFailed();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateInterrupted() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronouslyLaterDelegateInterrupted();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateSuccessful() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronouslyLaterDelegateSuccessful();
+}
+
+public void testListenLaterSetAsynchronouslyLaterSelfCancelled() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronouslyLaterSelfCancelled();
+}
+
+public void testListenLaterSetAsynchronouslyLaterSelfInterrupted() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronouslyLaterSelfInterrupted();
+}
+
+public void testListenLaterSuccessful() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSuccessful();
+}
+
+public void testMisbehavingListenerAlreadyDone() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testMisbehavingListenerAlreadyDone();
+}
+
+public void testMisbehavingListenerLaterDone() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testMisbehavingListenerLaterDone();
+}
+
+public void testNullExecutor() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testNullExecutor();
+}
+
+public void testNullListener() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testNullListener();
+}
+
+public void testNullTimeUnit() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testNullTimeUnit();
+}
+
+public void testPending() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testPending();
+}
+
+public void testSetExceptionNull() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetExceptionNull();
+}
+
+public void testSetFutureDelegateAlreadyCancelled() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureDelegateAlreadyCancelled();
+}
+
+public void testSetFutureDelegateAlreadyInterrupted() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureDelegateAlreadyInterrupted();
+}
+
+public void testSetFutureDelegateAlreadySuccessful() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureDelegateAlreadySuccessful();
+}
+
+public void testSetFutureDelegateLaterCancelled() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureDelegateLaterCancelled();
+}
+
+public void testSetFutureDelegateLaterInterrupted() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureDelegateLaterInterrupted();
+}
+
+public void testSetFutureDelegateLaterSuccessful() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureDelegateLaterSuccessful();
+}
+
+public void testSetFutureNull() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureNull();
+}
+
+public void testSetFuturePending() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFuturePending();
+}
+
+public void testSetFutureThenCancel() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureThenCancel();
+}
+
+public void testSetFutureThenInterrupt() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureThenInterrupt();
+}
+
+public void testSetNull() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetNull();
+}
+
+public void testSuccessful() throws Exception {
+ com.google.common.util.concurrent.TrustedInputFutureTest testCase = new com.google.common.util.concurrent.TrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSuccessful();
+}
+}
diff --git a/guava-gwt/test/com/google/common/util/concurrent/TrustedListenableFutureTaskTest_gwt.java b/guava-gwt/test/com/google/common/util/concurrent/TrustedListenableFutureTaskTest_gwt.java
new file mode 100644
index 0000000..f91659d
--- /dev/null
+++ b/guava-gwt/test/com/google/common/util/concurrent/TrustedListenableFutureTaskTest_gwt.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.common.util.concurrent;
+public class TrustedListenableFutureTaskTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+ at Override public String getModuleName() {
+ return "com.google.common.util.concurrent.testModule";
+}
+public void testCancelled() throws Exception {
+ com.google.common.util.concurrent.TrustedListenableFutureTaskTest testCase = new com.google.common.util.concurrent.TrustedListenableFutureTaskTest();
+ testCase.testCancelled();
+}
+
+public void testFailed() throws Exception {
+ com.google.common.util.concurrent.TrustedListenableFutureTaskTest testCase = new com.google.common.util.concurrent.TrustedListenableFutureTaskTest();
+ testCase.testFailed();
+}
+
+public void testSuccessful() throws Exception {
+ com.google.common.util.concurrent.TrustedListenableFutureTaskTest testCase = new com.google.common.util.concurrent.TrustedListenableFutureTaskTest();
+ testCase.testSuccessful();
+}
+}
diff --git a/guava-gwt/test/com/google/common/util/concurrent/UntrustedInputFutureTest_gwt.java b/guava-gwt/test/com/google/common/util/concurrent/UntrustedInputFutureTest_gwt.java
new file mode 100644
index 0000000..9bb0baa
--- /dev/null
+++ b/guava-gwt/test/com/google/common/util/concurrent/UntrustedInputFutureTest_gwt.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.common.util.concurrent;
+public class UntrustedInputFutureTest_gwt extends com.google.gwt.junit.client.GWTTestCase {
+ at Override public String getModuleName() {
+ return "com.google.common.util.concurrent.testModule";
+}
+public void testCanceled() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testCanceled();
+}
+
+public void testFailed() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testFailed();
+}
+
+public void testInterrupted() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testInterrupted();
+}
+
+public void testListenLaterCancelled() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterCancelled();
+}
+
+public void testListenLaterFailed() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterFailed();
+}
+
+public void testListenLaterInterrupted() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterInterrupted();
+}
+
+public void testListenLaterSetAsynchronously() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronously();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateCancelled() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronouslyLaterDelegateCancelled();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateFailed() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronouslyLaterDelegateFailed();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateInterrupted() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronouslyLaterDelegateInterrupted();
+}
+
+public void testListenLaterSetAsynchronouslyLaterDelegateSuccessful() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronouslyLaterDelegateSuccessful();
+}
+
+public void testListenLaterSetAsynchronouslyLaterSelfCancelled() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronouslyLaterSelfCancelled();
+}
+
+public void testListenLaterSetAsynchronouslyLaterSelfInterrupted() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSetAsynchronouslyLaterSelfInterrupted();
+}
+
+public void testListenLaterSuccessful() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testListenLaterSuccessful();
+}
+
+public void testMisbehavingListenerAlreadyDone() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testMisbehavingListenerAlreadyDone();
+}
+
+public void testMisbehavingListenerLaterDone() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testMisbehavingListenerLaterDone();
+}
+
+public void testNullExecutor() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testNullExecutor();
+}
+
+public void testNullListener() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testNullListener();
+}
+
+public void testNullTimeUnit() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testNullTimeUnit();
+}
+
+public void testPending() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testPending();
+}
+
+public void testSetExceptionNull() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetExceptionNull();
+}
+
+public void testSetFutureDelegateAlreadyCancelled() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureDelegateAlreadyCancelled();
+}
+
+public void testSetFutureDelegateAlreadyInterrupted() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureDelegateAlreadyInterrupted();
+}
+
+public void testSetFutureDelegateAlreadySuccessful() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureDelegateAlreadySuccessful();
+}
+
+public void testSetFutureDelegateLaterCancelled() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureDelegateLaterCancelled();
+}
+
+public void testSetFutureDelegateLaterInterrupted() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureDelegateLaterInterrupted();
+}
+
+public void testSetFutureDelegateLaterSuccessful() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureDelegateLaterSuccessful();
+}
+
+public void testSetFutureNull() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureNull();
+}
+
+public void testSetFuturePending() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFuturePending();
+}
+
+public void testSetFutureThenCancel() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureThenCancel();
+}
+
+public void testSetFutureThenInterrupt() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetFutureThenInterrupt();
+}
+
+public void testSetNull() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSetNull();
+}
+
+public void testSuccessful() throws Exception {
+ com.google.common.util.concurrent.UntrustedInputFutureTest testCase = new com.google.common.util.concurrent.UntrustedInputFutureTest();
+ testCase.setUp();
+ testCase.testSuccessful();
+}
+}
diff --git a/guava-gwt/test/com/google/common/util/concurrent/testModule.gwt.xml b/guava-gwt/test/com/google/common/util/concurrent/testModule.gwt.xml
index c9f489f..c7b559a 100644
--- a/guava-gwt/test/com/google/common/util/concurrent/testModule.gwt.xml
+++ b/guava-gwt/test/com/google/common/util/concurrent/testModule.gwt.xml
@@ -5,11 +5,13 @@
<inherits name="com.google.common.annotations.Annotations"/>
<inherits name="com.google.common.base.Base"/>
<inherits name="com.google.common.collect.Collect"/>
+ <inherits name="com.google.common.testing.Testing"/>
<inherits name="com.google.common.util.concurrent.Concurrent"/>
+ <inherits name="com.google.common.truth.Truth"/>
<entry-point class="com.google.common.util.concurrent.TestModuleEntryPoint"/>
<source path=""/>
-
+
<super-source path="super"/>
</module>
diff --git a/guava-testlib/pom.xml b/guava-testlib/pom.xml
index 5fe40f1..45b6a6f 100644
--- a/guava-testlib/pom.xml
+++ b/guava-testlib/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>com.google.guava</groupId>
<artifactId>guava-parent</artifactId>
- <version>18.0</version>
+ <version>19.0</version>
</parent>
<artifactId>guava-testlib</artifactId>
<name>Guava Testing Library</name>
@@ -19,6 +19,15 @@
<artifactId>jsr305</artifactId>
</dependency>
<dependency>
+ <groupId>com.google.errorprone</groupId>
+ <artifactId>error_prone_annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.j2objc</groupId>
+ <artifactId>j2objc-annotations</artifactId>
+ <optional>true</optional><!-- needed only for annotations -->
+ </dependency>
+ <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>guava</artifactId>
<version>${project.version}</version>
@@ -29,9 +38,12 @@
<scope>compile</scope><!-- testlib must carry these transitively -->
</dependency>
<dependency>
+ <!--
+ Do not include Truth in non-test scope! Doing so creates a problematic dependency cycle.
+ -->
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
- <scope>compile</scope><!-- testlib must carry these transitively -->
+ <scope>test</scope>
</dependency>
</dependencies>
<build>
@@ -51,9 +63,9 @@
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
- <version>2.3.1</version>
<executions>
<execution>
+ <id>create-test-jar</id>
<goals><goal>test-jar</goal></goals>
</execution>
</executions>
@@ -65,6 +77,12 @@
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <redirectTestOutputToFile>true</redirectTestOutputToFile>
+ </configuration>
+ </plugin>
</plugins>
</build>
</project>
diff --git a/guava-testlib/src/com/google/common/collect/testing/AbstractContainerTester.java b/guava-testlib/src/com/google/common/collect/testing/AbstractContainerTester.java
index a650f28..fbf44b6 100644
--- a/guava-testlib/src/com/google/common/collect/testing/AbstractContainerTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/AbstractContainerTester.java
@@ -237,11 +237,31 @@ public abstract class AbstractContainerTester<C, E>
@SuppressWarnings("unchecked")
protected MinimalCollection<E> createDisjointCollection() {
- return MinimalCollection.of(samples.e3, samples.e4);
+ return MinimalCollection.of(e3(), e4());
}
@SuppressWarnings("unchecked")
protected MinimalCollection<E> emptyCollection() {
return MinimalCollection.<E>of();
}
+
+ protected final E e0() {
+ return samples.e0();
+ }
+
+ protected final E e1() {
+ return samples.e1();
+ }
+
+ protected final E e2() {
+ return samples.e2();
+ }
+
+ protected final E e3() {
+ return samples.e3();
+ }
+
+ protected final E e4() {
+ return samples.e4();
+ }
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/AbstractMapTester.java b/guava-testlib/src/com/google/common/collect/testing/AbstractMapTester.java
index 4dd6298..5d57ea1 100644
--- a/guava-testlib/src/com/google/common/collect/testing/AbstractMapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/AbstractMapTester.java
@@ -154,7 +154,7 @@ public abstract class AbstractMapTester<K, V> extends
@SuppressWarnings("unchecked")
@Override protected MinimalCollection<Map.Entry<K, V>>
createDisjointCollection() {
- return MinimalCollection.of(samples.e3, samples.e4);
+ return MinimalCollection.of(e3(), e4());
}
protected int getNumEntries() {
@@ -228,4 +228,44 @@ public abstract class AbstractMapTester<K, V> extends
protected void resetMap(Entry<K, V>[] entries) {
resetContainer(getSubjectGenerator().create((Object[]) entries));
}
+
+ protected final K k0() {
+ return e0().getKey();
+ }
+
+ protected final V v0() {
+ return e0().getValue();
+ }
+
+ protected final K k1() {
+ return e1().getKey();
+ }
+
+ protected final V v1() {
+ return e1().getValue();
+ }
+
+ protected final K k2() {
+ return e2().getKey();
+ }
+
+ protected final V v2() {
+ return e2().getValue();
+ }
+
+ protected final K k3() {
+ return e3().getKey();
+ }
+
+ protected final V v3() {
+ return e3().getValue();
+ }
+
+ protected final K k4() {
+ return e4().getKey();
+ }
+
+ protected final V v4() {
+ return e4().getValue();
+ }
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/CollectionTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/CollectionTestSuiteBuilder.java
index d4143b5..02b3917 100644
--- a/guava-testlib/src/com/google/common/collect/testing/CollectionTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/CollectionTestSuiteBuilder.java
@@ -16,7 +16,9 @@
package com.google.common.collect.testing;
-import com.google.common.collect.testing.features.CollectionFeature;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS;
+
import com.google.common.collect.testing.features.Feature;
import com.google.common.testing.SerializableTester;
@@ -53,7 +55,7 @@ public class CollectionTestSuiteBuilder<E>
List<TestSuite> derivedSuites = new ArrayList<TestSuite>(
super.createDerivedSuites(parentBuilder));
- if (parentBuilder.getFeatures().contains(CollectionFeature.SERIALIZABLE)) {
+ if (parentBuilder.getFeatures().contains(SERIALIZABLE)) {
derivedSuites.add(CollectionTestSuiteBuilder
.using(new ReserializedCollectionGenerator<E>(parentBuilder.getSubjectGenerator()))
.named(getName() + " reserialized")
@@ -95,8 +97,8 @@ public class CollectionTestSuiteBuilder<E>
private static Set<Feature<?>> computeReserializedCollectionFeatures(Set<Feature<?>> features) {
Set<Feature<?>> derivedFeatures = new HashSet<Feature<?>>();
derivedFeatures.addAll(features);
- derivedFeatures.remove(CollectionFeature.SERIALIZABLE);
- derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS);
+ derivedFeatures.remove(SERIALIZABLE);
+ derivedFeatures.remove(SERIALIZABLE_INCLUDING_VIEWS);
return derivedFeatures;
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/ConcurrentMapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/ConcurrentMapTestSuiteBuilder.java
new file mode 100644
index 0000000..37e7765
--- /dev/null
+++ b/guava-testlib/src/com/google/common/collect/testing/ConcurrentMapTestSuiteBuilder.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.common.collect.testing;
+
+import com.google.common.collect.testing.testers.ConcurrentMapPutIfAbsentTester;
+import com.google.common.collect.testing.testers.ConcurrentMapRemoveTester;
+import com.google.common.collect.testing.testers.ConcurrentMapReplaceEntryTester;
+import com.google.common.collect.testing.testers.ConcurrentMapReplaceTester;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Creates, based on your criteria, a JUnit test suite that exhaustively tests a ConcurrentMap
+ * implementation.
+ *
+ * @author Louis Wasserman
+ */
+public class ConcurrentMapTestSuiteBuilder<K, V> extends MapTestSuiteBuilder<K, V> {
+ public static <K, V> ConcurrentMapTestSuiteBuilder<K, V> using(
+ TestMapGenerator<K, V> generator) {
+ ConcurrentMapTestSuiteBuilder<K, V> result = new ConcurrentMapTestSuiteBuilder<K, V>();
+ result.usingGenerator(generator);
+ return result;
+ }
+
+ static final List<? extends Class<? extends AbstractTester>> TESTERS =
+ Arrays.asList(
+ ConcurrentMapPutIfAbsentTester.class,
+ ConcurrentMapRemoveTester.class,
+ ConcurrentMapReplaceTester.class,
+ ConcurrentMapReplaceEntryTester.class);
+
+ @Override
+ protected List<Class<? extends AbstractTester>> getTesters() {
+ List<Class<? extends AbstractTester>> testers = Helpers.copyToList(super.getTesters());
+ testers.addAll(TESTERS);
+ return testers;
+ }
+}
diff --git a/guava-testlib/src/com/google/common/collect/testing/ConcurrentNavigableMapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/ConcurrentNavigableMapTestSuiteBuilder.java
new file mode 100644
index 0000000..e82a964
--- /dev/null
+++ b/guava-testlib/src/com/google/common/collect/testing/ConcurrentNavigableMapTestSuiteBuilder.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.collect.testing;
+
+import java.util.List;
+
+/**
+ * Creates, based on your criteria, a JUnit test suite that exhaustively tests
+ * a ConcurrentNavigableMap implementation.
+ *
+ * @author Louis Wasserman
+ */
+public class ConcurrentNavigableMapTestSuiteBuilder<K, V> extends
+ NavigableMapTestSuiteBuilder<K, V> {
+
+ public static <K, V> ConcurrentNavigableMapTestSuiteBuilder<K, V> using(
+ TestSortedMapGenerator<K, V> generator) {
+ ConcurrentNavigableMapTestSuiteBuilder<K, V> result =
+ new ConcurrentNavigableMapTestSuiteBuilder<K, V>();
+ result.usingGenerator(generator);
+ return result;
+ }
+
+ @Override
+ protected List<Class<? extends AbstractTester>> getTesters() {
+ List<Class<? extends AbstractTester>> testers = Helpers.copyToList(super.getTesters());
+ testers.addAll(ConcurrentMapTestSuiteBuilder.TESTERS);
+ return testers;
+ }
+
+ @Override
+ NavigableMapTestSuiteBuilder<K, V> subSuiteUsing(TestSortedMapGenerator<K, V> generator) {
+ return using(generator);
+ }
+}
diff --git a/guava-testlib/src/com/google/common/collect/testing/DerivedCollectionGenerators.java b/guava-testlib/src/com/google/common/collect/testing/DerivedCollectionGenerators.java
index e91d08d..08d1866 100644
--- a/guava-testlib/src/com/google/common/collect/testing/DerivedCollectionGenerators.java
+++ b/guava-testlib/src/com/google/common/collect/testing/DerivedCollectionGenerators.java
@@ -107,11 +107,11 @@ public final class DerivedCollectionGenerators {
final SampleElements<Map.Entry<K, V>> mapSamples =
this.mapGenerator.samples();
this.samples = new SampleElements<K>(
- mapSamples.e0.getKey(),
- mapSamples.e1.getKey(),
- mapSamples.e2.getKey(),
- mapSamples.e3.getKey(),
- mapSamples.e4.getKey());
+ mapSamples.e0().getKey(),
+ mapSamples.e1().getKey(),
+ mapSamples.e2().getKey(),
+ mapSamples.e3().getKey(),
+ mapSamples.e4().getKey());
}
@Override
@@ -151,7 +151,7 @@ public final class DerivedCollectionGenerators {
@Override
public Iterable<K> order(List<K> insertionOrder) {
- V v = ((TestMapGenerator<K, V>) mapGenerator.getInnerGenerator()).samples().e0.getValue();
+ V v = ((TestMapGenerator<K, V>) mapGenerator.getInnerGenerator()).samples().e0().getValue();
List<Entry<K, V>> entries = new ArrayList<Entry<K, V>>();
for (K element : insertionOrder) {
entries.add(mapEntry(element, v));
@@ -220,11 +220,11 @@ public final class DerivedCollectionGenerators {
final SampleElements<Map.Entry<K, V>> mapSamples =
this.mapGenerator.samples();
this.samples = new SampleElements<V>(
- mapSamples.e0.getValue(),
- mapSamples.e1.getValue(),
- mapSamples.e2.getValue(),
- mapSamples.e3.getValue(),
- mapSamples.e4.getValue());
+ mapSamples.e0().getValue(),
+ mapSamples.e1().getValue(),
+ mapSamples.e2().getValue(),
+ mapSamples.e3().getValue(),
+ mapSamples.e4().getValue());
}
@Override
@@ -484,7 +484,7 @@ public final class DerivedCollectionGenerators {
SampleElements<Entry<K, V>> samples = delegate.samples();
@SuppressWarnings("unchecked") // no elements are inserted into the array
List<Entry<K, V>> samplesList = Arrays.asList(
- samples.e0, samples.e1, samples.e2, samples.e3, samples.e4);
+ samples.e0(), samples.e1(), samples.e2(), samples.e3(), samples.e4());
Collections.sort(samplesList, entryComparator);
this.firstInclusive = samplesList.get(0).getKey();
this.lastInclusive = samplesList.get(samplesList.size() - 1).getKey();
diff --git a/guava-testlib/src/com/google/common/collect/testing/Helpers.java b/guava-testlib/src/com/google/common/collect/testing/Helpers.java
index 277f50d..7377626 100644
--- a/guava-testlib/src/com/google/common/collect/testing/Helpers.java
+++ b/guava-testlib/src/com/google/common/collect/testing/Helpers.java
@@ -76,6 +76,49 @@ public class Helpers {
return Collections.singletonMap(key, value).entrySet().iterator().next();
}
+ private static boolean isEmpty(Iterable<?> iterable) {
+ return iterable instanceof Collection
+ ? ((Collection<?>) iterable).isEmpty()
+ : iterable.iterator().hasNext();
+ }
+
+ public static void assertEmpty(Iterable<?> iterable) {
+ if (!isEmpty(iterable)) {
+ Assert.fail("Not true that " + iterable + " is empty");
+ }
+ }
+
+ public static void assertEmpty(Map<?, ?> map) {
+ if (!map.isEmpty()) {
+ Assert.fail("Not true that " + map + " is empty");
+ }
+ }
+
+ public static void assertEqualInOrder(
+ Iterable<?> expected, Iterable<?> actual) {
+ Iterator<?> expectedIter = expected.iterator();
+ Iterator<?> actualIter = actual.iterator();
+
+ while (expectedIter.hasNext() && actualIter.hasNext()) {
+ if (!equal(expectedIter.next(), actualIter.next())) {
+ Assert.fail(
+ "contents were not equal and in the same order: "
+ + "expected = " + expected + ", actual = " + actual);
+ }
+ }
+
+ if (expectedIter.hasNext() || actualIter.hasNext()) {
+ // actual either had too few or too many elements
+ Assert.fail(
+ "contents were not equal and in the same order: "
+ + "expected = " + expected + ", actual = " + actual);
+ }
+ }
+
+ public static void assertContentsInOrder(Iterable<?> actual, Object... expected) {
+ assertEqualInOrder(Arrays.asList(expected), actual);
+ }
+
public static void assertEqualIgnoringOrder(
Iterable<?> expected, Iterable<?> actual) {
List<?> exp = copyToList(expected);
@@ -100,6 +143,39 @@ public class Helpers {
assertEqualIgnoringOrder(Arrays.asList(expected), actual);
}
+ public static void assertContains(Iterable<?> actual, Object expected) {
+ boolean contained = false;
+ if (actual instanceof Collection) {
+ contained = ((Collection<?>) actual).contains(expected);
+ } else {
+ for (Object o : actual) {
+ if (equal(o, expected)) {
+ contained = true;
+ break;
+ }
+ }
+ }
+
+ if (!contained) {
+ Assert.fail("Not true that " + actual + " contains " + expected);
+ }
+ }
+
+ public static void assertContainsAllOf(
+ Iterable<?> actual, Object... expected) {
+ List<Object> expectedList = new ArrayList<Object>();
+ expectedList.addAll(Arrays.asList(expected));
+
+ for (Object o : actual) {
+ expectedList.remove(o);
+ }
+
+ if (!expectedList.isEmpty()) {
+ Assert.fail(
+ "Not true that " + actual + " contains all of " + Arrays.asList(expected));
+ }
+ }
+
public static <E> boolean addAll(
Collection<E> addTo, Iterable<? extends E> elementsToAdd) {
boolean modified = false;
@@ -180,11 +256,31 @@ public class Helpers {
};
}
+ /**
+ * Asserts that all pairs of {@code T} values within {@code valuesInExpectedOrder} are ordered
+ * consistently between their order within {@code valuesInExpectedOrder} and the order implied by
+ * the given {@code comparator}.
+ *
+ * @see #testComparator(Comparator, List)
+ */
public static <T> void testComparator(
Comparator<? super T> comparator, T... valuesInExpectedOrder) {
testComparator(comparator, Arrays.asList(valuesInExpectedOrder));
}
+ /**
+ * Asserts that all pairs of {@code T} values within {@code valuesInExpectedOrder} are ordered
+ * consistently between their order within {@code valuesInExpectedOrder} and the order implied by
+ * the given {@code comparator}.
+ *
+ * <p>In detail, this method asserts
+ * <ul>
+ * <li><i>reflexivity</i>: {@code comparator.compare(t, t) = 0} for all {@code t} in
+ * {@code valuesInExpectedOrder}; and
+ * <li><i>consistency</i>: {@code comparator.compare(ti, tj) < 0} and
+ * {@code comparator.compare(tj, ti) > 0} for {@code i < j}, where
+ * {@code ti = valuesInExpectedOrder.get(i)} and {@code tj = valuesInExpectedOrder.get(j)}.
+ */
public static <T> void testComparator(
Comparator<? super T> comparator, List<T> valuesInExpectedOrder) {
// This does an O(n^2) test of all pairs of values in both orders
diff --git a/guava-testlib/src/com/google/common/collect/testing/ListTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/ListTestSuiteBuilder.java
index 03f16cf..71b410c 100644
--- a/guava-testlib/src/com/google/common/collect/testing/ListTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/ListTestSuiteBuilder.java
@@ -16,6 +16,10 @@
package com.google.common.collect.testing;
+import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS;
+
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.Feature;
import com.google.common.collect.testing.testers.CollectionSerializationEqualTester;
@@ -91,7 +95,7 @@ public final class ListTestSuiteBuilder<E> extends
* lists have an iteration ordering corresponding to the insertion order.
*/
@Override public TestSuite createTestSuite() {
- withFeatures(CollectionFeature.KNOWN_ORDER);
+ withFeatures(KNOWN_ORDER);
return super.createTestSuite();
}
@@ -104,7 +108,7 @@ public final class ListTestSuiteBuilder<E> extends
List<TestSuite> derivedSuites = new ArrayList<TestSuite>(
super.createDerivedSuites(parentBuilder));
- if (parentBuilder.getFeatures().contains(CollectionFeature.SERIALIZABLE)) {
+ if (parentBuilder.getFeatures().contains(SERIALIZABLE)) {
derivedSuites.add(ListTestSuiteBuilder
.using(new ReserializedListGenerator<E>(parentBuilder.getSubjectGenerator()))
.named(getName() + " reserialized")
@@ -147,8 +151,8 @@ public final class ListTestSuiteBuilder<E> extends
Set<Feature<?>> features) {
Set<Feature<?>> derivedFeatures = new HashSet<Feature<?>>();
derivedFeatures.addAll(features);
- derivedFeatures.remove(CollectionFeature.SERIALIZABLE);
- derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS);
+ derivedFeatures.remove(SERIALIZABLE);
+ derivedFeatures.remove(SERIALIZABLE_INCLUDING_VIEWS);
return derivedFeatures;
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/MapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/MapTestSuiteBuilder.java
index c8390f0..3f3fc1a 100644
--- a/guava-testlib/src/com/google/common/collect/testing/MapTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/MapTestSuiteBuilder.java
@@ -169,7 +169,7 @@ public class MapTestSuiteBuilder<K, V>
Set<Feature<?>> keySetFeatures =
computeCommonDerivedCollectionFeatures(mapFeatures);
- // TODO(user): make this trigger only if the map is a submap
+ // TODO(lowasser): make this trigger only if the map is a submap
// currently, the KeySetGenerator won't work properly for a subset of a keyset of a submap
keySetFeatures.add(CollectionFeature.SUBSET_VIEW);
if (mapFeatures.contains(MapFeature.ALLOWS_NULL_KEYS)) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/NavigableMapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/NavigableMapTestSuiteBuilder.java
index c31cc61..aa91337 100644
--- a/guava-testlib/src/com/google/common/collect/testing/NavigableMapTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/NavigableMapTestSuiteBuilder.java
@@ -20,6 +20,7 @@ import static com.google.common.collect.testing.Helpers.castOrCopyToList;
import static java.util.Collections.reverse;
import com.google.common.collect.testing.DerivedCollectionGenerators.Bound;
+import com.google.common.collect.testing.DerivedCollectionGenerators.ForwardingTestMapGenerator;
import com.google.common.collect.testing.DerivedCollectionGenerators.SortedMapSubmapTestMapGenerator;
import com.google.common.collect.testing.features.Feature;
import com.google.common.collect.testing.testers.NavigableMapNavigationTester;
@@ -106,7 +107,7 @@ public class NavigableMapTestSuiteBuilder<K, V> extends SortedMapTestSuiteBuilde
@Override
public NavigableMapTestSuiteBuilder<K, V> newBuilderUsing(
TestSortedMapGenerator<K, V> delegate, Bound to, Bound from) {
- return using(new NavigableMapSubmapTestMapGenerator<K, V>(delegate, to, from));
+ return subSuiteUsing(new NavigableMapSubmapTestMapGenerator<K, V>(delegate, to, from));
}
/**
@@ -114,68 +115,64 @@ public class NavigableMapTestSuiteBuilder<K, V> extends SortedMapTestSuiteBuilde
*/
private TestSuite createDescendingSuite(final FeatureSpecificTestSuiteBuilder<?,
? extends OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>>> parentBuilder) {
- final TestMapGenerator<K, V> delegate
- = (TestMapGenerator<K, V>) parentBuilder.getSubjectGenerator().getInnerGenerator();
+ final TestSortedMapGenerator<K, V> delegate
+ = (TestSortedMapGenerator<K, V>) parentBuilder.getSubjectGenerator().getInnerGenerator();
List<Feature<?>> features = new ArrayList<Feature<?>>();
features.add(NoRecurse.DESCENDING);
features.addAll(parentBuilder.getFeatures());
- return NavigableMapTestSuiteBuilder
- .using(new ForwardingTestMapGenerator<K, V>(delegate) {
- @Override public Map<K, V> create(Object... entries) {
- NavigableMap<K, V> map = (NavigableMap<K, V>) delegate.create(entries);
- return map.descendingMap();
- }
-
- @Override
- public Iterable<Entry<K, V>> order(List<Entry<K, V>> insertionOrder) {
- insertionOrder = castOrCopyToList(delegate.order(insertionOrder));
- reverse(insertionOrder);
- return insertionOrder;
- }
- })
+ return subSuiteUsing(new DescendingTestMapGenerator<K, V>(delegate))
.named(parentBuilder.getName() + " descending")
.withFeatures(features)
.suppressing(parentBuilder.getSuppressedTests())
.createTestSuite();
}
+
+ NavigableMapTestSuiteBuilder<K, V> subSuiteUsing(TestSortedMapGenerator<K, V> generator) {
+ return using(generator);
+ }
+
+ static class DescendingTestMapGenerator<K, V>
+ extends ForwardingTestMapGenerator<K, V> implements TestSortedMapGenerator<K, V> {
+ DescendingTestMapGenerator(TestSortedMapGenerator<K, V> delegate) {
+ super(delegate);
+ }
- static class ForwardingTestMapGenerator<K, V> implements TestMapGenerator<K, V> {
- private TestMapGenerator<K, V> delegate;
-
- ForwardingTestMapGenerator(TestMapGenerator<K, V> delegate) {
- this.delegate = delegate;
+ @Override public NavigableMap<K, V> create(Object... entries) {
+ NavigableMap<K, V> map = (NavigableMap<K, V>) delegate.create(entries);
+ return map.descendingMap();
}
@Override
public Iterable<Entry<K, V>> order(List<Entry<K, V>> insertionOrder) {
- return delegate.order(insertionOrder);
+ insertionOrder = castOrCopyToList(delegate.order(insertionOrder));
+ reverse(insertionOrder);
+ return insertionOrder;
}
-
- @Override
- public K[] createKeyArray(int length) {
- return delegate.createKeyArray(length);
+
+ TestSortedMapGenerator<K, V> delegate() {
+ return (TestSortedMapGenerator<K, V>) delegate;
}
@Override
- public V[] createValueArray(int length) {
- return delegate.createValueArray(length);
+ public Entry<K, V> belowSamplesLesser() {
+ return delegate().aboveSamplesGreater();
}
@Override
- public SampleElements<Entry<K, V>> samples() {
- return delegate.samples();
+ public Entry<K, V> belowSamplesGreater() {
+ return delegate().aboveSamplesLesser();
}
@Override
- public Map<K, V> create(Object... elements) {
- return delegate.create(elements);
+ public Entry<K, V> aboveSamplesLesser() {
+ return delegate().belowSamplesGreater();
}
@Override
- public Entry<K, V>[] createArray(int length) {
- return delegate.createArray(length);
- }
+ public Entry<K, V> aboveSamplesGreater() {
+ return delegate().belowSamplesLesser();
+ }
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/NavigableSetTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/NavigableSetTestSuiteBuilder.java
index 4642147..524d721 100644
--- a/guava-testlib/src/com/google/common/collect/testing/NavigableSetTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/NavigableSetTestSuiteBuilder.java
@@ -16,9 +16,11 @@
package com.google.common.collect.testing;
+import static com.google.common.collect.testing.features.CollectionFeature.DESCENDING_VIEW;
+import static com.google.common.collect.testing.features.CollectionFeature.SUBSET_VIEW;
+
import com.google.common.collect.testing.DerivedCollectionGenerators.Bound;
import com.google.common.collect.testing.DerivedCollectionGenerators.SortedSetSubsetTestSetGenerator;
-import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.Feature;
import com.google.common.collect.testing.testers.NavigableSetNavigationTester;
@@ -52,7 +54,7 @@ public final class NavigableSetTestSuiteBuilder<E>
List<TestSuite> derivedSuites = new ArrayList<TestSuite>(
super.createDerivedSuites(parentBuilder));
- if (!parentBuilder.getFeatures().contains(CollectionFeature.SUBSET_VIEW)) {
+ if (!parentBuilder.getFeatures().contains(SUBSET_VIEW)) {
// Other combinations are inherited from SortedSetTestSuiteBuilder.
derivedSuites.add(createSubsetSuite(parentBuilder, Bound.NO_BOUND, Bound.INCLUSIVE));
derivedSuites.add(createSubsetSuite(parentBuilder, Bound.EXCLUSIVE, Bound.NO_BOUND));
@@ -60,7 +62,7 @@ public final class NavigableSetTestSuiteBuilder<E>
derivedSuites.add(createSubsetSuite(parentBuilder, Bound.EXCLUSIVE, Bound.INCLUSIVE));
derivedSuites.add(createSubsetSuite(parentBuilder, Bound.INCLUSIVE, Bound.INCLUSIVE));
}
- if (!parentBuilder.getFeatures().contains(CollectionFeature.DESCENDING_VIEW)) {
+ if (!parentBuilder.getFeatures().contains(DESCENDING_VIEW)) {
derivedSuites.add(createDescendingSuite(parentBuilder));
}
return derivedSuites;
@@ -107,7 +109,7 @@ public final class NavigableSetTestSuiteBuilder<E>
(TestSetGenerator<E>) parentBuilder.getSubjectGenerator().getInnerGenerator();
List<Feature<?>> features = new ArrayList<Feature<?>>();
- features.add(CollectionFeature.DESCENDING_VIEW);
+ features.add(DESCENDING_VIEW);
features.addAll(parentBuilder.getFeatures());
return NavigableSetTestSuiteBuilder.using(new TestSetGenerator<E>() {
diff --git a/guava-testlib/src/com/google/common/collect/testing/OneSizeGenerator.java b/guava-testlib/src/com/google/common/collect/testing/OneSizeGenerator.java
index cb61997..5046e6d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/OneSizeGenerator.java
+++ b/guava-testlib/src/com/google/common/collect/testing/OneSizeGenerator.java
@@ -73,7 +73,7 @@ public final class OneSizeGenerator<T, E>
SampleElements<E> samples = samples();
@SuppressWarnings("unchecked")
List<E> allSampleElements = Arrays.asList(
- samples.e0, samples.e1, samples.e2, samples.e3, samples.e4);
+ samples.e0(), samples.e1(), samples.e2(), samples.e3(), samples.e4());
return new ArrayList<E>(allSampleElements.subList(0, howMany));
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/Platform.java b/guava-testlib/src/com/google/common/collect/testing/Platform.java
index 99eeb06..fe1e9af 100644
--- a/guava-testlib/src/com/google/common/collect/testing/Platform.java
+++ b/guava-testlib/src/com/google/common/collect/testing/Platform.java
@@ -18,6 +18,8 @@ package com.google.common.collect.testing;
import com.google.common.annotations.GwtCompatible;
+import java.util.Locale;
+
/**
* Methods factored out so that they can be emulated differently in GWT.
*
@@ -48,7 +50,7 @@ final class Platform {
}
static String format(String template, Object... args) {
- return String.format(template, args);
+ return String.format(Locale.ROOT, template, args);
}
private Platform() {}
diff --git a/guava-testlib/src/com/google/common/collect/testing/SampleElements.java b/guava-testlib/src/com/google/common/collect/testing/SampleElements.java
index d0b7638..092eac3 100644
--- a/guava-testlib/src/com/google/common/collect/testing/SampleElements.java
+++ b/guava-testlib/src/com/google/common/collect/testing/SampleElements.java
@@ -31,11 +31,11 @@ import java.util.Map;
@GwtCompatible
public class SampleElements<E> implements Iterable<E> {
// TODO: rename e3, e4 => missing1, missing2
- public final E e0;
- public final E e1;
- public final E e2;
- public final E e3;
- public final E e4;
+ private final E e0;
+ private final E e1;
+ private final E e2;
+ private final E e3;
+ private final E e4;
public SampleElements(E e0, E e1, E e2, E e3, E e4) {
this.e0 = e0;
@@ -51,7 +51,7 @@ public class SampleElements<E> implements Iterable<E> {
}
public List<E> asList() {
- return Arrays.asList(e0, e1, e2, e3, e4);
+ return Arrays.asList(e0(), e1(), e2(), e3(), e4());
}
public static class Strings extends SampleElements<String> {
@@ -92,11 +92,31 @@ public class SampleElements<E> implements Iterable<E> {
public static <K, V> SampleElements<Map.Entry<K, V>> mapEntries(
SampleElements<K> keys, SampleElements<V> values) {
return new SampleElements<Map.Entry<K, V>>(
- Helpers.mapEntry(keys.e0, values.e0),
- Helpers.mapEntry(keys.e1, values.e1),
- Helpers.mapEntry(keys.e2, values.e2),
- Helpers.mapEntry(keys.e3, values.e3),
- Helpers.mapEntry(keys.e4, values.e4));
+ Helpers.mapEntry(keys.e0(), values.e0()),
+ Helpers.mapEntry(keys.e1(), values.e1()),
+ Helpers.mapEntry(keys.e2(), values.e2()),
+ Helpers.mapEntry(keys.e3(), values.e3()),
+ Helpers.mapEntry(keys.e4(), values.e4()));
+ }
+
+ public E e0() {
+ return e0;
+ }
+
+ public E e1() {
+ return e1;
+ }
+
+ public E e2() {
+ return e2;
+ }
+
+ public E e3() {
+ return e3;
+ }
+
+ public E e4() {
+ return e4;
}
public static class Unhashables extends SampleElements<UnhashableObject> {
diff --git a/guava-testlib/src/com/google/common/collect/testing/SetTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/SetTestSuiteBuilder.java
index 7437760..321dd5f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/SetTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/SetTestSuiteBuilder.java
@@ -16,7 +16,9 @@
package com.google.common.collect.testing;
-import com.google.common.collect.testing.features.CollectionFeature;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS;
+
import com.google.common.collect.testing.features.Feature;
import com.google.common.collect.testing.testers.CollectionSerializationEqualTester;
import com.google.common.collect.testing.testers.SetAddAllTester;
@@ -74,7 +76,7 @@ public class SetTestSuiteBuilder<E>
List<TestSuite> derivedSuites = new ArrayList<TestSuite>(
super.createDerivedSuites(parentBuilder));
- if (parentBuilder.getFeatures().contains(CollectionFeature.SERIALIZABLE)) {
+ if (parentBuilder.getFeatures().contains(SERIALIZABLE)) {
derivedSuites.add(SetTestSuiteBuilder
.using(new ReserializedSetGenerator<E>(parentBuilder.getSubjectGenerator()))
.named(getName() + " reserialized")
@@ -117,8 +119,8 @@ public class SetTestSuiteBuilder<E>
Set<Feature<?>> features) {
Set<Feature<?>> derivedFeatures = new HashSet<Feature<?>>();
derivedFeatures.addAll(features);
- derivedFeatures.remove(CollectionFeature.SERIALIZABLE);
- derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS);
+ derivedFeatures.remove(SERIALIZABLE);
+ derivedFeatures.remove(SERIALIZABLE_INCLUDING_VIEWS);
return derivedFeatures;
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/SortedMapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/SortedMapTestSuiteBuilder.java
index f5cad51..82ef33b 100644
--- a/guava-testlib/src/com/google/common/collect/testing/SortedMapTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/SortedMapTestSuiteBuilder.java
@@ -16,9 +16,10 @@
package com.google.common.collect.testing;
+import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
+
import com.google.common.collect.testing.DerivedCollectionGenerators.Bound;
import com.google.common.collect.testing.DerivedCollectionGenerators.SortedMapSubmapTestMapGenerator;
-import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.Feature;
import com.google.common.collect.testing.testers.SortedMapNavigationTester;
@@ -50,9 +51,9 @@ public class SortedMapTestSuiteBuilder<K, V> extends MapTestSuiteBuilder<K, V> {
}
@Override public TestSuite createTestSuite() {
- if (!getFeatures().contains(CollectionFeature.KNOWN_ORDER)) {
+ if (!getFeatures().contains(KNOWN_ORDER)) {
List<Feature<?>> features = Helpers.copyToList(getFeatures());
- features.add(CollectionFeature.KNOWN_ORDER);
+ features.add(KNOWN_ORDER);
withFeatures(features);
}
return super.createTestSuite();
diff --git a/guava-testlib/src/com/google/common/collect/testing/TestsForMapsInJavaUtil.java b/guava-testlib/src/com/google/common/collect/testing/TestsForMapsInJavaUtil.java
index 72db7f6..e28e8ef 100644
--- a/guava-testlib/src/com/google/common/collect/testing/TestsForMapsInJavaUtil.java
+++ b/guava-testlib/src/com/google/common/collect/testing/TestsForMapsInJavaUtil.java
@@ -247,10 +247,9 @@ public class TestsForMapsInJavaUtil {
}
public Test testsForConcurrentHashMap() {
- return MapTestSuiteBuilder
+ return ConcurrentMapTestSuiteBuilder
.using(new TestStringMapGenerator() {
- @Override protected Map<String, String> create(
- Entry<String, String>[] entries) {
+ @Override protected Map<String, String> create(Entry<String, String>[] entries) {
return populate(new ConcurrentHashMap<String, String>(), entries);
}
})
@@ -265,7 +264,7 @@ public class TestsForMapsInJavaUtil {
}
public Test testsForConcurrentSkipListMapNatural() {
- return NavigableMapTestSuiteBuilder
+ return ConcurrentNavigableMapTestSuiteBuilder
.using(new TestStringSortedMapGenerator() {
@Override protected SortedMap<String, String> create(
Entry<String, String>[] entries) {
@@ -284,7 +283,7 @@ public class TestsForMapsInJavaUtil {
}
public Test testsForConcurrentSkipListMapWithComparator() {
- return NavigableMapTestSuiteBuilder
+ return ConcurrentNavigableMapTestSuiteBuilder
.using(new TestStringSortedMapGenerator() {
@Override protected SortedMap<String, String> create(
Entry<String, String>[] entries) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/features/FeatureUtil.java b/guava-testlib/src/com/google/common/collect/testing/features/FeatureUtil.java
index 491fe08..cb18aa1 100644
--- a/guava-testlib/src/com/google/common/collect/testing/features/FeatureUtil.java
+++ b/guava-testlib/src/com/google/common/collect/testing/features/FeatureUtil.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -233,9 +234,9 @@ public class FeatureUtil {
Set<Feature<?>> conflictingFeatures =
intersection(allPresentFeatures, allAbsentFeatures);
if (!conflictingFeatures.isEmpty()) {
- throw new ConflictingRequirementsException("Annotation explicitly or " +
- "implicitly requires one or more features to be both present " +
- "and absent.",
+ throw new ConflictingRequirementsException("Annotation explicitly or "
+ + "implicitly requires one or more features to be both present "
+ + "and absent.",
conflictingFeatures, testerAnnotation);
}
return new TesterRequirements(allPresentFeatures, allAbsentFeatures);
@@ -278,9 +279,9 @@ public class FeatureUtil {
Set<Feature<?>> conflictingFeatures;
conflictingFeatures = intersection(newFeatures, earlierFeatures);
if (!conflictingFeatures.isEmpty()) {
- throw new ConflictingRequirementsException(String.format(
- "Annotation requires to be %s features that earlier " +
- "annotations required to be %s.",
+ throw new ConflictingRequirementsException(String.format(Locale.ROOT,
+ "Annotation requires to be %s features that earlier "
+ + "annotations required to be %s.",
newRequirement, earlierRequirement),
conflictingFeatures, source);
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/AbstractListMultimapTester.java b/guava-testlib/src/com/google/common/collect/testing/google/AbstractListMultimapTester.java
index acf973c..1f30f24 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/AbstractListMultimapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/AbstractListMultimapTester.java
@@ -14,7 +14,7 @@
package com.google.common.collect.testing.google;
-import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.collect.testing.Helpers.assertEqualInOrder;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.ListMultimap;
@@ -36,13 +36,13 @@ public class AbstractListMultimapTester<K, V>
}
protected void assertGet(K key, Collection<V> values) {
- assertThat(multimap().get(key)).has().exactlyAs(values).inOrder();
+ assertEqualInOrder(values, multimap().get(key));
if (!values.isEmpty()) {
- assertThat(multimap().asMap().get(key)).has().exactlyAs(values).inOrder();
+ assertEqualInOrder(values, multimap().asMap().get(key));
assertFalse(multimap().isEmpty());
} else {
- assertThat(multimap().asMap().get(key)).isNull();
+ assertNull(multimap().asMap().get(key));
}
assertEquals(values.size(), multimap().get(key).size());
@@ -51,4 +51,3 @@ public class AbstractListMultimapTester<K, V>
assertEquals(values.size() > 0, multimap().keys().contains(key));
}
}
-
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultimapTester.java b/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultimapTester.java
index f307c36..80074e7 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultimapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultimapTester.java
@@ -16,7 +16,7 @@
package com.google.common.collect.testing.google;
-import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Multimap;
@@ -145,21 +145,59 @@ public abstract class AbstractMultimapTester<K, V, M extends Multimap<K, V>>
}
protected void assertGet(K key, Collection<V> values) {
- assertThat(multimap().get(key)).has().exactlyAs(values);
+ assertEqualIgnoringOrder(values, multimap().get(key));
if (!values.isEmpty()) {
- assertThat(multimap().asMap().get(key)).has().exactlyAs(values);
+ assertEqualIgnoringOrder(values, multimap().asMap().get(key));
assertFalse(multimap().isEmpty());
} else {
- assertThat(multimap().asMap().get(key)).isNull();
+ assertNull(multimap().asMap().get(key));
}
- // TODO(user): Add proper overrides to prevent autoboxing.
- // Truth+autoboxing == compile error. Cast int to long to fix:
- assertThat(multimap().get(key).size()).isEqualTo((long) values.size());
+ assertEquals(values.size(), multimap().get(key).size());
assertEquals(values.size() > 0, multimap().containsKey(key));
assertEquals(values.size() > 0, multimap().keySet().contains(key));
assertEquals(values.size() > 0, multimap().keys().contains(key));
}
+
+ protected final K k0() {
+ return e0().getKey();
+ }
+
+ protected final V v0() {
+ return e0().getValue();
+ }
+
+ protected final K k1() {
+ return e1().getKey();
+ }
+
+ protected final V v1() {
+ return e1().getValue();
+ }
+
+ protected final K k2() {
+ return e2().getKey();
+ }
+
+ protected final V v2() {
+ return e2().getValue();
+ }
+
+ protected final K k3() {
+ return e3().getKey();
+ }
+
+ protected final V v3() {
+ return e3().getValue();
+ }
+
+ protected final K k4() {
+ return e4().getKey();
+ }
+
+ protected final V v4() {
+ return e4().getValue();
+ }
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java b/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java
index 25772a3..3f33a1a 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetSetCountTester.java
@@ -112,16 +112,16 @@ public abstract class AbstractMultisetSetCountTester<E>
// Unconditional setCount no-ops.
private void assertZeroToZero() {
- assertSetCount(samples.e3, 0);
+ assertSetCount(e3(), 0);
}
private void assertOneToOne() {
- assertSetCount(samples.e0, 1);
+ assertSetCount(e0(), 1);
}
private void assertThreeToThree() {
initThreeCopies();
- assertSetCount(samples.e0, 3);
+ assertSetCount(e0(), 3);
}
@CollectionFeature.Require(SUPPORTS_ADD)
@@ -188,7 +188,7 @@ public abstract class AbstractMultisetSetCountTester<E>
@CollectionFeature.Require(SUPPORTS_ADD)
public void testSetCount_zeroToOne_supported() {
- assertSetCount(samples.e3, 1);
+ assertSetCount(e3(), 1);
}
@CollectionFeature.Require({SUPPORTS_ADD,
@@ -196,7 +196,7 @@ public abstract class AbstractMultisetSetCountTester<E>
public void testSetCountZeroToOneConcurrentWithIteration() {
try {
Iterator<E> iterator = collection.iterator();
- assertSetCount(samples.e3, 1);
+ assertSetCount(e3(), 1);
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -209,7 +209,7 @@ public abstract class AbstractMultisetSetCountTester<E>
public void testSetCountZeroToOneConcurrentWithEntrySetIteration() {
try {
Iterator<Entry<E>> iterator = getMultiset().entrySet().iterator();
- assertSetCount(samples.e3, 1);
+ assertSetCount(e3(), 1);
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -219,29 +219,29 @@ public abstract class AbstractMultisetSetCountTester<E>
@CollectionFeature.Require(SUPPORTS_ADD)
public void testSetCount_zeroToThree_supported() {
- assertSetCount(samples.e3, 3);
+ assertSetCount(e3(), 3);
}
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require(SUPPORTS_ADD)
public void testSetCount_oneToThree_supported() {
- assertSetCount(samples.e0, 3);
+ assertSetCount(e0(), 3);
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
public void testSetCount_zeroToOne_unsupported() {
- assertSetCountIncreasingFailure(samples.e3, 1);
+ assertSetCountIncreasingFailure(e3(), 1);
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
public void testSetCount_zeroToThree_unsupported() {
- assertSetCountIncreasingFailure(samples.e3, 3);
+ assertSetCountIncreasingFailure(e3(), 3);
}
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require(absent = SUPPORTS_ADD)
public void testSetCount_oneToThree_unsupported() {
- assertSetCountIncreasingFailure(samples.e3, 3);
+ assertSetCountIncreasingFailure(e3(), 3);
}
// Unconditional setCount size decreases:
@@ -249,7 +249,7 @@ public abstract class AbstractMultisetSetCountTester<E>
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testSetCount_oneToZero_supported() {
- assertSetCount(samples.e0, 0);
+ assertSetCount(e0(), 0);
}
@CollectionFeature.Require({SUPPORTS_REMOVE,
@@ -258,7 +258,7 @@ public abstract class AbstractMultisetSetCountTester<E>
public void testSetCountOneToZeroConcurrentWithIteration() {
try {
Iterator<E> iterator = collection.iterator();
- assertSetCount(samples.e0, 0);
+ assertSetCount(e0(), 0);
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -272,7 +272,7 @@ public abstract class AbstractMultisetSetCountTester<E>
public void testSetCountOneToZeroConcurrentWithEntrySetIteration() {
try {
Iterator<Entry<E>> iterator = getMultiset().entrySet().iterator();
- assertSetCount(samples.e0, 0);
+ assertSetCount(e0(), 0);
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -284,34 +284,34 @@ public abstract class AbstractMultisetSetCountTester<E>
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testSetCount_threeToZero_supported() {
initThreeCopies();
- assertSetCount(samples.e0, 0);
+ assertSetCount(e0(), 0);
}
@CollectionSize.Require(SEVERAL)
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testSetCount_threeToOne_supported() {
initThreeCopies();
- assertSetCount(samples.e0, 1);
+ assertSetCount(e0(), 1);
}
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
public void testSetCount_oneToZero_unsupported() {
- assertSetCountDecreasingFailure(samples.e0, 0);
+ assertSetCountDecreasingFailure(e0(), 0);
}
@CollectionSize.Require(SEVERAL)
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
public void testSetCount_threeToZero_unsupported() {
initThreeCopies();
- assertSetCountDecreasingFailure(samples.e0, 0);
+ assertSetCountDecreasingFailure(e0(), 0);
}
@CollectionSize.Require(SEVERAL)
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
public void testSetCount_threeToOne_unsupported() {
initThreeCopies();
- assertSetCountDecreasingFailure(samples.e0, 1);
+ assertSetCountDecreasingFailure(e0(), 1);
}
// setCount with nulls:
@@ -370,7 +370,7 @@ public abstract class AbstractMultisetSetCountTester<E>
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testSetCount_negative_removeSupported() {
try {
- setCountNoCheckReturnValue(samples.e3, -1);
+ setCountNoCheckReturnValue(e3(), -1);
fail("calling setCount() with a negative count should throw "
+ "IllegalArgumentException");
} catch (IllegalArgumentException expected) {
@@ -380,7 +380,7 @@ public abstract class AbstractMultisetSetCountTester<E>
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
public void testSetCount_negative_removeUnsupported() {
try {
- setCountNoCheckReturnValue(samples.e3, -1);
+ setCountNoCheckReturnValue(e3(), -1);
fail("calling setCount() with a negative count should throw "
+ "IllegalArgumentException or UnsupportedOperationException");
} catch (IllegalArgumentException expected) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetTester.java
index c4317d1..f9c4f52 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/AbstractMultisetTester.java
@@ -33,6 +33,6 @@ public class AbstractMultisetTester<E> extends AbstractCollectionTester<E> {
protected void initThreeCopies() {
collection =
- getSubjectGenerator().create(samples.e0, samples.e0, samples.e0);
+ getSubjectGenerator().create(e0(), e0(), e0());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/BiMapGenerators.java b/guava-testlib/src/com/google/common/collect/testing/google/BiMapGenerators.java
index fc850e5..eb055fe 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/BiMapGenerators.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/BiMapGenerators.java
@@ -21,6 +21,7 @@ import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.Maps;
+import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
@@ -52,4 +53,10 @@ public class BiMapGenerators {
return ImmutableBiMap.copyOf(builder);
}
}
+
+ public static class ImmutableBiMapCopyOfEntriesGenerator extends TestStringBiMapGenerator {
+ @Override protected BiMap<String, String> create(Entry<String, String>[] entries) {
+ return ImmutableBiMap.copyOf(Arrays.asList(entries));
+ }
+ }
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/BiMapPutTester.java b/guava-testlib/src/com/google/common/collect/testing/google/BiMapPutTester.java
index 8c31aa3..1f017e6 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/BiMapPutTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/BiMapPutTester.java
@@ -34,66 +34,53 @@ public class BiMapPutTester<K, V> extends AbstractBiMapTester<K, V> {
@MapFeature.Require(SUPPORTS_PUT)
@CollectionSize.Require(ZERO)
public void testPutWithSameValueFails() {
- K k0 = samples.e0.getKey();
- K k1 = samples.e1.getKey();
- V v0 = samples.e0.getValue();
- getMap().put(k0, v0);
+ getMap().put(k0(), v0());
try {
- getMap().put(k1, v0);
+ getMap().put(k1(), v0());
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {
// success
}
// verify that the bimap is unchanged
- expectAdded(samples.e0);
+ expectAdded(e0());
}
@SuppressWarnings("unchecked")
@MapFeature.Require(SUPPORTS_PUT)
@CollectionSize.Require(ZERO)
public void testPutPresentKeyDifferentValue() {
- K k0 = samples.e0.getKey();
- V v0 = samples.e0.getValue();
- V v1 = samples.e1.getValue();
- getMap().put(k0, v0);
- getMap().put(k0, v1);
+ getMap().put(k0(), v0());
+ getMap().put(k0(), v1());
// verify that the bimap is changed, and that the old inverse mapping
// from v1 -> v0 is deleted
- expectContents(Helpers.mapEntry(k0, v1));
+ expectContents(Helpers.mapEntry(k0(), v1()));
}
@SuppressWarnings("unchecked")
@MapFeature.Require(SUPPORTS_PUT)
@CollectionSize.Require(ZERO)
public void putDistinctKeysDistinctValues() {
- getMap().put(samples.e0.getKey(), samples.e0.getValue());
- getMap().put(samples.e1.getKey(), samples.e1.getValue());
- expectAdded(samples.e0, samples.e1);
+ getMap().put(k0(), v0());
+ getMap().put(k1(), v1());
+ expectAdded(e0(), e1());
}
@SuppressWarnings("unchecked")
@MapFeature.Require(SUPPORTS_PUT)
@CollectionSize.Require(ZERO)
public void testForcePutOverwritesOldValueEntry() {
- K k0 = samples.e0.getKey();
- K k1 = samples.e1.getKey();
- V v0 = samples.e0.getValue();
- getMap().put(k0, v0);
- getMap().forcePut(k1, v0);
+ getMap().put(k0(), v0());
+ getMap().forcePut(k1(), v0());
// verify that the bimap is unchanged
- expectAdded(Helpers.mapEntry(k1, v0));
+ expectAdded(Helpers.mapEntry(k1(), v0()));
}
@SuppressWarnings("unchecked")
@MapFeature.Require(SUPPORTS_PUT)
@CollectionSize.Require(ZERO)
public void testInversePut() {
- K k0 = samples.e0.getKey();
- V v0 = samples.e0.getValue();
- K k1 = samples.e1.getKey();
- V v1 = samples.e1.getValue();
- getMap().put(k0, v0);
- getMap().inverse().put(v1, k1);
- expectAdded(samples.e0, samples.e1);
+ getMap().put(k0(), v0());
+ getMap().inverse().put(v1(), k1());
+ expectAdded(e0(), e1());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/BiMapRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/google/BiMapRemoveTester.java
index 4f875a0..8ba0ede 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/BiMapRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/BiMapRemoveTester.java
@@ -38,48 +38,48 @@ public class BiMapRemoveTester<K, V> extends AbstractBiMapTester<K, V> {
@MapFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(absent = ZERO)
public void testRemoveKeyRemovesFromInverse() {
- getMap().remove(samples.e0.getKey());
- expectMissing(samples.e0);
+ getMap().remove(k0());
+ expectMissing(e0());
}
@SuppressWarnings("unchecked")
@MapFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(absent = ZERO)
public void testRemoveKeyFromKeySetRemovesFromInverse() {
- getMap().keySet().remove(samples.e0.getKey());
- expectMissing(samples.e0);
+ getMap().keySet().remove(k0());
+ expectMissing(e0());
}
@SuppressWarnings("unchecked")
@MapFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(absent = ZERO)
public void testRemoveFromValuesRemovesFromInverse() {
- getMap().values().remove(samples.e0.getValue());
- expectMissing(samples.e0);
+ getMap().values().remove(v0());
+ expectMissing(e0());
}
@SuppressWarnings("unchecked")
@MapFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(absent = ZERO)
public void testRemoveFromInverseRemovesFromForward() {
- getMap().inverse().remove(samples.e0.getValue());
- expectMissing(samples.e0);
+ getMap().inverse().remove(v0());
+ expectMissing(e0());
}
@SuppressWarnings("unchecked")
@MapFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(absent = ZERO)
public void testRemoveFromInverseKeySetRemovesFromForward() {
- getMap().inverse().keySet().remove(samples.e0.getValue());
- expectMissing(samples.e0);
+ getMap().inverse().keySet().remove(v0());
+ expectMissing(e0());
}
@SuppressWarnings("unchecked")
@MapFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(absent = ZERO)
public void testRemoveFromInverseValuesRemovesFromInverse() {
- getMap().inverse().values().remove(samples.e0.getKey());
- expectMissing(samples.e0);
+ getMap().inverse().values().remove(k0());
+ expectMissing(e0());
}
@CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/BiMapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/google/BiMapTestSuiteBuilder.java
index 037231b..67d0fea 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/BiMapTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/BiMapTestSuiteBuilder.java
@@ -135,7 +135,7 @@ public class BiMapTestSuiteBuilder<K, V>
return inverseFeatures;
}
- // TODO(user): can we eliminate the duplication from MapTestSuiteBuilder here?
+ // TODO(lowasser): can we eliminate the duplication from MapTestSuiteBuilder here?
private static Set<Feature<?>> computeValuesSetFeatures(
Set<Feature<?>> mapFeatures) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/DerivedGoogleCollectionGenerators.java b/guava-testlib/src/com/google/common/collect/testing/google/DerivedGoogleCollectionGenerators.java
index e385bf9..9dec389 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/DerivedGoogleCollectionGenerators.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/DerivedGoogleCollectionGenerators.java
@@ -100,8 +100,8 @@ public final class DerivedGoogleCollectionGenerators {
@Override
public SampleElements<Map.Entry<V, K>> samples() {
SampleElements<Entry<K, V>> samples = generator.samples();
- return new SampleElements<Map.Entry<V, K>>(reverse(samples.e0), reverse(samples.e1),
- reverse(samples.e2), reverse(samples.e3), reverse(samples.e4));
+ return new SampleElements<Map.Entry<V, K>>(reverse(samples.e0()), reverse(samples.e1()),
+ reverse(samples.e2()), reverse(samples.e3()), reverse(samples.e4()));
}
private Map.Entry<V, K> reverse(Map.Entry<K, V> entry) {
@@ -158,11 +158,11 @@ public final class DerivedGoogleCollectionGenerators {
final SampleElements<Map.Entry<K, V>> mapSamples =
this.mapGenerator.samples();
this.samples = new SampleElements<V>(
- mapSamples.e0.getValue(),
- mapSamples.e1.getValue(),
- mapSamples.e2.getValue(),
- mapSamples.e3.getValue(),
- mapSamples.e4.getValue());
+ mapSamples.e0().getValue(),
+ mapSamples.e1().getValue(),
+ mapSamples.e2().getValue(),
+ mapSamples.e3().getValue(),
+ mapSamples.e4().getValue());
}
@Override
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/GoogleHelpers.java
similarity index 61%
copy from guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java
copy to guava-testlib/src/com/google/common/collect/testing/google/GoogleHelpers.java
index ee703d8..cf856fa 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/GoogleHelpers.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,20 +16,24 @@
package com.google.common.collect.testing.google;
+import static junit.framework.Assert.fail;
+
import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.SortedSetMultimap;
+import com.google.common.collect.Multimap;
/**
- * Tester for {@link SortedSetMultimap#get(Object)}.
+ * Helper methods/assertions for use with {@code com.google.common.collect} types.
*
- * @author Louis Wasserman
+ * @author Colin Decker
*/
@GwtCompatible
-public class SortedSetMultimapGetTester<K, V>
- extends AbstractMultimapTester<K, V, SortedSetMultimap<K, V>> {
- public void testValueComparator() {
- assertEquals(
- multimap().valueComparator(),
- multimap().get(sampleKeys().e0).comparator());
+final class GoogleHelpers {
+
+ private GoogleHelpers() {}
+
+ static void assertEmpty(Multimap<?, ?> multimap) {
+ if (!multimap.isEmpty()) {
+ fail("Not true that " + multimap + " is empty");
+ }
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapAsMapTester.java b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapAsMapTester.java
index ab18c2c..bd3b11d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapAsMapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapAsMapTester.java
@@ -67,12 +67,12 @@ public class ListMultimapAsMapTester<K, V> extends AbstractListMultimapTester<K,
@CollectionSize.Require(SEVERAL)
public void testEquals() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e1, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k1(), v0()),
+ Helpers.mapEntry(k0(), v3()));
Map<K, Collection<V>> expected = Maps.newHashMap();
- expected.put(sampleKeys().e0, Lists.newArrayList(sampleValues().e0, sampleValues().e3));
- expected.put(sampleKeys().e1, Lists.newArrayList(sampleValues().e0));
+ expected.put(k0(), Lists.newArrayList(v0(), v3()));
+ expected.put(k1(), Lists.newArrayList(v0()));
new EqualsTester()
.addEqualityGroup(expected, multimap().asMap())
.testEquals();
@@ -81,16 +81,16 @@ public class ListMultimapAsMapTester<K, V> extends AbstractListMultimapTester<K,
@CollectionSize.Require(SEVERAL)
public void testEntrySetEquals() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e1, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k1(), v0()),
+ Helpers.mapEntry(k0(), v3()));
Set<Entry<K, Collection<V>>> expected = Sets.newHashSet();
expected.add(Helpers.mapEntry(
- sampleKeys().e0,
- (Collection<V>) Lists.newArrayList(sampleValues().e0, sampleValues().e3)));
+ k0(),
+ (Collection<V>) Lists.newArrayList(v0(), v3())));
expected.add(Helpers.mapEntry(
- sampleKeys().e1,
- (Collection<V>) Lists.newArrayList(sampleValues().e0)));
+ k1(),
+ (Collection<V>) Lists.newArrayList(v0())));
new EqualsTester()
.addEqualityGroup(expected, multimap().asMap().entrySet())
.testEquals();
@@ -100,14 +100,14 @@ public class ListMultimapAsMapTester<K, V> extends AbstractListMultimapTester<K,
@MapFeature.Require(SUPPORTS_REMOVE)
public void testValuesRemove() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e1, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
- assertTrue(multimap().asMap().values().remove(Collections.singletonList(sampleValues().e0)));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k1(), v0()),
+ Helpers.mapEntry(k0(), v3()));
+ assertTrue(multimap().asMap().values().remove(Collections.singletonList(v0())));
assertEquals(2, multimap().size());
assertEquals(
Collections.singletonMap(
- sampleKeys().e0, Lists.newArrayList(sampleValues().e0, sampleValues().e3)),
+ k0(), Lists.newArrayList(v0(), v3())),
multimap().asMap());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapEqualsTester.java b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapEqualsTester.java
index 31c4611..3b22a0c 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapEqualsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapEqualsTester.java
@@ -32,13 +32,13 @@ public class ListMultimapEqualsTester<K, V> extends AbstractListMultimapTester<K
@CollectionSize.Require(SEVERAL)
public void testOrderingAffectsEqualsComparisons() {
ListMultimap<K, V> multimap1 = getSubjectGenerator().create(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v1()),
+ Helpers.mapEntry(k0(), v0()));
ListMultimap<K, V> multimap2 = getSubjectGenerator().create(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0));
+ Helpers.mapEntry(k0(), v1()),
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v0()));
new EqualsTester()
.addEqualityGroup(multimap1)
.addEqualityGroup(multimap2)
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapPutAllTester.java b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapPutAllTester.java
index 9a3c966..4cf0d04 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapPutAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapPutAllTester.java
@@ -35,9 +35,9 @@ public class ListMultimapPutAllTester<K, V> extends AbstractListMultimapTester<K
public void testPutAllAddsAtEndInOrder() {
@SuppressWarnings("unchecked")
List<V> values = Arrays.asList(
- sampleValues().e3,
- sampleValues().e1,
- sampleValues().e4);
+ v3(),
+ v1(),
+ v4());
for (K k : sampleKeys()) {
resetContainer();
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapRemoveTester.java
index e84e4bb..eb8d190 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapRemoveTester.java
@@ -14,11 +14,11 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertContentsInOrder;
import static com.google.common.collect.testing.Helpers.copyToList;
import static com.google.common.collect.testing.Helpers.mapEntry;
import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.ListMultimap;
@@ -41,33 +41,27 @@ public class ListMultimapRemoveTester<K, V> extends AbstractListMultimapTester<K
@MapFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(SEVERAL)
public void testMultimapRemoveDeletesFirstOccurrence() {
- K k = sampleKeys().e0;
- V v0 = sampleValues().e0;
- V v1 = sampleValues().e2;
- resetContainer(mapEntry(k, v0), mapEntry(k, v1), mapEntry(k, v0));
-
- List<V> list = multimap().get(k);
- multimap().remove(k, v0);
- assertThat(list).has().exactly(v1, v0).inOrder();
+ resetContainer(mapEntry(k0(), v0()), mapEntry(k0(), v1()), mapEntry(k0(), v0()));
+
+ List<V> list = multimap().get(k0());
+ multimap().remove(k0(), v0());
+ assertContentsInOrder(list, v1(), v0());
}
@SuppressWarnings("unchecked")
@MapFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(SEVERAL)
public void testRemoveAtIndexFromGetPropagates() {
- K k = sampleKeys().e0;
- V v0 = sampleValues().e0;
- V v1 = sampleValues().e2;
- List<V> values = Arrays.asList(v0, v1, v0);
+ List<V> values = Arrays.asList(v0(), v1(), v0());
for (int i = 0; i < 3; i++) {
- resetContainer(mapEntry(k, v0), mapEntry(k, v1), mapEntry(k, v0));
+ resetContainer(mapEntry(k0(), v0()), mapEntry(k0(), v1()), mapEntry(k0(), v0()));
List<V> expectedValues = copyToList(values);
- multimap().get(k).remove(i);
+ multimap().get(k0()).remove(i);
expectedValues.remove(i);
- assertGet(k, expectedValues);
+ assertGet(k0(), expectedValues);
}
}
@@ -75,20 +69,17 @@ public class ListMultimapRemoveTester<K, V> extends AbstractListMultimapTester<K
@MapFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(SEVERAL)
public void testRemoveAtIndexFromAsMapPropagates() {
- K k = sampleKeys().e0;
- V v0 = sampleValues().e0;
- V v1 = sampleValues().e2;
- List<V> values = Arrays.asList(v0, v1, v0);
+ List<V> values = Arrays.asList(v0(), v1(), v0());
for (int i = 0; i < 3; i++) {
- resetContainer(mapEntry(k, v0), mapEntry(k, v1), mapEntry(k, v0));
+ resetContainer(mapEntry(k0(), v0()), mapEntry(k0(), v1()), mapEntry(k0(), v0()));
List<V> expectedValues = copyToList(values);
- List<V> asMapValue = (List<V>) multimap().asMap().get(k);
+ List<V> asMapValue = (List<V>) multimap().asMap().get(k0());
asMapValue.remove(i);
expectedValues.remove(i);
- assertGet(k, expectedValues);
+ assertGet(k0(), expectedValues);
}
}
@@ -96,13 +87,10 @@ public class ListMultimapRemoveTester<K, V> extends AbstractListMultimapTester<K
@MapFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(SEVERAL)
public void testRemoveAtIndexFromAsMapEntrySetPropagates() {
- K k = sampleKeys().e0;
- V v0 = sampleValues().e0;
- V v1 = sampleValues().e2;
- List<V> values = Arrays.asList(v0, v1, v0);
+ List<V> values = Arrays.asList(v0(), v1(), v0());
for (int i = 0; i < 3; i++) {
- resetContainer(mapEntry(k, v0), mapEntry(k, v1), mapEntry(k, v0));
+ resetContainer(mapEntry(k0(), v0()), mapEntry(k0(), v1()), mapEntry(k0(), v0()));
List<V> expectedValues = copyToList(values);
Map.Entry<K, Collection<V>> asMapEntry = multimap().asMap().entrySet().iterator().next();
@@ -110,7 +98,7 @@ public class ListMultimapRemoveTester<K, V> extends AbstractListMultimapTester<K
asMapValue.remove(i);
expectedValues.remove(i);
- assertGet(k, expectedValues);
+ assertGet(k0(), expectedValues);
}
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapReplaceValuesTester.java b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapReplaceValuesTester.java
index b7551af..640b256 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapReplaceValuesTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/ListMultimapReplaceValuesTester.java
@@ -35,9 +35,9 @@ public class ListMultimapReplaceValuesTester<K, V> extends AbstractListMultimapT
public void testReplaceValuesPreservesOrder() {
@SuppressWarnings("unchecked")
List<V> values = Arrays.asList(
- sampleValues().e3,
- sampleValues().e1,
- sampleValues().e4);
+ v3(),
+ v1(),
+ v4());
for (K k : sampleKeys()) {
resetContainer();
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MapGenerators.java b/guava-testlib/src/com/google/common/collect/testing/google/MapGenerators.java
index 090eed9..b71ae5b 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MapGenerators.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MapGenerators.java
@@ -31,6 +31,7 @@ import com.google.common.collect.testing.TestStringMapGenerator;
import com.google.common.collect.testing.TestUnhashableCollectionGenerator;
import com.google.common.collect.testing.UnhashableObject;
+import java.util.Arrays;
import java.util.Collection;
import java.util.EnumMap;
import java.util.List;
@@ -66,6 +67,13 @@ public class MapGenerators {
return ImmutableMap.copyOf(builder);
}
}
+
+ public static class ImmutableMapCopyOfEntriesGenerator
+ extends TestStringMapGenerator {
+ @Override protected Map<String, String> create(Entry<String, String>[] entries) {
+ return ImmutableMap.copyOf(Arrays.asList(entries));
+ }
+ }
public static class ImmutableMapUnhashableValuesGenerator
extends TestUnhashableCollectionGenerator<Collection<UnhashableObject>> {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapGetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapGetTester.java
index 88e576e..da5fbb5 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapGetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapGetTester.java
@@ -16,13 +16,14 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertContentsAnyOrder;
+import static com.google.common.collect.testing.Helpers.assertEmpty;
import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Multimap;
@@ -39,56 +40,56 @@ import java.util.Collection;
*/
@GwtCompatible
public class MultimapAsMapGetTester<K, V> extends AbstractMultimapTester<K, V, Multimap<K, V>> {
-
+
@CollectionSize.Require(SEVERAL)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testPropagatesRemoveToMultimap() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e2));
- Collection<V> result = multimap().asMap().get(sampleKeys().e0);
- assertTrue(result.remove(sampleValues().e0));
- assertFalse(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v3()),
+ Helpers.mapEntry(k0(), v2()));
+ Collection<V> result = multimap().asMap().get(k0());
+ assertTrue(result.remove(v0()));
+ assertFalse(multimap().containsEntry(k0(), v0()));
assertEquals(2, multimap().size());
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testPropagatesRemoveLastElementToMultimap() {
- Collection<V> result = multimap().asMap().get(sampleKeys().e0);
- assertTrue(result.remove(sampleValues().e0));
- assertGet(sampleKeys().e0);
+ Collection<V> result = multimap().asMap().get(k0());
+ assertTrue(result.remove(v0()));
+ assertGet(k0());
}
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testPropagatesClearToMultimap() {
- Collection<V> result = multimap().asMap().get(sampleKeys().e0);
+ Collection<V> result = multimap().asMap().get(k0());
result.clear();
- assertGet(sampleKeys().e0);
- assertThat(result).isEmpty();
+ assertGet(k0());
+ assertEmpty(result);
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
public void testAddNullValue() {
- Collection<V> result = multimap().asMap().get(sampleKeys().e0);
+ Collection<V> result = multimap().asMap().get(k0());
assertTrue(result.add(null));
- assertTrue(multimap().containsEntry(sampleKeys().e0, null));
+ assertTrue(multimap().containsEntry(k0(), null));
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUE_QUERIES})
public void testRemoveNullValue() {
- Collection<V> result = multimap().asMap().get(sampleKeys().e0);
+ Collection<V> result = multimap().asMap().get(k0());
assertFalse(result.remove(null));
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
public void testAddNullValueUnsupported() {
- Collection<V> result = multimap().asMap().get(sampleKeys().e0);
+ Collection<V> result = multimap().asMap().get(k0());
try {
result.add(null);
fail("Expected NullPointerException");
@@ -98,10 +99,11 @@ public class MultimapAsMapGetTester<K, V> extends AbstractMultimapTester<K, V, M
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_PUT)
public void testPropagatesAddToMultimap() {
- Collection<V> result = multimap().asMap().get(sampleKeys().e0);
- result.add(sampleValues().e3);
- assertThat(multimap().get(sampleKeys().e0))
- .has().exactly(sampleValues().e0, sampleValues().e3);
+ Collection<V> result = multimap().asMap().get(k0());
+ result.add(v3());
+ assertContentsAnyOrder(
+ multimap().get(k0()),
+ v0(), v3());
}
@CollectionSize.Require(absent = ZERO)
@@ -109,35 +111,29 @@ public class MultimapAsMapGetTester<K, V> extends AbstractMultimapTester<K, V, M
public void testPropagatesRemoveThenAddToMultimap() {
int oldSize = getNumElements();
- K k0 = sampleKeys().e0;
- V v0 = sampleValues().e0;
-
- Collection<V> result = multimap().asMap().get(k0);
- assertTrue(result.remove(v0));
+ Collection<V> result = multimap().asMap().get(k0());
+ assertTrue(result.remove(v0()));
- assertFalse(multimap().containsKey(k0));
- assertFalse(multimap().containsEntry(k0, v0));
- assertThat(result).isEmpty();
+ assertFalse(multimap().containsKey(k0()));
+ assertFalse(multimap().containsEntry(k0(), v0()));
+ assertEmpty(result);
- V v1 = sampleValues().e1;
- V v2 = sampleValues().e2;
+ assertTrue(result.add(v1()));
+ assertTrue(result.add(v2()));
- assertTrue(result.add(v1));
- assertTrue(result.add(v2));
-
- assertThat(result).has().exactly(v1, v2);
- assertThat(multimap().get(k0)).has().exactly(v1, v2);
- assertTrue(multimap().containsKey(k0));
- assertFalse(multimap().containsEntry(k0, v0));
- assertTrue(multimap().containsEntry(k0, v2));
+ assertContentsAnyOrder(result, v1(), v2());
+ assertContentsAnyOrder(multimap().get(k0()), v1(), v2());
+ assertTrue(multimap().containsKey(k0()));
+ assertFalse(multimap().containsEntry(k0(), v0()));
+ assertTrue(multimap().containsEntry(k0(), v2()));
assertEquals(oldSize + 1, multimap().size());
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testReflectsMultimapRemove() {
- Collection<V> result = multimap().asMap().get(sampleKeys().e0);
- multimap().removeAll(sampleKeys().e0);
- assertThat(result).isEmpty();
+ Collection<V> result = multimap().asMap().get(k0());
+ multimap().removeAll(k0());
+ assertEmpty(result);
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapTester.java
index b18f35b..0d0eb0d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapAsMapTester.java
@@ -14,6 +14,9 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertContentsAnyOrder;
+import static com.google.common.collect.testing.Helpers.assertContentsInOrder;
+import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
@@ -21,7 +24,6 @@ import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEY_QUERIES;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Iterables;
@@ -56,25 +58,24 @@ public class MultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, Mult
Collection<V> collection = multimap().asMap().get(key);
if (expectedValues.isEmpty()) {
- assertThat(collection).isNull();
+ assertNull(collection);
} else {
- assertThat(collection).has().exactlyAs(expectedValues);
+ assertEqualIgnoringOrder(expectedValues, collection);
}
}
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(ALLOWS_NULL_KEYS)
public void testAsMapGetNullKeyPresent() {
initMultimapWithNullKey();
- assertThat(multimap().asMap().get(null)).has().exactly(getValueForNullKey());
+ assertContentsAnyOrder(multimap().asMap().get(null), getValueForNullKey());
}
-
@MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
public void testAsMapGetNullKeyAbsent() {
- assertThat(multimap().asMap().get(null)).isNull();
+ assertNull(multimap().asMap().get(null));
}
-
+
@MapFeature.Require(absent = ALLOWS_NULL_KEY_QUERIES)
public void testAsMapGetNullKeyUnsupported() {
try {
@@ -82,12 +83,12 @@ public class MultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, Mult
fail("Expected NullPointerException");
} catch (NullPointerException expected) {}
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testAsMapRemove() {
- assertThat(multimap().asMap().remove(sampleKeys().e0)).iteratesAs(sampleValues().e0);
- assertGet(sampleKeys().e0);
+ assertContentsInOrder(multimap().asMap().remove(k0()), v0());
+ assertGet(k0());
assertEquals(getNumElements() - 1, multimap().size());
}
@@ -95,27 +96,25 @@ public class MultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, Mult
@MapFeature.Require(SUPPORTS_PUT)
public void testAsMapEntrySetReflectsPutSameKey() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
-
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v3()));
+
Set<Entry<K, Collection<V>>> asMapEntrySet = multimap().asMap().entrySet();
Collection<V> valueCollection = Iterables.getOnlyElement(asMapEntrySet).getValue();
- assertThat(valueCollection)
- .has().exactly(sampleValues().e0, sampleValues().e3);
- assertTrue(multimap().put(sampleKeys().e0, sampleValues().e4));
- assertThat(valueCollection)
- .has().exactly(sampleValues().e0, sampleValues().e3, sampleValues().e4);
+ assertContentsAnyOrder(valueCollection, v0(), v3());
+ assertTrue(multimap().put(k0(), v4()));
+ assertContentsAnyOrder(valueCollection, v0(), v3(), v4());
}
@CollectionSize.Require(SEVERAL)
@MapFeature.Require(SUPPORTS_PUT)
public void testAsMapEntrySetReflectsPutDifferentKey() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
-
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v3()));
+
Set<Entry<K, Collection<V>>> asMapEntrySet = multimap().asMap().entrySet();
- assertTrue(multimap().put(sampleKeys().e1, sampleValues().e4));
+ assertTrue(multimap().put(k1(), v4()));
assertEquals(2, asMapEntrySet.size());
}
@@ -123,22 +122,22 @@ public class MultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, Mult
@MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
public void testAsMapEntrySetRemovePropagatesToMultimap() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v3()));
Set<Entry<K, Collection<V>>> asMapEntrySet = multimap().asMap().entrySet();
Entry<K, Collection<V>> asMapEntry0 = Iterables.getOnlyElement(asMapEntrySet);
- assertTrue(multimap().put(sampleKeys().e1, sampleValues().e4));
+ assertTrue(multimap().put(k1(), v4()));
assertTrue(asMapEntrySet.remove(asMapEntry0));
assertEquals(1, multimap().size());
- assertThat(multimap().keySet()).iteratesAs(sampleKeys().e1);
+ assertContentsInOrder(multimap().keySet(), k1());
}
@CollectionSize.Require(SEVERAL)
@CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
public void testAsMapEntrySetIteratorRemovePropagatesToMultimap() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v3()));
Set<Entry<K, Collection<V>>> asMapEntrySet = multimap().asMap().entrySet();
Iterator<Entry<K, Collection<V>>> asMapEntryItr = asMapEntrySet.iterator();
asMapEntryItr.next();
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapClearTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapClearTester.java
index 5c25fe4..1aa661a 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapClearTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapClearTester.java
@@ -16,9 +16,10 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertEmpty;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.collect.testing.google.GoogleHelpers.assertEmpty;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Multimap;
@@ -47,54 +48,54 @@ public class MultimapClearTester<K, V> extends AbstractMultimapTester<K, V, Mult
private void assertCleared() {
assertEquals(0, multimap().size());
- assertTrue(multimap().isEmpty());
+ assertEmpty(multimap());
assertEquals(multimap(), getSubjectGenerator().create());
- assertThat(multimap().entries()).isEmpty();
- assertThat(multimap().asMap()).isEmpty();
- assertThat(multimap().keySet()).isEmpty();
- assertThat(multimap().keys()).isEmpty();
- assertThat(multimap().values()).isEmpty();
+ assertEmpty(multimap().entries());
+ assertEmpty(multimap().asMap());
+ assertEmpty(multimap().keySet());
+ assertEmpty(multimap().keys());
+ assertEmpty(multimap().values());
for (K key : sampleKeys()) {
assertGet(key);
}
}
-
+
@MapFeature.Require(SUPPORTS_REMOVE)
public void testClear() {
multimap().clear();
assertCleared();
}
-
+
@MapFeature.Require(SUPPORTS_REMOVE)
public void testClearThroughEntries() {
multimap().entries().clear();
assertCleared();
}
-
+
@MapFeature.Require(SUPPORTS_REMOVE)
public void testClearThroughAsMap() {
multimap().asMap().clear();
assertCleared();
}
-
+
@MapFeature.Require(SUPPORTS_REMOVE)
public void testClearThroughKeySet() {
multimap().keySet().clear();
assertCleared();
}
-
+
@MapFeature.Require(SUPPORTS_REMOVE)
public void testClearThroughKeys() {
multimap().keys().clear();
assertCleared();
}
-
+
@MapFeature.Require(SUPPORTS_REMOVE)
public void testClearThroughValues() {
multimap().values().clear();
assertCleared();
}
-
+
@MapFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(absent = ZERO)
public void testClearPropagatesToGet() {
@@ -102,7 +103,7 @@ public class MultimapClearTester<K, V> extends AbstractMultimapTester<K, V, Mult
resetContainer();
Collection<V> collection = multimap().get(key);
multimap().clear();
- assertThat(collection).isEmpty();
+ assertEmpty(collection);
}
}
@@ -114,7 +115,7 @@ public class MultimapClearTester<K, V> extends AbstractMultimapTester<K, V, Mult
Collection<V> collection = multimap().asMap().get(key);
if (collection != null) {
multimap().clear();
- assertThat(collection).isEmpty();
+ assertEmpty(collection);
}
}
}
@@ -123,13 +124,13 @@ public class MultimapClearTester<K, V> extends AbstractMultimapTester<K, V, Mult
public void testClearPropagatesToAsMap() {
Map<K, Collection<V>> asMap = multimap().asMap();
multimap().clear();
- assertThat(asMap).isEmpty();
+ assertEmpty(asMap);
}
@MapFeature.Require(SUPPORTS_REMOVE)
public void testClearPropagatesToEntries() {
Collection<Entry<K, V>> entries = multimap().entries();
multimap().clear();
- assertThat(entries).isEmpty();
+ assertEmpty(entries);
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsEntryTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsEntryTester.java
index 91bcd44..ab65e4c 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsEntryTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsEntryTester.java
@@ -37,11 +37,11 @@ public class MultimapContainsEntryTester<K, V>
extends AbstractMultimapTester<K, V, Multimap<K, V>> {
@CollectionSize.Require(absent = ZERO)
public void testContainsEntryYes() {
- assertTrue(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
+ assertTrue(multimap().containsEntry(k0(), v0()));
}
public void testContainsEntryNo() {
- assertFalse(multimap().containsEntry(sampleKeys().e3, sampleValues().e3));
+ assertFalse(multimap().containsEntry(k3(), v3()));
}
public void testContainsEntryAgreesWithGet() {
@@ -68,7 +68,7 @@ public class MultimapContainsEntryTester<K, V>
@MapFeature.Require(absent = ALLOWS_NULL_KEY_QUERIES)
public void testContainsEntryNullDisallowedBecauseKeyQueriesDisallowed() {
try {
- multimap().containsEntry(null, sampleValues().e3);
+ multimap().containsEntry(null, v3());
fail("Expected NullPointerException");
} catch (NullPointerException expected) {
// success
@@ -82,7 +82,7 @@ public class MultimapContainsEntryTester<K, V>
@MapFeature.Require(absent = ALLOWS_NULL_VALUE_QUERIES)
public void testContainsEntryNullDisallowedBecauseValueQueriesDisallowed() {
try {
- multimap().containsEntry(sampleKeys().e3, null);
+ multimap().containsEntry(k3(), null);
fail("Expected NullPointerException");
} catch (NullPointerException expected) {
// success
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsKeyTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsKeyTester.java
index 958af87..07e69bc 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsKeyTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsKeyTester.java
@@ -35,11 +35,11 @@ public class MultimapContainsKeyTester<K, V>
extends AbstractMultimapTester<K, V, Multimap<K, V>> {
@CollectionSize.Require(absent = ZERO)
public void testContainsKeyYes() {
- assertTrue(multimap().containsKey(sampleKeys().e0));
+ assertTrue(multimap().containsKey(k0()));
}
public void testContainsKeyNo() {
- assertFalse(multimap().containsKey(sampleKeys().e3));
+ assertFalse(multimap().containsKey(k3()));
}
public void testContainsKeysFromKeySet() {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsValueTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsValueTester.java
index 7ccaa41..a201d5f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsValueTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapContainsValueTester.java
@@ -35,11 +35,11 @@ public class MultimapContainsValueTester<K, V>
extends AbstractMultimapTester<K, V, Multimap<K, V>> {
@CollectionSize.Require(absent = ZERO)
public void testContainsValueYes() {
- assertTrue(multimap().containsValue(sampleValues().e0));
+ assertTrue(multimap().containsValue(v0()));
}
public void testContainsValueNo() {
- assertFalse(multimap().containsValue(sampleValues().e3));
+ assertFalse(multimap().containsValue(v3()));
}
@MapFeature.Require(ALLOWS_NULL_VALUES)
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapEntriesTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapEntriesTester.java
index c815631..f51ea75 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapEntriesTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapEntriesTester.java
@@ -14,6 +14,8 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertContains;
+import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
import static com.google.common.collect.testing.features.CollectionSize.ONE;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
@@ -22,7 +24,6 @@ import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Multimap;
@@ -43,79 +44,77 @@ import java.util.Map.Entry;
@GwtCompatible
public class MultimapEntriesTester<K, V> extends AbstractMultimapTester<K, V, Multimap<K, V>> {
public void testEntries() {
- assertThat(multimap().entries()).has().exactlyAs(getSampleElements());
+ assertEqualIgnoringOrder(getSampleElements(), multimap().entries());
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(ALLOWS_NULL_KEYS)
public void testContainsEntryWithNullKeyPresent() {
initMultimapWithNullKey();
- assertThat(multimap().entries()).has().allOf(
- Helpers.mapEntry((K) null, getValueForNullKey()));
+ assertContains(multimap().entries(), Helpers.mapEntry((K) null, getValueForNullKey()));
}
-
+
@MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
public void testContainsEntryWithNullKeyAbsent() {
- assertFalse(multimap().entries().contains(Helpers.mapEntry(null, sampleValues().e0)));
+ assertFalse(multimap().entries().contains(Helpers.mapEntry(null, v0())));
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(ALLOWS_NULL_VALUES)
public void testContainsEntryWithNullValuePresent() {
initMultimapWithNullValue();
- assertThat(multimap().entries()).has().allOf(
- Helpers.mapEntry(getKeyForNullValue(), (V) null));
+ assertContains(multimap().entries(), Helpers.mapEntry(getKeyForNullValue(), (V) null));
}
-
+
@MapFeature.Require(ALLOWS_NULL_VALUE_QUERIES)
public void testContainsEntryWithNullValueAbsent() {
assertFalse(multimap().entries().contains(
- Helpers.mapEntry(sampleKeys().e0, null)));
+ Helpers.mapEntry(k0(), null)));
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testRemovePropagatesToMultimap() {
assertTrue(multimap().entries().remove(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0)));
- expectMissing(Helpers.mapEntry(sampleKeys().e0, sampleValues().e0));
+ Helpers.mapEntry(k0(), v0())));
+ expectMissing(Helpers.mapEntry(k0(), v0()));
assertEquals(getNumElements() - 1, multimap().size());
- assertFalse(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
+ assertFalse(multimap().containsEntry(k0(), v0()));
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testRemoveAllPropagatesToMultimap() {
assertTrue(multimap().entries().removeAll(
- Collections.singleton(Helpers.mapEntry(sampleKeys().e0, sampleValues().e0))));
- expectMissing(Helpers.mapEntry(sampleKeys().e0, sampleValues().e0));
+ Collections.singleton(Helpers.mapEntry(k0(), v0()))));
+ expectMissing(Helpers.mapEntry(k0(), v0()));
assertEquals(getNumElements() - 1, multimap().size());
- assertFalse(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
+ assertFalse(multimap().containsEntry(k0(), v0()));
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testRetainAllPropagatesToMultimap() {
multimap().entries().retainAll(
- Collections.singleton(Helpers.mapEntry(sampleKeys().e0, sampleValues().e0)));
+ Collections.singleton(Helpers.mapEntry(k0(), v0())));
assertEquals(
- getSubjectGenerator().create(Helpers.mapEntry(sampleKeys().e0, sampleValues().e0)),
+ getSubjectGenerator().create(Helpers.mapEntry(k0(), v0())),
multimap());
assertEquals(1, multimap().size());
- assertTrue(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
+ assertTrue(multimap().containsEntry(k0(), v0()));
}
-
+
@CollectionSize.Require(ONE)
@CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
public void testIteratorRemovePropagatesToMultimap() {
Iterator<Entry<K, V>> iterator = multimap().entries().iterator();
assertEquals(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
+ Helpers.mapEntry(k0(), v0()),
iterator.next());
iterator.remove();
assertTrue(multimap().isEmpty());
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testEntriesRemainValidAfterRemove() {
@@ -128,4 +127,3 @@ public class MultimapEntriesTester<K, V> extends AbstractMultimapTester<K, V, Mu
assertEquals(value, entry.getValue());
}
}
-
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapEqualsTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapEqualsTester.java
index 5d66f4e..6eb1ca7 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapEqualsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapEqualsTester.java
@@ -44,7 +44,7 @@ public class MultimapEqualsTester<K, V> extends AbstractMultimapTester<K, V, Mul
public void testEqualsFalse() {
List<Entry<K, V>> targetEntries = new ArrayList<Entry<K, V>>(getSampleElements());
- targetEntries.add(Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+ targetEntries.add(Helpers.mapEntry(k0(), v3()));
new EqualsTester()
.addEqualityGroup(multimap())
.addEqualityGroup(getSubjectGenerator().create(targetEntries.toArray()))
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapGetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapGetTester.java
index 1dc82d6..b6010c0 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapGetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapGetTester.java
@@ -15,7 +15,9 @@
*/
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertContains;
import static com.google.common.collect.testing.Helpers.assertContentsAnyOrder;
+import static com.google.common.collect.testing.Helpers.assertEmpty;
import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
@@ -23,7 +25,6 @@ import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Multimap;
@@ -42,71 +43,71 @@ import java.util.Collections;
@GwtCompatible
public class MultimapGetTester<K, V> extends AbstractMultimapTester<K, V, Multimap<K, V>> {
public void testGetEmpty() {
- Collection<V> result = multimap().get(sampleKeys().e3);
- assertTrue(result.isEmpty());
+ Collection<V> result = multimap().get(k3());
+ assertEmpty(result);
assertEquals(0, result.size());
}
-
+
@CollectionSize.Require(absent = ZERO)
public void testGetNonEmpty() {
- Collection<V> result = multimap().get(sampleKeys().e0);
+ Collection<V> result = multimap().get(k0());
assertFalse(result.isEmpty());
- assertContentsAnyOrder(result, sampleValues().e0);
+ assertContentsAnyOrder(result, v0());
}
@CollectionSize.Require(SEVERAL)
public void testGetMultiple() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e2));
- assertGet(sampleKeys().e0,
- sampleValues().e0,
- sampleValues().e1,
- sampleValues().e2);
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v1()),
+ Helpers.mapEntry(k0(), v2()));
+ assertGet(k0(),
+ v0(),
+ v1(),
+ v2());
}
-
+
public void testGetAbsentKey() {
- assertGet(sampleKeys().e4);
+ assertGet(k4());
}
-
+
@CollectionSize.Require(SEVERAL)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testPropagatesRemoveToMultimap() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e2));
- Collection<V> result = multimap().get(sampleKeys().e0);
- assertTrue(result.remove(sampleValues().e0));
- assertFalse(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v3()),
+ Helpers.mapEntry(k0(), v2()));
+ Collection<V> result = multimap().get(k0());
+ assertTrue(result.remove(v0()));
+ assertFalse(multimap().containsEntry(k0(), v0()));
assertEquals(2, multimap().size());
}
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testPropagatesRemoveLastElementToMultimap() {
- Collection<V> result = multimap().get(sampleKeys().e0);
- assertTrue(result.remove(sampleValues().e0));
- assertGet(sampleKeys().e0);
- }
+ Collection<V> result = multimap().get(k0());
+ assertTrue(result.remove(v0()));
+ assertGet(k0());
+ }
@MapFeature.Require(SUPPORTS_PUT)
public void testPropagatesAddToMultimap() {
- Collection<V> result = multimap().get(sampleKeys().e0);
- assertTrue(result.add(sampleValues().e3));
- assertTrue(multimap().containsKey(sampleKeys().e0));
+ Collection<V> result = multimap().get(k0());
+ assertTrue(result.add(v3()));
+ assertTrue(multimap().containsKey(k0()));
assertEquals(getNumElements() + 1, multimap().size());
- assertTrue(multimap().containsEntry(sampleKeys().e0, sampleValues().e3));
+ assertTrue(multimap().containsEntry(k0(), v3()));
}
@MapFeature.Require(SUPPORTS_PUT)
public void testPropagatesAddAllToMultimap() {
- Collection<V> result = multimap().get(sampleKeys().e0);
- assertTrue(result.addAll(Collections.singletonList(sampleValues().e3)));
- assertTrue(multimap().containsKey(sampleKeys().e0));
+ Collection<V> result = multimap().get(k0());
+ assertTrue(result.addAll(Collections.singletonList(v3())));
+ assertTrue(multimap().containsKey(k0()));
assertEquals(getNumElements() + 1, multimap().size());
- assertTrue(multimap().containsEntry(sampleKeys().e0, sampleValues().e3));
+ assertTrue(multimap().containsEntry(k0(), v3()));
}
@CollectionSize.Require(absent = ZERO)
@@ -114,27 +115,21 @@ public class MultimapGetTester<K, V> extends AbstractMultimapTester<K, V, Multim
public void testPropagatesRemoveLastThenAddToMultimap() {
int oldSize = getNumElements();
- K k0 = sampleKeys().e0;
- V v0 = sampleValues().e0;
-
- Collection<V> result = multimap().get(k0);
- assertTrue(result.remove(v0));
-
- assertFalse(multimap().containsKey(k0));
- assertFalse(multimap().containsEntry(k0, v0));
- assertThat(result).isEmpty();
+ Collection<V> result = multimap().get(k0());
+ assertTrue(result.remove(v0()));
- V v1 = sampleValues().e1;
- V v2 = sampleValues().e2;
+ assertFalse(multimap().containsKey(k0()));
+ assertFalse(multimap().containsEntry(k0(), v0()));
+ assertEmpty(result);
- assertTrue(result.add(v1));
- assertTrue(result.add(v2));
+ assertTrue(result.add(v1()));
+ assertTrue(result.add(v2()));
- assertThat(result).has().exactly(v1, v2);
- assertThat(multimap().get(k0)).has().exactly(v1, v2);
- assertTrue(multimap().containsKey(k0));
- assertFalse(multimap().containsEntry(k0, v0));
- assertTrue(multimap().containsEntry(k0, v2));
+ assertContentsAnyOrder(result, v1(), v2());
+ assertContentsAnyOrder(multimap().get(k0()), v1(), v2());
+ assertTrue(multimap().containsKey(k0()));
+ assertFalse(multimap().containsEntry(k0(), v0()));
+ assertTrue(multimap().containsEntry(k0(), v2()));
assertEquals(oldSize + 1, multimap().size());
}
@@ -142,12 +137,12 @@ public class MultimapGetTester<K, V> extends AbstractMultimapTester<K, V, Multim
@CollectionSize.Require(absent = ZERO)
public void testGetNullPresent() {
initMultimapWithNullKey();
- assertThat(multimap().get(null)).has().item(getValueForNullKey());
+ assertContains(multimap().get(null), getValueForNullKey());
}
@MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
public void testGetNullAbsent() {
- assertThat(multimap().get(null)).isEmpty();
+ assertEmpty(multimap().get(null));
}
@MapFeature.Require(absent = ALLOWS_NULL_KEY_QUERIES)
@@ -164,7 +159,6 @@ public class MultimapGetTester<K, V> extends AbstractMultimapTester<K, V, Multim
@CollectionSize.Require(absent = ZERO)
public void testGetWithNullValue() {
initMultimapWithNullValue();
- assertThat(multimap().get(getKeyForNullValue()))
- .has().item(null);
+ assertContains(multimap().get(getKeyForNullValue()), null);
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeySetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeySetTester.java
index 6ccb993..fe7f143 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeySetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeySetTester.java
@@ -56,23 +56,23 @@ public class MultimapKeySetTester<K, V> extends AbstractMultimapTester<K, V, Mul
@MapFeature.Require(SUPPORTS_REMOVE)
public void testKeySetRemovePropagatesToMultimap() {
- int key0Count = multimap().get(sampleKeys().e0).size();
- assertEquals(key0Count > 0, multimap().keySet().remove(sampleKeys().e0));
+ int key0Count = multimap().get(k0()).size();
+ assertEquals(key0Count > 0, multimap().keySet().remove(k0()));
assertEquals(getNumElements() - key0Count, multimap().size());
- assertGet(sampleKeys().e0);
+ assertGet(k0());
}
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
public void testKeySetIteratorRemove() {
- int key0Count = multimap().get(sampleKeys().e0).size();
+ int key0Count = multimap().get(k0()).size();
Iterator<K> keyItr = multimap().keySet().iterator();
while (keyItr.hasNext()) {
- if (keyItr.next().equals(sampleKeys().e0)) {
+ if (keyItr.next().equals(k0())) {
keyItr.remove();
}
}
assertEquals(getNumElements() - key0Count, multimap().size());
- assertGet(sampleKeys().e0);
+ assertGet(k0());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeysTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeysTester.java
index b331030..3ebfd55 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeysTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapKeysTester.java
@@ -14,13 +14,13 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertContainsAllOf;
import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
import static com.google.common.collect.testing.features.CollectionSize.ONE;
import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEY_QUERIES;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Multimap;
@@ -43,72 +43,72 @@ public class MultimapKeysTester<K, V> extends AbstractMultimapTester<K, V, Multi
@CollectionSize.Require(SEVERAL)
public void testKeys() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
- Helpers.mapEntry(sampleKeys().e1, sampleValues().e0));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v1()),
+ Helpers.mapEntry(k1(), v0()));
Multiset<K> keys = multimap().keys();
- assertEquals(2, keys.count(sampleKeys().e0));
- assertEquals(1, keys.count(sampleKeys().e1));
+ assertEquals(2, keys.count(k0()));
+ assertEquals(1, keys.count(k1()));
assertEquals(3, keys.size());
- assertThat(keys).has().allOf(sampleKeys().e0, sampleKeys().e1);
- assertThat(keys.entrySet()).has().allOf(
- Multisets.immutableEntry(sampleKeys().e0, 2),
- Multisets.immutableEntry(sampleKeys().e1, 1));
+ assertContainsAllOf(keys, k0(), k1());
+ assertContainsAllOf(keys.entrySet(),
+ Multisets.immutableEntry(k0(), 2),
+ Multisets.immutableEntry(k1(), 1));
}
-
+
@MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
public void testKeysCountAbsentNullKey() {
assertEquals(0, multimap().keys().count(null));
}
-
+
@CollectionSize.Require(SEVERAL)
@MapFeature.Require(ALLOWS_NULL_KEYS)
public void testKeysWithNullKey() {
resetContainer(
- Helpers.mapEntry((K) null, sampleValues().e0),
- Helpers.mapEntry((K) null, sampleValues().e1),
- Helpers.mapEntry(sampleKeys().e1, sampleValues().e0));
+ Helpers.mapEntry((K) null, v0()),
+ Helpers.mapEntry((K) null, v1()),
+ Helpers.mapEntry(k1(), v0()));
Multiset<K> keys = multimap().keys();
assertEquals(2, keys.count(null));
- assertEquals(1, keys.count(sampleKeys().e1));
+ assertEquals(1, keys.count(k1()));
assertEquals(3, keys.size());
- assertThat(keys).has().allOf(null, sampleKeys().e1);
- assertThat(keys.entrySet()).has().allOf(
+ assertContainsAllOf(keys, null, k1());
+ assertContainsAllOf(keys.entrySet(),
Multisets.immutableEntry((K) null, 2),
- Multisets.immutableEntry(sampleKeys().e1, 1));
+ Multisets.immutableEntry(k1(), 1));
}
-
+
public void testKeysElementSet() {
assertEquals(multimap().keySet(), multimap().keys().elementSet());
}
@MapFeature.Require(SUPPORTS_REMOVE)
public void testKeysRemove() {
- int original = multimap().keys().remove(sampleKeys().e0, 1);
- assertEquals(Math.max(original - 1, 0), multimap().get(sampleKeys().e0).size());
+ int original = multimap().keys().remove(k0(), 1);
+ assertEquals(Math.max(original - 1, 0), multimap().get(k0()).size());
}
-
+
@CollectionSize.Require(ONE)
@CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
public void testKeysEntrySetIteratorRemove() {
Multiset<K> keys = multimap().keys();
Iterator<Multiset.Entry<K>> itr = keys.entrySet().iterator();
- assertEquals(Multisets.immutableEntry(sampleKeys().e0, 1),
+ assertEquals(Multisets.immutableEntry(k0(), 1),
itr.next());
itr.remove();
assertTrue(multimap().isEmpty());
}
-
+
@CollectionSize.Require(SEVERAL)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testKeysEntrySetRemove() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
- Helpers.mapEntry(sampleKeys().e1, sampleValues().e0));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v1()),
+ Helpers.mapEntry(k1(), v0()));
assertTrue(multimap().keys().entrySet().remove(
- Multisets.immutableEntry(sampleKeys().e0, 2)));
+ Multisets.immutableEntry(k0(), 2)));
assertEquals(1, multimap().size());
- assertTrue(multimap().containsEntry(sampleKeys().e1, sampleValues().e0));
+ assertTrue(multimap().containsEntry(k1(), v0()));
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutAllMultimapTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutAllMultimapTester.java
index fc65e5c..b258cf1 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutAllMultimapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutAllMultimapTester.java
@@ -16,10 +16,10 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertContains;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Multimap;
@@ -40,59 +40,59 @@ public class MultimapPutAllMultimapTester<K, V>
public void testPutUnsupported() {
try {
multimap().putAll(getSubjectGenerator().create(
- Helpers.mapEntry(sampleKeys().e3, sampleValues().e3)));
+ Helpers.mapEntry(k3(), v3())));
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {}
}
-
+
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAllIntoEmpty() {
Multimap<K, V> target = getSubjectGenerator().create();
assertEquals(!multimap().isEmpty(), target.putAll(multimap()));
- assertEquals(multimap(), target);
+ assertEquals(multimap(), target);
}
-
+
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAll() {
Multimap<K, V> source = getSubjectGenerator().create(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3),
- Helpers.mapEntry(sampleKeys().e3, sampleValues().e3));
+ Helpers.mapEntry(k0(), v3()),
+ Helpers.mapEntry(k3(), v3()));
assertTrue(multimap().putAll(source));
- assertTrue(multimap().containsEntry(sampleKeys().e0, sampleValues().e3));
- assertTrue(multimap().containsEntry(sampleKeys().e3, sampleValues().e3));
+ assertTrue(multimap().containsEntry(k0(), v3()));
+ assertTrue(multimap().containsEntry(k3(), v3()));
}
-
+
@MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
public void testPutAllWithNullValue() {
Multimap<K, V> source = getSubjectGenerator().create(
- Helpers.mapEntry(sampleKeys().e0, null));
+ Helpers.mapEntry(k0(), null));
assertTrue(multimap().putAll(source));
- assertTrue(multimap().containsEntry(sampleKeys().e0, null));
+ assertTrue(multimap().containsEntry(k0(), null));
}
-
+
@MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS})
public void testPutAllWithNullKey() {
Multimap<K, V> source = getSubjectGenerator().create(
- Helpers.mapEntry(null, sampleValues().e0));
+ Helpers.mapEntry(null, v0()));
assertTrue(multimap().putAll(source));
- assertTrue(multimap().containsEntry(null, sampleValues().e0));
+ assertTrue(multimap().containsEntry(null, v0()));
}
-
+
@MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
public void testPutAllRejectsNullValue() {
Multimap<K, V> source = getSubjectGenerator().create(
- Helpers.mapEntry(sampleKeys().e0, null));
+ Helpers.mapEntry(k0(), null));
try {
multimap().putAll(source);
fail("Expected NullPointerException");
} catch (NullPointerException expected) {}
expectUnchanged();
}
-
+
@MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_KEYS)
public void testPutAllRejectsNullKey() {
Multimap<K, V> source = getSubjectGenerator().create(
- Helpers.mapEntry(null, sampleValues().e0));
+ Helpers.mapEntry(null, v0()));
try {
multimap().putAll(source);
fail("Expected NullPointerException");
@@ -103,12 +103,12 @@ public class MultimapPutAllMultimapTester<K, V>
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAllPropagatesToGet() {
Multimap<K, V> source = getSubjectGenerator().create(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3),
- Helpers.mapEntry(sampleKeys().e3, sampleValues().e3));
- Collection<V> getCollection = multimap().get(sampleKeys().e0);
+ Helpers.mapEntry(k0(), v3()),
+ Helpers.mapEntry(k3(), v3()));
+ Collection<V> getCollection = multimap().get(k0());
int getCollectionSize = getCollection.size();
assertTrue(multimap().putAll(source));
assertEquals(getCollectionSize + 1, getCollection.size());
- assertThat(getCollection).has().allOf(sampleValues().e3);
+ assertContains(getCollection, v3());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutIterableTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutIterableTester.java
index 5e2768c..9440ff4 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutIterableTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutIterableTester.java
@@ -16,13 +16,14 @@
package com.google.common.collect.testing.google;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.testing.Helpers.assertContainsAllOf;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
@@ -43,80 +44,80 @@ public class MultimapPutIterableTester<K, V> extends AbstractMultimapTester<K, V
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAllNonEmptyIterableOnPresentKey() {
- assertTrue(multimap().putAll(sampleKeys().e0, new Iterable<V>() {
+ assertTrue(multimap().putAll(k0(), new Iterable<V>() {
@Override
public Iterator<V> iterator() {
- return Lists.newArrayList(sampleValues().e3, sampleValues().e4).iterator();
+ return Lists.newArrayList(v3(), v4()).iterator();
}
}));
- assertGet(sampleKeys().e0, sampleValues().e0, sampleValues().e3, sampleValues().e4);
+ assertGet(k0(), v0(), v3(), v4());
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAllNonEmptyCollectionOnPresentKey() {
assertTrue(multimap().putAll(
- sampleKeys().e0, Lists.newArrayList(sampleValues().e3, sampleValues().e4)));
- assertGet(sampleKeys().e0, sampleValues().e0, sampleValues().e3, sampleValues().e4);
+ k0(), Lists.newArrayList(v3(), v4())));
+ assertGet(k0(), v0(), v3(), v4());
}
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAllNonEmptyIterableOnAbsentKey() {
- assertTrue(multimap().putAll(sampleKeys().e3, new Iterable<V>() {
+ assertTrue(multimap().putAll(k3(), new Iterable<V>() {
@Override
public Iterator<V> iterator() {
- return Lists.newArrayList(sampleValues().e3, sampleValues().e4).iterator();
+ return Lists.newArrayList(v3(), v4()).iterator();
}
}));
- assertGet(sampleKeys().e3, sampleValues().e3, sampleValues().e4);
+ assertGet(k3(), v3(), v4());
}
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAllNonEmptyCollectionOnAbsentKey() {
assertTrue(multimap().putAll(
- sampleKeys().e3, Lists.newArrayList(sampleValues().e3, sampleValues().e4)));
- assertGet(sampleKeys().e3, sampleValues().e3, sampleValues().e4);
+ k3(), Lists.newArrayList(v3(), v4())));
+ assertGet(k3(), v3(), v4());
}
-
+
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
public void testPutAllNullValueOnPresentKey_supported() {
- assertTrue(multimap().putAll(sampleKeys().e0, Lists.newArrayList(sampleValues().e3, null)));
- assertGet(sampleKeys().e0, sampleValues().e0, sampleValues().e3, null);
+ assertTrue(multimap().putAll(k0(), Lists.newArrayList(v3(), null)));
+ assertGet(k0(), v0(), v3(), null);
}
-
+
@MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
public void testPutAllNullValueOnAbsentKey_supported() {
- assertTrue(multimap().putAll(sampleKeys().e3, Lists.newArrayList(sampleValues().e3, null)));
- assertGet(sampleKeys().e3, sampleValues().e3, null);
+ assertTrue(multimap().putAll(k3(), Lists.newArrayList(v3(), null)));
+ assertGet(k3(), v3(), null);
}
@MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
public void testPutAllNullValueSingle_unsupported() {
- multimap().putAll(sampleKeys().e1, Lists.newArrayList((V) null));
+ multimap().putAll(k1(), Lists.newArrayList((V) null));
expectUnchanged();
}
// In principle, it would be nice to apply these two tests to keys with existing values, too.
-
+
@MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
public void testPutAllNullValueNullLast_unsupported() {
int size = getNumElements();
try {
- multimap().putAll(sampleKeys().e3, Lists.newArrayList(sampleValues().e3, null));
+ multimap().putAll(k3(), Lists.newArrayList(v3(), null));
fail();
} catch (NullPointerException expected) {
}
- Collection<V> values = multimap().get(sampleKeys().e3);
+ Collection<V> values = multimap().get(k3());
if (values.size() == 0) {
expectUnchanged();
// Be extra thorough in case internal state was corrupted by the expected null.
assertEquals(Lists.newArrayList(), Lists.newArrayList(values));
assertEquals(size, multimap().size());
} else {
- assertEquals(Lists.newArrayList(sampleValues().e3), Lists.newArrayList(values));
+ assertEquals(Lists.newArrayList(v3()), Lists.newArrayList(values));
assertEquals(size + 1, multimap().size());
}
}
@@ -126,7 +127,7 @@ public class MultimapPutIterableTester<K, V> extends AbstractMultimapTester<K, V
int size = getNumElements();
try {
- multimap().putAll(sampleKeys().e3, Lists.newArrayList(null, sampleValues().e3));
+ multimap().putAll(k3(), Lists.newArrayList(null, v3()));
fail();
} catch (NullPointerException expected) {
}
@@ -138,31 +139,30 @@ public class MultimapPutIterableTester<K, V> extends AbstractMultimapTester<K, V
*/
expectUnchanged();
// Be extra thorough in case internal state was corrupted by the expected null.
- assertEquals(Lists.newArrayList(), Lists.newArrayList(multimap().get(sampleKeys().e3)));
+ assertEquals(Lists.newArrayList(), Lists.newArrayList(multimap().get(k3())));
assertEquals(size, multimap().size());
}
@MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS})
public void testPutAllOnPresentNullKey() {
- assertTrue(multimap().putAll(null, Lists.newArrayList(sampleValues().e3, sampleValues().e4)));
- assertGet(null, sampleValues().e3, sampleValues().e4);
+ assertTrue(
+ multimap().putAll(null, Lists.newArrayList(v3(), v4())));
+ assertGet(null, v3(), v4());
}
@MapFeature.Require(absent = ALLOWS_NULL_KEYS)
public void testPutAllNullForbidden() {
try {
- multimap().putAll(null, Collections.singletonList(sampleValues().e3));
+ multimap().putAll(null, Collections.singletonList(v3()));
fail("Expected NullPointerException");
} catch (NullPointerException expected) {
// success
}
}
- private static final Object[] EMPTY = new Object[0];
-
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAllEmptyCollectionOnAbsentKey() {
- assertFalse(multimap().putAll(sampleKeys().e3, Collections.<V>emptyList()));
+ assertFalse(multimap().putAll(k3(), Collections.<V>emptyList()));
expectUnchanged();
}
@@ -171,21 +171,21 @@ public class MultimapPutIterableTester<K, V> extends AbstractMultimapTester<K, V
Iterable<V> iterable = new Iterable<V>() {
@Override
public Iterator<V> iterator() {
- return Iterators.emptyIterator();
+ return ImmutableSet.<V>of().iterator();
}
};
- assertFalse(multimap().putAll(sampleKeys().e3, iterable));
+ assertFalse(multimap().putAll(k3(), iterable));
expectUnchanged();
}
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAllEmptyIterableOnPresentKey() {
- multimap().putAll(sampleKeys().e0, Collections.<V>emptyList());
+ multimap().putAll(k0(), Collections.<V>emptyList());
expectUnchanged();
}
-
+
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAllOnlyCallsIteratorOnce() {
Iterable<V> iterable = new Iterable<V>() {
@@ -195,20 +195,20 @@ public class MultimapPutIterableTester<K, V> extends AbstractMultimapTester<K, V
public Iterator<V> iterator() {
checkState(!calledIteratorAlready);
calledIteratorAlready = true;
- return Iterators.forArray(sampleValues().e3);
+ return Iterators.forArray(v3());
}
};
-
- multimap().putAll(sampleKeys().e3, iterable);
+
+ multimap().putAll(k3(), iterable);
}
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAllPropagatesToGet() {
- Collection<V> getCollection = multimap().get(sampleKeys().e0);
+ Collection<V> getCollection = multimap().get(k0());
int getCollectionSize = getCollection.size();
assertTrue(multimap().putAll(
- sampleKeys().e0, Lists.newArrayList(sampleValues().e3, sampleValues().e4)));
+ k0(), Lists.newArrayList(v3(), v4())));
assertEquals(getCollectionSize + 2, getCollection.size());
- assertThat(getCollection).has().allOf(sampleValues().e3, sampleValues().e4);
+ assertContainsAllOf(getCollection, v3(), v4());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutTester.java
index 5ac36a4..409b74a 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapPutTester.java
@@ -16,11 +16,13 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertContains;
+import static com.google.common.collect.testing.Helpers.assertEmpty;
+import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.ImmutableList;
@@ -45,23 +47,20 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
@MapFeature.Require(absent = SUPPORTS_PUT)
public void testPutUnsupported() {
try {
- multimap().put(sampleKeys().e3, sampleValues().e3);
+ multimap().put(k3(), v3());
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {}
}
-
+
@MapFeature.Require(SUPPORTS_PUT)
public void testPutEmpty() {
int size = getNumElements();
- K key = sampleKeys().e3;
- V value = sampleValues().e3;
-
- assertGet(key, ImmutableList.<V>of());
+ assertGet(k3(), ImmutableList.<V>of());
- assertTrue(multimap().put(key, value));
+ assertTrue(multimap().put(k3(), v3()));
- assertGet(key, value);
+ assertGet(k3(), v3());
assertEquals(size + 1, multimap().size());
}
@@ -70,15 +69,11 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
public void testPutPresent() {
int size = getNumElements();
- K key = sampleKeys().e0;
- V oldValue = sampleValues().e0;
- V newValue = sampleValues().e3;
+ assertGet(k0(), v0());
- assertGet(key, oldValue);
+ assertTrue(multimap().put(k0(), v3()));
- assertTrue(multimap().put(key, newValue));
-
- assertGet(key, oldValue, newValue);
+ assertGet(k0(), v0(), v3());
assertEquals(size + 1, multimap().size());
}
@@ -86,19 +81,15 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
public void testPutTwoElements() {
int size = getNumElements();
- K key = sampleKeys().e0;
- V v1 = sampleValues().e3;
- V v2 = sampleValues().e4;
-
- List<V> values = Helpers.copyToList(multimap().get(key));
+ List<V> values = Helpers.copyToList(multimap().get(k0()));
- assertTrue(multimap().put(key, v1));
- assertTrue(multimap().put(key, v2));
+ assertTrue(multimap().put(k0(), v1()));
+ assertTrue(multimap().put(k0(), v2()));
- values.add(v1);
- values.add(v2);
+ values.add(v1());
+ values.add(v2());
- assertGet(key, values);
+ assertGet(k0(), values);
assertEquals(size + 2, multimap().size());
}
@@ -106,16 +97,16 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
public void testPutNullValue_supported() {
int size = getNumElements();
- multimap().put(sampleKeys().e3, null);
+ multimap().put(k3(), null);
- assertGet(sampleKeys().e3, Lists.newArrayList((V) null)); // ImmutableList.of can't take null.
+ assertGet(k3(), Lists.newArrayList((V) null)); // ImmutableList.of can't take null.
assertEquals(size + 1, multimap().size());
}
@MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
public void testPutNullValue_unsupported() {
try {
- multimap().put(sampleKeys().e1, null);
+ multimap().put(k1(), null);
fail();
} catch (NullPointerException expected) {
}
@@ -127,37 +118,37 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
public void testPutNullKey() {
int size = getNumElements();
- multimap().put(null, sampleValues().e3);
+ multimap().put(null, v3());
- assertGet(null, sampleValues().e3);
+ assertGet(null, v3());
assertEquals(size + 1, multimap().size());
}
@MapFeature.Require(SUPPORTS_PUT)
public void testPutNotPresentKeyPropagatesToGet() {
int size = getNumElements();
- Collection<V> collection = multimap().get(sampleKeys().e3);
- assertThat(collection).isEmpty();
- multimap().put(sampleKeys().e3, sampleValues().e3);
- assertThat(collection).has().item(sampleValues().e3);
+ Collection<V> collection = multimap().get(k3());
+ assertEmpty(collection);
+ multimap().put(k3(), v3());
+ assertContains(collection, v3());
assertEquals(size + 1, multimap().size());
}
@MapFeature.Require(SUPPORTS_PUT)
public void testPutNotPresentKeyPropagatesToEntries() {
Collection<Entry<K, V>> entries = multimap().entries();
- assertFalse(entries.contains(Helpers.mapEntry(sampleKeys().e3, sampleValues().e3)));
- multimap().put(sampleKeys().e3, sampleValues().e3);
- assertThat(entries).has().allOf(Helpers.mapEntry(sampleKeys().e3, sampleValues().e3));
+ assertFalse(entries.contains(Helpers.mapEntry(k3(), v3())));
+ multimap().put(k3(), v3());
+ assertContains(entries, Helpers.mapEntry(k3(), v3()));
}
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_PUT)
public void testPutPresentKeyPropagatesToEntries() {
Collection<Entry<K, V>> entries = multimap().entries();
- assertFalse(entries.contains(Helpers.mapEntry(sampleKeys().e0, sampleValues().e3)));
- multimap().put(sampleKeys().e0, sampleValues().e3);
- assertThat(entries).has().allOf(Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+ assertFalse(entries.contains(Helpers.mapEntry(k0(), v3())));
+ multimap().put(k0(), v3());
+ assertContains(entries, Helpers.mapEntry(k0(), v3()));
}
@MapFeature.Require(SUPPORTS_PUT)
@@ -172,9 +163,9 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
Collection<V> collection = multimap().get(key);
Collection<V> expectedCollection = Helpers.copyToList(collection);
- multimap().put(key, sampleValues().e3);
- expectedCollection.add(sampleValues().e3);
- assertThat(collection).has().exactlyAs(expectedCollection);
+ multimap().put(key, v3());
+ expectedCollection.add(v3());
+ assertEqualIgnoringOrder(expectedCollection, collection);
assertEquals(size + 1, multimap().size());
}
}
@@ -192,9 +183,9 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
assertNotNull(collection);
Collection<V> expectedCollection = Helpers.copyToList(collection);
- multimap().put(key, sampleValues().e3);
- expectedCollection.add(sampleValues().e3);
- assertThat(collection).has().exactlyAs(expectedCollection);
+ multimap().put(key, v3());
+ expectedCollection.add(v3());
+ assertEqualIgnoringOrder(expectedCollection, collection);
assertEquals(size + 1, multimap().size());
}
}
@@ -220,9 +211,9 @@ public class MultimapPutTester<K, V> extends AbstractMultimapTester<K, V, Multim
assertNotNull(collection);
Collection<V> expectedCollection = Helpers.copyToList(collection);
- multimap().put(key, sampleValues().e3);
- expectedCollection.add(sampleValues().e3);
- assertThat(collection).has().exactlyAs(expectedCollection);
+ multimap().put(key, v3());
+ expectedCollection.add(v3());
+ assertEqualIgnoringOrder(expectedCollection, collection);
assertEquals(size + 1, multimap().size());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveAllTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveAllTester.java
index cbd84c9..7ab2e9b 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveAllTester.java
@@ -16,12 +16,14 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertContentsAnyOrder;
+import static com.google.common.collect.testing.Helpers.assertEmpty;
import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_ANY_NULL_QUERIES;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.collect.testing.google.GoogleHelpers.assertEmpty;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Multimap;
@@ -40,40 +42,38 @@ import java.util.Collection;
public class MultimapRemoveAllTester<K, V> extends AbstractMultimapTester<K, V, Multimap<K, V>> {
@MapFeature.Require(SUPPORTS_REMOVE)
public void testRemoveAllAbsentKey() {
- assertThat(multimap().removeAll(sampleKeys().e3)).isEmpty();
+ assertEmpty(multimap().removeAll(k3()));
expectUnchanged();
}
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testRemoveAllPresentKey() {
- assertThat(multimap().removeAll(sampleKeys().e0))
- .has().exactly(sampleValues().e0).inOrder();
- expectMissing(samples.e0);
+ assertContentsAnyOrder(multimap().removeAll(k0()), v0());
+ expectMissing(e0());
}
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testRemoveAllPropagatesToGet() {
- Collection<V> getResult = multimap().get(sampleKeys().e0);
+ Collection<V> getResult = multimap().get(k0());
- multimap().removeAll(sampleKeys().e0);
+ multimap().removeAll(k0());
- assertThat(getResult).isEmpty();
- expectMissing(samples.e0);
+ assertEmpty(getResult);
+ expectMissing(e0());
}
@CollectionSize.Require(SEVERAL)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testRemoveAllMultipleValues() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e2));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v1()),
+ Helpers.mapEntry(k0(), v2()));
- assertThat(multimap().removeAll(sampleKeys().e0))
- .has().exactly(sampleValues().e0, sampleValues().e1, sampleValues().e2);
- assertTrue(multimap().isEmpty());
+ assertContentsAnyOrder(multimap().removeAll(k0()), v0(), v1(), v2());
+ assertEmpty(multimap());
}
@CollectionSize.Require(absent = ZERO)
@@ -81,14 +81,14 @@ public class MultimapRemoveAllTester<K, V> extends AbstractMultimapTester<K, V,
public void testRemoveAllNullKeyPresent() {
initMultimapWithNullKey();
- assertThat(multimap().removeAll(null)).has().exactly(getValueForNullKey()).inOrder();
+ assertContentsAnyOrder(multimap().removeAll(null), getValueForNullKey());
expectMissing(Helpers.mapEntry((K) null, getValueForNullKey()));
}
@MapFeature.Require({ SUPPORTS_REMOVE, ALLOWS_ANY_NULL_QUERIES})
public void testRemoveAllNullKeyAbsent() {
- assertThat(multimap().removeAll(null)).isEmpty();
+ assertEmpty(multimap().removeAll(null));
expectUnchanged();
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveEntryTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveEntryTester.java
index c1d6783..8f131f3 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveEntryTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapRemoveEntryTester.java
@@ -16,13 +16,13 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEY_QUERIES;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.ImmutableList;
@@ -45,19 +45,19 @@ import java.util.Map.Entry;
public class MultimapRemoveEntryTester<K, V> extends AbstractMultimapTester<K, V, Multimap<K, V>> {
@MapFeature.Require(SUPPORTS_REMOVE)
public void testRemoveAbsent() {
- assertFalse(multimap().remove(sampleKeys().e0, sampleValues().e1));
+ assertFalse(multimap().remove(k0(), v1()));
expectUnchanged();
}
@CollectionSize.Require(absent = ZERO)
@MapFeature.Require(SUPPORTS_REMOVE)
public void testRemovePresent() {
- assertTrue(multimap().remove(sampleKeys().e0, sampleValues().e0));
+ assertTrue(multimap().remove(k0(), v0()));
- assertFalse(multimap().containsEntry(sampleKeys().e0, sampleValues().e0));
- expectMissing(samples.e0);
+ assertFalse(multimap().containsEntry(k0(), v0()));
+ expectMissing(e0());
assertEquals(getNumElements() - 1, multimap().size());
- assertGet(sampleKeys().e0, ImmutableList.<V>of());
+ assertGet(k0(), ImmutableList.<V>of());
}
@CollectionSize.Require(absent = ZERO)
@@ -84,20 +84,20 @@ public class MultimapRemoveEntryTester<K, V> extends AbstractMultimapTester<K, V
@MapFeature.Require({ SUPPORTS_REMOVE, ALLOWS_NULL_KEY_QUERIES})
public void testRemoveNullKeyAbsent() {
- assertFalse(multimap().remove(null, sampleValues().e0));
+ assertFalse(multimap().remove(null, v0()));
expectUnchanged();
}
@MapFeature.Require({ SUPPORTS_REMOVE, ALLOWS_NULL_VALUE_QUERIES})
public void testRemoveNullValueAbsent() {
- assertFalse(multimap().remove(sampleKeys().e0, null));
+ assertFalse(multimap().remove(k0(), null));
expectUnchanged();
}
@MapFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_VALUE_QUERIES)
public void testRemoveNullValueForbidden() {
try {
- multimap().remove(sampleKeys().e0, null);
+ multimap().remove(k0(), null);
fail("Expected NullPointerException");
} catch (NullPointerException expected) {
// success
@@ -108,7 +108,7 @@ public class MultimapRemoveEntryTester<K, V> extends AbstractMultimapTester<K, V
@MapFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_KEY_QUERIES)
public void testRemoveNullKeyForbidden() {
try {
- multimap().remove(null, sampleValues().e0);
+ multimap().remove(null, v0());
fail("Expected NullPointerException");
} catch (NullPointerException expected) {
// success
@@ -132,7 +132,7 @@ public class MultimapRemoveEntryTester<K, V> extends AbstractMultimapTester<K, V
multimap().remove(key, value);
expectedCollection.remove(value);
- assertThat(collection).has().exactlyAs(expectedCollection);
+ assertEqualIgnoringOrder(expectedCollection, collection);
assertEquals(!expectedCollection.isEmpty(), multimap().containsKey(key));
}
}
@@ -153,7 +153,7 @@ public class MultimapRemoveEntryTester<K, V> extends AbstractMultimapTester<K, V
multimap().remove(key, value);
expectedCollection.remove(value);
- assertThat(collection).has().exactlyAs(expectedCollection);
+ assertEqualIgnoringOrder(expectedCollection, collection);
assertEquals(!expectedCollection.isEmpty(), multimap().containsKey(key));
}
}
@@ -183,7 +183,7 @@ public class MultimapRemoveEntryTester<K, V> extends AbstractMultimapTester<K, V
multimap().remove(key, value);
expectedCollection.remove(value);
- assertThat(collection).has().exactlyAs(expectedCollection);
+ assertEqualIgnoringOrder(expectedCollection, collection);
assertEquals(!expectedCollection.isEmpty(), multimap().containsKey(key));
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapReplaceValuesTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapReplaceValuesTester.java
index 930d16f..d8ae346 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapReplaceValuesTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapReplaceValuesTester.java
@@ -16,12 +16,12 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertContentsAnyOrder;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Multimap;
@@ -46,61 +46,54 @@ public class MultimapReplaceValuesTester<K, V>
@MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
public void testReplaceValuesWithNullValue() {
- int size = multimap().size();
- K key = sampleKeys().e0;
@SuppressWarnings("unchecked")
- List<V> values = Arrays.asList(sampleValues().e0, null, sampleValues().e3);
- multimap().replaceValues(key, values);
- assertGet(key, values);
+ List<V> values = Arrays.asList(v0(), null, v3());
+ multimap().replaceValues(k0(), values);
+ assertGet(k0(), values);
}
-
+
@MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE, ALLOWS_NULL_KEYS})
public void testReplaceValuesWithNullKey() {
- int size = multimap().size();
- K key = null;
@SuppressWarnings("unchecked")
- List<V> values = Arrays.asList(sampleValues().e0, sampleValues().e2, sampleValues().e3);
- multimap().replaceValues(key, values);
- assertGet(key, values);
+ List<V> values = Arrays.asList(v0(), v2(), v3());
+ multimap().replaceValues(null, values);
+ assertGet(null, values);
}
-
+
@MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
public void testReplaceEmptyValues() {
int size = multimap().size();
- K key = sampleKeys().e3;
@SuppressWarnings("unchecked")
- List<V> values = Arrays.asList(sampleValues().e0, sampleValues().e2, sampleValues().e3);
- multimap().replaceValues(key, values);
- assertGet(key, values);
+ List<V> values = Arrays.asList(v0(), v2(), v3());
+ multimap().replaceValues(k3(), values);
+ assertGet(k3(), values);
assertEquals(size + values.size(), multimap().size());
}
-
+
@MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
public void testReplaceValuesWithEmpty() {
int size = multimap().size();
- K key = sampleKeys().e0;
- List<V> oldValues = new ArrayList<V>(multimap().get(key));
+ List<V> oldValues = new ArrayList<V>(multimap().get(k0()));
@SuppressWarnings("unchecked")
List<V> values = Collections.emptyList();
- assertEquals(oldValues, new ArrayList<V>(multimap().replaceValues(key, values)));
- assertGet(key);
+ assertEquals(oldValues, new ArrayList<V>(multimap().replaceValues(k0(), values)));
+ assertGet(k0());
assertEquals(size - oldValues.size(), multimap().size());
}
-
+
@MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
public void testReplaceValuesWithDuplicates() {
int size = multimap().size();
- K key = sampleKeys().e0;
- List<V> oldValues = new ArrayList<V>(multimap().get(key));
+ List<V> oldValues = new ArrayList<V>(multimap().get(k0()));
List<V> values = Arrays.asList(
- sampleValues().e0,
- sampleValues().e3,
- sampleValues().e0);
- assertEquals(oldValues, new ArrayList<V>(multimap().replaceValues(key, values)));
+ v0(),
+ v3(),
+ v0());
+ assertEquals(oldValues, new ArrayList<V>(multimap().replaceValues(k0(), values)));
assertEquals(
- size - oldValues.size() + multimap().get(key).size(),
+ size - oldValues.size() + multimap().get(k0()).size(),
multimap().size());
- assertTrue(multimap().get(key).containsAll(values));
+ assertTrue(multimap().get(k0()).containsAll(values));
}
@CollectionSize.Require(absent = ZERO)
@@ -108,7 +101,7 @@ public class MultimapReplaceValuesTester<K, V>
public void testReplaceNonEmptyValues() {
List<K> keys = Helpers.copyToList(multimap().keySet());
@SuppressWarnings("unchecked")
- List<V> values = Arrays.asList(sampleValues().e0, sampleValues().e2, sampleValues().e3);
+ List<V> values = Arrays.asList(v0(), v2(), v3());
for (K k : keys) {
resetContainer();
@@ -120,24 +113,22 @@ public class MultimapReplaceValuesTester<K, V>
assertEquals(size + values.size() - oldKeyValues.size(), multimap().size());
}
}
-
+
@MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
public void testReplaceValuesPropagatesToGet() {
- K key = sampleKeys().e0;
- Collection<V> getCollection = multimap().get(key);
+ Collection<V> getCollection = multimap().get(k0());
@SuppressWarnings("unchecked")
- List<V> values = Arrays.asList(sampleValues().e0, sampleValues().e2, sampleValues().e3);
- multimap().replaceValues(key, values);
- assertThat(getCollection).has().exactly(
- sampleValues().e0, sampleValues().e2, sampleValues().e3);
+ List<V> values = Arrays.asList(v0(), v2(), v3());
+ multimap().replaceValues(k0(), values);
+ assertContentsAnyOrder(getCollection, v0(), v2(), v3());
}
@MapFeature.Require(absent = SUPPORTS_REMOVE)
@CollectionSize.Require(absent = ZERO)
public void testReplaceValuesRemoveNotSupported() {
- List<V> values = Collections.singletonList(sampleValues().e3);
+ List<V> values = Collections.singletonList(v3());
try {
- multimap().replaceValues(sampleKeys().e0, values);
+ multimap().replaceValues(k0(), values);
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
// success
@@ -146,9 +137,9 @@ public class MultimapReplaceValuesTester<K, V>
@MapFeature.Require(absent = SUPPORTS_PUT)
public void testReplaceValuesPutNotSupported() {
- List<V> values = Collections.singletonList(sampleValues().e3);
+ List<V> values = Collections.singletonList(v3());
try {
- multimap().replaceValues(sampleKeys().e0, values);
+ multimap().replaceValues(k0(), values);
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
// success
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapSizeTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapSizeTester.java
index 894c165..fbcb8da 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapSizeTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapSizeTester.java
@@ -19,7 +19,8 @@ package com.google.common.collect.testing.google;
import static com.google.common.collect.testing.Helpers.mapEntry;
import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.collect.testing.features.MapFeature.*;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Multimap;
@@ -93,9 +94,9 @@ public class MultimapSizeTester<K, V> extends AbstractMultimapTester<K, V, Multi
@CollectionSize.Require(SEVERAL)
public void testSizeMultipleValues() {
resetContainer(
- mapEntry(sampleKeys().e0, sampleValues().e0),
- mapEntry(sampleKeys().e0, sampleValues().e1),
- mapEntry(sampleKeys().e0, sampleValues().e2));
+ mapEntry(k0(), v0()),
+ mapEntry(k0(), v1()),
+ mapEntry(k0(), v2()));
assertEquals(3, multimap().size());
assertEquals(3, multimap().entries().size());
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapTestSuiteBuilder.java
index 6f419f8..15261dd 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapTestSuiteBuilder.java
@@ -332,11 +332,11 @@ public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> extends
SampleElements<V> sampleValues =
((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()).sampleValues();
return new SampleElements<Entry<K, Collection<V>>>(
- mapEntry(sampleKeys.e0, createCollection(sampleValues.e0)),
- mapEntry(sampleKeys.e1, createCollection(sampleValues.e1)),
- mapEntry(sampleKeys.e2, createCollection(sampleValues.e2)),
- mapEntry(sampleKeys.e3, createCollection(sampleValues.e3)),
- mapEntry(sampleKeys.e4, createCollection(sampleValues.e4)));
+ mapEntry(sampleKeys.e0(), createCollection(sampleValues.e0())),
+ mapEntry(sampleKeys.e1(), createCollection(sampleValues.e1())),
+ mapEntry(sampleKeys.e2(), createCollection(sampleValues.e2())),
+ mapEntry(sampleKeys.e3(), createCollection(sampleValues.e3())),
+ mapEntry(sampleKeys.e4(), createCollection(sampleValues.e4())));
}
@Override
@@ -444,8 +444,8 @@ public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> extends
@Override
public Collection<V> create(Object... elements) {
- K k =
- ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()).sampleKeys().e0;
+ K k = ((TestMultimapGenerator<K, V, M>)
+ multimapGenerator.getInnerGenerator()).sampleKeys().e0();
Entry<K, V>[] entries = new Entry[elements.length];
for (int i = 0; i < elements.length; i++) {
entries[i] = mapEntry(k, (V) elements[i]);
@@ -462,8 +462,8 @@ public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> extends
@Override
public Iterable<V> order(List<V> insertionOrder) {
- K k =
- ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()).sampleKeys().e0;
+ K k = ((TestMultimapGenerator<K, V, M>)
+ multimapGenerator.getInnerGenerator()).sampleKeys().e0();
List<Entry<K, V>> entries = new ArrayList<Entry<K, V>>();
for (V v : insertionOrder) {
entries.add(mapEntry(k, v));
@@ -570,7 +570,7 @@ public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> extends
@Override
public Iterable<V> order(List<V> insertionOrder) {
K k = ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator())
- .sampleKeys().e0;
+ .sampleKeys().e0();
List<Entry<K, V>> entries = new ArrayList<Entry<K, V>>();
for (V v : insertionOrder) {
entries.add(mapEntry(k, v));
@@ -587,7 +587,7 @@ public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> extends
public Collection<V> create(Object... elements) {
Entry<K, V>[] array = multimapGenerator.createArray(elements.length);
K k = ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator())
- .sampleKeys().e0;
+ .sampleKeys().e0();
for (int i = 0; i < elements.length; i++) {
array[i] = mapEntry(k, (V) elements[i]);
}
@@ -608,7 +608,7 @@ public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> extends
public Collection<V> create(Object... elements) {
Entry<K, V>[] array = multimapGenerator.createArray(elements.length);
K k = ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator())
- .sampleKeys().e0;
+ .sampleKeys().e0();
for (int i = 0; i < elements.length; i++) {
array[i] = mapEntry(k, (V) elements[i]);
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapToStringTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapToStringTester.java
index 29896f3..b85a1ff 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapToStringTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapToStringTester.java
@@ -38,7 +38,8 @@ public class MultimapToStringTester<K, V> extends AbstractMultimapTester<K, V, M
@CollectionSize.Require(ONE)
public void testToStringSingleton() {
- assertEquals("{" + sampleKeys().e0 + "=[" + sampleValues().e0 + "]}", multimap().toString());
+ assertEquals(
+ "{" + k0() + "=[" + v0() + "]}", multimap().toString());
}
@CollectionSize.Require(absent = ZERO)
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultimapValuesTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultimapValuesTester.java
index e7da59e..f0b791d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultimapValuesTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultimapValuesTester.java
@@ -14,10 +14,11 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
+import static com.google.common.collect.testing.Helpers.assertEqualInOrder;
import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
import static com.google.common.collect.testing.features.CollectionSize.ONE;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.Lists;
@@ -41,19 +42,18 @@ public class MultimapValuesTester<K, V> extends AbstractMultimapTester<K, V, Mul
for (Map.Entry<K, V> entry : getSampleElements()) {
expected.add(entry.getValue());
}
- assertThat(multimap().values()).has().exactlyAs(expected);
+ assertEqualIgnoringOrder(expected, multimap().values());
}
-
+
@CollectionFeature.Require(KNOWN_ORDER)
public void testValuesInOrder() {
List<V> expected = Lists.newArrayList();
for (Map.Entry<K, V> entry : getOrderedElements()) {
expected.add(entry.getValue());
}
- assertThat(multimap().values()).has().exactlyAs(expected).inOrder();
+ assertEqualInOrder(expected, multimap().values());
}
-
-
+
@CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
@CollectionSize.Require(ONE)
public void testValuesIteratorRemove() {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetAddTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetAddTester.java
index 365e0a3..a11276f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetAddTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetAddTester.java
@@ -34,45 +34,45 @@ public class MultisetAddTester<E> extends AbstractMultisetTester<E> {
@CollectionFeature.Require(absent = SUPPORTS_ADD)
public void testAddUnsupported() {
try {
- getMultiset().add(samples.e0);
+ getMultiset().add(e0());
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {}
}
@CollectionFeature.Require(SUPPORTS_ADD)
public void testAddMeansAddOne() {
- int originalCount = getMultiset().count(samples.e0);
- assertTrue(getMultiset().add(samples.e0));
- assertEquals(originalCount + 1, getMultiset().count(samples.e0));
+ int originalCount = getMultiset().count(e0());
+ assertTrue(getMultiset().add(e0()));
+ assertEquals(originalCount + 1, getMultiset().count(e0()));
}
@CollectionFeature.Require(SUPPORTS_ADD)
public void testAddOccurrencesZero() {
- int originalCount = getMultiset().count(samples.e0);
- assertEquals("old count", originalCount, getMultiset().add(samples.e0, 0));
+ int originalCount = getMultiset().count(e0());
+ assertEquals("old count", originalCount, getMultiset().add(e0(), 0));
expectUnchanged();
}
@CollectionFeature.Require(SUPPORTS_ADD)
public void testAddOccurrences() {
- int originalCount = getMultiset().count(samples.e0);
- assertEquals("old count", originalCount, getMultiset().add(samples.e0, 2));
- assertEquals("old count", originalCount + 2, getMultiset().count(samples.e0));
+ int originalCount = getMultiset().count(e0());
+ assertEquals("old count", originalCount, getMultiset().add(e0(), 2));
+ assertEquals("old count", originalCount + 2, getMultiset().count(e0()));
}
@CollectionFeature.Require(SUPPORTS_ADD)
public void testAddSeveralTimes() {
- int originalCount = getMultiset().count(samples.e0);
- assertEquals(originalCount, getMultiset().add(samples.e0, 2));
- assertTrue(getMultiset().add(samples.e0));
- assertEquals(originalCount + 3, getMultiset().add(samples.e0, 1));
- assertEquals(originalCount + 4, getMultiset().count(samples.e0));
+ int originalCount = getMultiset().count(e0());
+ assertEquals(originalCount, getMultiset().add(e0(), 2));
+ assertTrue(getMultiset().add(e0()));
+ assertEquals(originalCount + 3, getMultiset().add(e0(), 1));
+ assertEquals(originalCount + 4, getMultiset().count(e0()));
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
public void testAddOccurrences_unsupported() {
try {
- getMultiset().add(samples.e0, 2);
+ getMultiset().add(e0(), 2);
fail("unsupported multiset.add(E, int) didn't throw exception");
} catch (UnsupportedOperationException required) {}
}
@@ -80,19 +80,19 @@ public class MultisetAddTester<E> extends AbstractMultisetTester<E> {
@CollectionFeature.Require(SUPPORTS_ADD)
public void testAddOccurrencesNegative() {
try {
- getMultiset().add(samples.e0, -1);
+ getMultiset().add(e0(), -1);
fail("multiset.add(E, -1) didn't throw an exception");
} catch (IllegalArgumentException required) {}
}
@CollectionFeature.Require(SUPPORTS_ADD)
public void testAddTooMany() {
- getMultiset().add(samples.e3, Integer.MAX_VALUE);
+ getMultiset().add(e3(), Integer.MAX_VALUE);
try {
- getMultiset().add(samples.e3);
+ getMultiset().add(e3());
fail();
} catch (IllegalArgumentException expected) {}
- assertEquals(Integer.MAX_VALUE, getMultiset().count(samples.e3));
+ assertEquals(Integer.MAX_VALUE, getMultiset().count(e3()));
assertEquals(Integer.MAX_VALUE, getMultiset().size());
}
@@ -110,14 +110,14 @@ public class MultisetAddTester<E> extends AbstractMultisetTester<E> {
@CollectionFeature.Require(SUPPORTS_ADD)
public void testAddAll_nonEmptyList() {
- assertTrue(getMultiset().addAll(Arrays.asList(samples.e3, samples.e4, samples.e3)));
- expectAdded(samples.e3, samples.e4, samples.e3);
+ assertTrue(getMultiset().addAll(Arrays.asList(e3(), e4(), e3())));
+ expectAdded(e3(), e4(), e3());
}
@CollectionFeature.Require(SUPPORTS_ADD)
public void testAddAll_nonEmptyMultiset() {
assertTrue(getMultiset().addAll(
- getSubjectGenerator().create(samples.e3, samples.e4, samples.e3)));
- expectAdded(samples.e3, samples.e4, samples.e3);
+ getSubjectGenerator().create(e3(), e4(), e3())));
+ expectAdded(e3(), e4(), e3());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetContainsTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetContainsTester.java
index 11cb686..5e4910e 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetContainsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetContainsTester.java
@@ -31,11 +31,11 @@ public class MultisetContainsTester<E> extends AbstractMultisetTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testContainsAllMultisetIgnoresFrequency() {
assertTrue(getMultiset()
- .containsAll(getSubjectGenerator().create(samples.e0, samples.e0, samples.e0)));
+ .containsAll(getSubjectGenerator().create(e0(), e0(), e0())));
}
@CollectionSize.Require(absent = ZERO)
public void testContainsAllListIgnoresFrequency() {
- assertTrue(getMultiset().containsAll(Arrays.asList(samples.e0, samples.e0, samples.e0)));
+ assertTrue(getMultiset().containsAll(Arrays.asList(e0(), e0(), e0())));
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetCountTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetCountTester.java
index e1ceb81..ffeee88 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetCountTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetCountTester.java
@@ -42,20 +42,20 @@ public class MultisetCountTester<E> extends AbstractMultisetTester<E> {
public void testCount_0() {
assertEquals("multiset.count(missing) didn't return 0",
- 0, getMultiset().count(samples.e3));
+ 0, getMultiset().count(e3()));
}
@CollectionSize.Require(absent = ZERO)
public void testCount_1() {
assertEquals("multiset.count(present) didn't return 1",
- 1, getMultiset().count(samples.e0));
+ 1, getMultiset().count(e0()));
}
@CollectionSize.Require(SEVERAL)
public void testCount_3() {
initThreeCopies();
assertEquals("multiset.count(thriceContained) didn't return 3",
- 3, getMultiset().count(samples.e0));
+ 3, getMultiset().count(e0()));
}
@CollectionFeature.Require(ALLOWS_NULL_QUERIES)
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetElementSetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetElementSetTester.java
index 0ad79cc..29cb7e4 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetElementSetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetElementSetTester.java
@@ -16,11 +16,11 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertEmpty;
import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ADD;
import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.testing.features.CollectionFeature;
@@ -31,7 +31,7 @@ import java.util.Set;
/**
* Tests for {@code Multiset.elementSet()} not covered by the derived {@code SetTestSuiteBuilder}.
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible
@@ -39,26 +39,26 @@ public class MultisetElementSetTester<E> extends AbstractMultisetTester<E> {
@CollectionFeature.Require(SUPPORTS_ADD)
public void testElementSetReflectsAddAbsent() {
Set<E> elementSet = getMultiset().elementSet();
- assertFalse(elementSet.contains(samples.e3));
- getMultiset().add(samples.e3, 4);
- assertTrue(elementSet.contains(samples.e3));
+ assertFalse(elementSet.contains(e3()));
+ getMultiset().add(e3(), 4);
+ assertTrue(elementSet.contains(e3()));
}
-
+
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testElementSetReflectsRemove() {
Set<E> elementSet = getMultiset().elementSet();
- assertTrue(elementSet.contains(samples.e0));
- getMultiset().removeAll(Collections.singleton(samples.e0));
- assertFalse(elementSet.contains(samples.e0));
+ assertTrue(elementSet.contains(e0()));
+ getMultiset().removeAll(Collections.singleton(e0()));
+ assertFalse(elementSet.contains(e0()));
}
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testElementSetRemovePropagatesToMultiset() {
Set<E> elementSet = getMultiset().elementSet();
- assertTrue(elementSet.remove(samples.e0));
- assertFalse(getMultiset().contains(samples.e0));
+ assertTrue(elementSet.remove(e0()));
+ assertFalse(getMultiset().contains(e0()));
}
@CollectionSize.Require(SEVERAL)
@@ -66,20 +66,20 @@ public class MultisetElementSetTester<E> extends AbstractMultisetTester<E> {
public void testElementSetRemoveDuplicatePropagatesToMultiset() {
initThreeCopies();
Set<E> elementSet = getMultiset().elementSet();
- assertTrue(elementSet.remove(samples.e0));
- assertThat(getMultiset()).isEmpty();
+ assertTrue(elementSet.remove(e0()));
+ assertEmpty(getMultiset());
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testElementSetRemoveAbsent() {
Set<E> elementSet = getMultiset().elementSet();
- assertFalse(elementSet.remove(samples.e3));
+ assertFalse(elementSet.remove(e3()));
expectUnchanged();
}
-
+
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testElementSetClear() {
getMultiset().elementSet().clear();
- assertThat(getMultiset()).isEmpty();
+ assertEmpty(getMultiset());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetEntrySetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetEntrySetTester.java
index e172243..b1a8a90 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetEntrySetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetEntrySetTester.java
@@ -57,7 +57,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
"non-empty multiset.entrySet() iterator.hasNext() returned false",
iterator.hasNext());
assertEquals("multiset.entrySet() iterator.next() returned incorrect entry",
- Multisets.immutableEntry(samples.e0, 1), iterator.next());
+ Multisets.immutableEntry(e0(), 1), iterator.next());
assertFalse(
"size 1 multiset.entrySet() iterator.hasNext() returned true "
+ "after next()",
@@ -74,10 +74,10 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
assertTrue(
"multiset.entrySet.remove(presentEntry) returned false",
getMultiset().entrySet().remove(
- Multisets.immutableEntry(samples.e0, 1)));
+ Multisets.immutableEntry(e0(), 1)));
assertFalse(
"multiset contains element after removing its entry",
- getMultiset().contains(samples.e0));
+ getMultiset().contains(e0()));
}
@CollectionSize.Require(absent = ZERO)
@@ -86,10 +86,10 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
assertFalse(
"multiset.entrySet.remove(missingEntry) returned true",
getMultiset().entrySet().remove(
- Multisets.immutableEntry(samples.e0, 2)));
+ Multisets.immutableEntry(e0(), 2)));
assertTrue(
"multiset didn't contain element after removing a missing entry",
- getMultiset().contains(samples.e0));
+ getMultiset().contains(e0()));
}
@CollectionSize.Require(absent = ZERO)
@@ -98,10 +98,10 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
assertTrue(
"multiset.entrySet.removeAll(presentEntry) returned false",
getMultiset().entrySet().removeAll(
- Collections.singleton(Multisets.immutableEntry(samples.e0, 1))));
+ Collections.singleton(Multisets.immutableEntry(e0(), 1))));
assertFalse(
"multiset contains element after removing its entry",
- getMultiset().contains(samples.e0));
+ getMultiset().contains(e0()));
}
@CollectionSize.Require(absent = ZERO)
@@ -110,10 +110,10 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
assertFalse(
"multiset.entrySet.remove(missingEntry) returned true",
getMultiset().entrySet().removeAll(
- Collections.singleton(Multisets.immutableEntry(samples.e0, 2))));
+ Collections.singleton(Multisets.immutableEntry(e0(), 2))));
assertTrue(
"multiset didn't contain element after removing a missing entry",
- getMultiset().contains(samples.e0));
+ getMultiset().contains(e0()));
}
@CollectionSize.Require(ONE)
@@ -122,10 +122,10 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
assertFalse(
"multiset.entrySet.retainAll(presentEntry) returned false",
getMultiset().entrySet().retainAll(
- Collections.singleton(Multisets.immutableEntry(samples.e0, 1))));
+ Collections.singleton(Multisets.immutableEntry(e0(), 1))));
assertTrue(
"multiset doesn't contains element after retaining its entry",
- getMultiset().contains(samples.e0));
+ getMultiset().contains(e0()));
}
@CollectionSize.Require(ONE)
@@ -134,10 +134,10 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
assertTrue(
"multiset.entrySet.retainAll(missingEntry) returned true",
getMultiset().entrySet().retainAll(
- Collections.singleton(Multisets.immutableEntry(samples.e0, 2))));
+ Collections.singleton(Multisets.immutableEntry(e0(), 2))));
assertFalse(
"multiset contains element after retaining a different entry",
- getMultiset().contains(samples.e0));
+ getMultiset().contains(e0()));
}
@CollectionSize.Require(SEVERAL)
@@ -145,12 +145,12 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
@MultisetFeature.Require(ENTRIES_ARE_VIEWS)
public void testEntryViewReflectsRemove() {
initThreeCopies();
- assertEquals(3, getMultiset().count(samples.e0));
+ assertEquals(3, getMultiset().count(e0()));
Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
assertEquals(3, entry.getCount());
- assertTrue(getMultiset().remove(samples.e0));
+ assertTrue(getMultiset().remove(e0()));
assertEquals(2, entry.getCount());
- assertTrue(getMultiset().elementSet().remove(samples.e0));
+ assertTrue(getMultiset().elementSet().remove(e0()));
assertEquals(0, entry.getCount());
}
@@ -159,7 +159,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
@MultisetFeature.Require(ENTRIES_ARE_VIEWS)
public void testEntryReflectsIteratorRemove() {
initThreeCopies();
- assertEquals(3, getMultiset().count(samples.e0));
+ assertEquals(3, getMultiset().count(e0()));
Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
assertEquals(3, entry.getCount());
Iterator<E> itr = getMultiset().iterator();
@@ -178,7 +178,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
@MultisetFeature.Require(ENTRIES_ARE_VIEWS)
public void testEntryReflectsClear() {
initThreeCopies();
- assertEquals(3, getMultiset().count(samples.e0));
+ assertEquals(3, getMultiset().count(e0()));
Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
assertEquals(3, entry.getCount());
getMultiset().clear();
@@ -190,7 +190,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
@MultisetFeature.Require(ENTRIES_ARE_VIEWS)
public void testEntryReflectsEntrySetClear() {
initThreeCopies();
- assertEquals(3, getMultiset().count(samples.e0));
+ assertEquals(3, getMultiset().count(e0()));
Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
assertEquals(3, entry.getCount());
getMultiset().entrySet().clear();
@@ -202,7 +202,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
@MultisetFeature.Require(ENTRIES_ARE_VIEWS)
public void testEntryReflectsEntrySetIteratorRemove() {
initThreeCopies();
- assertEquals(3, getMultiset().count(samples.e0));
+ assertEquals(3, getMultiset().count(e0()));
Iterator<Multiset.Entry<E>> entryItr = getMultiset().entrySet().iterator();
Multiset.Entry<E> entry = entryItr.next();
entryItr.remove();
@@ -214,7 +214,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
@MultisetFeature.Require(ENTRIES_ARE_VIEWS)
public void testEntryReflectsElementSetClear() {
initThreeCopies();
- assertEquals(3, getMultiset().count(samples.e0));
+ assertEquals(3, getMultiset().count(e0()));
Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
assertEquals(3, entry.getCount());
getMultiset().elementSet().clear();
@@ -226,7 +226,7 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
@MultisetFeature.Require(ENTRIES_ARE_VIEWS)
public void testEntryReflectsElementSetIteratorRemove() {
initThreeCopies();
- assertEquals(3, getMultiset().count(samples.e0));
+ assertEquals(3, getMultiset().count(e0()));
Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
assertEquals(3, entry.getCount());
Iterator<E> elementItr = getMultiset().elementSet().iterator();
@@ -240,14 +240,14 @@ public class MultisetEntrySetTester<E> extends AbstractMultisetTester<E> {
@MultisetFeature.Require(ENTRIES_ARE_VIEWS)
public void testEntryReflectsRemoveThenAdd() {
initThreeCopies();
- assertEquals(3, getMultiset().count(samples.e0));
+ assertEquals(3, getMultiset().count(e0()));
Multiset.Entry<E> entry = Iterables.getOnlyElement(getMultiset().entrySet());
assertEquals(3, entry.getCount());
- assertTrue(getMultiset().remove(samples.e0));
+ assertTrue(getMultiset().remove(e0()));
assertEquals(2, entry.getCount());
- assertTrue(getMultiset().elementSet().remove(samples.e0));
+ assertTrue(getMultiset().elementSet().remove(e0()));
assertEquals(0, entry.getCount());
- getMultiset().add(samples.e0, 2);
+ getMultiset().add(e0(), 2);
assertEquals(2, entry.getCount());
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetIteratorTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetIteratorTester.java
index 2df8b42..2ea2168 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetIteratorTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetIteratorTester.java
@@ -14,13 +14,14 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.IteratorFeature.MODIFIABLE;
+import static com.google.common.collect.testing.IteratorFeature.UNMODIFIABLE;
import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.testing.Helpers;
-import com.google.common.collect.testing.IteratorFeature;
import com.google.common.collect.testing.IteratorTester;
import com.google.common.collect.testing.features.CollectionFeature;
@@ -40,12 +41,12 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
@SuppressWarnings("unchecked")
@CollectionFeature.Require({SUPPORTS_ITERATOR_REMOVE, KNOWN_ORDER})
public void testRemovingIteratorKnownOrder() {
- new IteratorTester<E>(4, IteratorFeature.MODIFIABLE, getSubjectGenerator().order(
- Arrays.asList(samples.e0, samples.e1, samples.e1, samples.e2)),
+ new IteratorTester<E>(4, MODIFIABLE, getSubjectGenerator().order(
+ Arrays.asList(e0(), e1(), e1(), e2())),
IteratorTester.KnownOrder.KNOWN_ORDER) {
@Override
protected Iterator<E> newTargetIterator() {
- return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+ return getSubjectGenerator().create(e0(), e1(), e1(), e2())
.iterator();
}
}.test();
@@ -54,11 +55,11 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
@SuppressWarnings("unchecked")
@CollectionFeature.Require(value = SUPPORTS_ITERATOR_REMOVE, absent = KNOWN_ORDER)
public void testRemovingIteratorUnknownOrder() {
- new IteratorTester<E>(4, IteratorFeature.MODIFIABLE, Arrays.asList(samples.e0, samples.e1,
- samples.e1, samples.e2), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
+ new IteratorTester<E>(4, MODIFIABLE, Arrays.asList(e0(), e1(),
+ e1(), e2()), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
@Override
protected Iterator<E> newTargetIterator() {
- return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+ return getSubjectGenerator().create(e0(), e1(), e1(), e2())
.iterator();
}
}.test();
@@ -67,12 +68,12 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
@SuppressWarnings("unchecked")
@CollectionFeature.Require(value = KNOWN_ORDER, absent = SUPPORTS_ITERATOR_REMOVE)
public void testIteratorKnownOrder() {
- new IteratorTester<E>(4, IteratorFeature.UNMODIFIABLE, getSubjectGenerator().order(
- Arrays.asList(samples.e0, samples.e1, samples.e1, samples.e2)),
+ new IteratorTester<E>(4, UNMODIFIABLE, getSubjectGenerator().order(
+ Arrays.asList(e0(), e1(), e1(), e2())),
IteratorTester.KnownOrder.KNOWN_ORDER) {
@Override
protected Iterator<E> newTargetIterator() {
- return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+ return getSubjectGenerator().create(e0(), e1(), e1(), e2())
.iterator();
}
}.test();
@@ -81,11 +82,11 @@ public class MultisetIteratorTester<E> extends AbstractMultisetTester<E> {
@SuppressWarnings("unchecked")
@CollectionFeature.Require(absent = {SUPPORTS_ITERATOR_REMOVE, KNOWN_ORDER})
public void testIteratorUnknownOrder() {
- new IteratorTester<E>(4, IteratorFeature.UNMODIFIABLE, Arrays.asList(samples.e0, samples.e1,
- samples.e1, samples.e2), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
+ new IteratorTester<E>(4, UNMODIFIABLE, Arrays.asList(e0(), e1(),
+ e1(), e2()), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
@Override
protected Iterator<E> newTargetIterator() {
- return getSubjectGenerator().create(samples.e0, samples.e1, samples.e1, samples.e2)
+ return getSubjectGenerator().create(e0(), e1(), e1(), e2())
.iterator();
}
}.test();
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetNavigationTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetNavigationTester.java
index 9c844e8..efb2e64 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetNavigationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetNavigationTester.java
@@ -109,8 +109,8 @@ public class MultisetNavigationTester<E> extends AbstractMultisetTester<E> {
@CollectionSize.Require(ZERO)
public void testEmptyMultisetNearby() {
for (BoundType type : BoundType.values()) {
- assertNull(sortedMultiset.headMultiset(samples.e0, type).lastEntry());
- assertNull(sortedMultiset.tailMultiset(samples.e0, type).firstEntry());
+ assertNull(sortedMultiset.headMultiset(e0(), type).lastEntry());
+ assertNull(sortedMultiset.tailMultiset(e0(), type).firstEntry());
}
}
@@ -143,11 +143,11 @@ public class MultisetNavigationTester<E> extends AbstractMultisetTester<E> {
@CollectionSize.Require(ONE)
public void testSingletonMultisetNearby() {
- assertNull(sortedMultiset.headMultiset(samples.e0, OPEN).lastEntry());
- assertNull(sortedMultiset.tailMultiset(samples.e0, OPEN).lastEntry());
+ assertNull(sortedMultiset.headMultiset(e0(), OPEN).lastEntry());
+ assertNull(sortedMultiset.tailMultiset(e0(), OPEN).lastEntry());
- assertEquals(a, sortedMultiset.headMultiset(samples.e0, CLOSED).lastEntry());
- assertEquals(a, sortedMultiset.tailMultiset(samples.e0, CLOSED).firstEntry());
+ assertEquals(a, sortedMultiset.headMultiset(e0(), CLOSED).lastEntry());
+ assertEquals(a, sortedMultiset.tailMultiset(e0(), CLOSED).firstEntry());
}
@CollectionSize.Require(ONE)
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetReadsTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetReadsTester.java
index bdb1d28..9c05ef1 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetReadsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetReadsTester.java
@@ -38,25 +38,25 @@ public class MultisetReadsTester<E> extends AbstractMultisetTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testElementSet_contains() {
assertTrue("multiset.elementSet().contains(present) returned false",
- getMultiset().elementSet().contains(samples.e0));
+ getMultiset().elementSet().contains(e0()));
}
@CollectionSize.Require(absent = ZERO)
public void testEntrySet_contains() {
assertTrue("multiset.entrySet() didn't contain [present, 1]",
getMultiset().entrySet().contains(
- Multisets.immutableEntry(samples.e0, 1)));
+ Multisets.immutableEntry(e0(), 1)));
}
public void testEntrySet_contains_count0() {
assertFalse("multiset.entrySet() contains [missing, 0]",
getMultiset().entrySet().contains(
- Multisets.immutableEntry(samples.e3, 0)));
+ Multisets.immutableEntry(e3(), 0)));
}
public void testEntrySet_contains_nonentry() {
assertFalse("multiset.entrySet() contains a non-entry",
- getMultiset().entrySet().contains(samples.e0));
+ getMultiset().entrySet().contains(e0()));
}
public void testEntrySet_twice() {
@@ -73,7 +73,7 @@ public class MultisetReadsTester<E> extends AbstractMultisetTester<E> {
@CollectionSize.Require(ONE)
public void testEntrySet_hashCode_size1() {
assertEquals("multiset.entrySet() has incorrect hash code",
- 1 ^ samples.e0.hashCode(), getMultiset().entrySet().hashCode());
+ 1 ^ e0().hashCode(), getMultiset().entrySet().hashCode());
}
public void testEquals_yes() {
@@ -83,7 +83,7 @@ public class MultisetReadsTester<E> extends AbstractMultisetTester<E> {
public void testEquals_differentSize() {
Multiset<E> other = HashMultiset.create(getSampleElements());
- other.add(samples.e0);
+ other.add(e0());
assertFalse("multiset equals a multiset with a different size",
getMultiset().equals(other));
}
@@ -91,8 +91,8 @@ public class MultisetReadsTester<E> extends AbstractMultisetTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testEquals_differentElements() {
Multiset<E> other = HashMultiset.create(getSampleElements());
- other.remove(samples.e0);
- other.add(samples.e3);
+ other.remove(e0());
+ other.add(e3());
assertFalse("multiset equals a multiset with different elements",
getMultiset().equals(other));
}
@@ -106,6 +106,6 @@ public class MultisetReadsTester<E> extends AbstractMultisetTester<E> {
@CollectionSize.Require(ONE)
public void testHashCode_size1() {
assertEquals("multiset has incorrect hash code",
- 1 ^ samples.e0.hashCode(), getMultiset().hashCode());
+ 1 ^ e0().hashCode(), getMultiset().hashCode());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetRemoveTester.java
index 7a76116..525b412 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetRemoveTester.java
@@ -16,12 +16,12 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.Helpers.assertEmpty;
import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_QUERIES;
import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES;
import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
@@ -38,32 +38,32 @@ import java.util.List;
/**
* Tests for {@code Multiset#remove}, {@code Multiset.removeAll}, and {@code Multiset.retainAll}
* not already covered by the corresponding Collection testers.
- *
+ *
* @author Jared Levy
*/
@GwtCompatible(emulated = true)
-public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
+public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemoveNegative() {
try {
- getMultiset().remove(samples.e0, -1);
+ getMultiset().remove(e0(), -1);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {}
expectUnchanged();
}
-
+
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
public void testRemoveUnsupported() {
try {
- getMultiset().remove(samples.e0, 2);
+ getMultiset().remove(e0(), 2);
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {}
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemoveZeroNoOp() {
- int originalCount = getMultiset().count(samples.e0);
- assertEquals("old count", originalCount, getMultiset().remove(samples.e0, 0));
+ int originalCount = getMultiset().count(e0());
+ assertEquals("old count", originalCount, getMultiset().remove(e0(), 0));
expectUnchanged();
}
@@ -71,10 +71,10 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemove_occurrences_present() {
assertEquals("multiset.remove(present, 2) didn't return the old count",
- 1, getMultiset().remove(samples.e0, 2));
+ 1, getMultiset().remove(e0(), 2));
assertFalse("multiset contains present after multiset.remove(present, 2)",
- getMultiset().contains(samples.e0));
- assertEquals(0, getMultiset().count(samples.e0));
+ getMultiset().contains(e0()));
+ assertEquals(0, getMultiset().count(e0()));
}
@CollectionSize.Require(SEVERAL)
@@ -82,16 +82,16 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
public void testRemove_some_occurrences_present() {
initThreeCopies();
assertEquals("multiset.remove(present, 2) didn't return the old count",
- 3, getMultiset().remove(samples.e0, 2));
+ 3, getMultiset().remove(e0(), 2));
assertTrue("multiset contains present after multiset.remove(present, 2)",
- getMultiset().contains(samples.e0));
- assertEquals(1, getMultiset().count(samples.e0));
+ getMultiset().contains(e0()));
+ assertEquals(1, getMultiset().count(e0()));
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemove_occurrences_absent() {
assertEquals("multiset.remove(absent, 0) didn't return 0",
- 0, getMultiset().remove(samples.e3, 2));
+ 0, getMultiset().remove(e3(), 2));
}
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -100,21 +100,21 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
try {
assertEquals(
"multiset.remove(absent, 2) didn't return 0 or throw an exception",
- 0, getMultiset().remove(samples.e3, 2));
+ 0, getMultiset().remove(e3(), 2));
} catch (UnsupportedOperationException ok) {}
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemove_occurrences_0() {
- int oldCount = getMultiset().count(samples.e0);
+ int oldCount = getMultiset().count(e0());
assertEquals("multiset.remove(E, 0) didn't return the old count",
- oldCount, getMultiset().remove(samples.e0, 0));
+ oldCount, getMultiset().remove(e0(), 0));
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemove_occurrences_negative() {
try {
- getMultiset().remove(samples.e0, -1);
+ getMultiset().remove(e0(), -1);
fail("multiset.remove(E, -1) didn't throw an exception");
} catch (IllegalArgumentException required) {}
}
@@ -124,7 +124,7 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
assertEquals("multiset.remove(wrongType, 1) didn't return 0",
0, getMultiset().remove(WrongType.VALUE, 1));
}
-
+
@CollectionSize.Require(absent = ZERO)
@CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
public void testRemove_nullPresent() {
@@ -134,12 +134,12 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
getMultiset().contains(null));
assertEquals(0, getMultiset().count(null));
}
-
+
@CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_QUERIES})
public void testRemove_nullAbsent() {
assertEquals(0, getMultiset().remove(null, 2));
}
-
+
@CollectionFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_QUERIES)
public void testRemove_nullForbidden() {
try {
@@ -147,24 +147,24 @@ public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
fail("Expected NullPointerException");
} catch (NullPointerException expected) {}
}
-
+
@CollectionSize.Require(SEVERAL)
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemoveAllIgnoresCount() {
initThreeCopies();
- assertTrue(getMultiset().removeAll(Collections.singleton(samples.e0)));
- assertThat(getMultiset()).isEmpty();
+ assertTrue(getMultiset().removeAll(Collections.singleton(e0())));
+ assertEmpty(getMultiset());
}
-
+
@CollectionSize.Require(SEVERAL)
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRetainAllIgnoresCount() {
initThreeCopies();
List<E> contents = Helpers.copyToList(getMultiset());
- assertFalse(getMultiset().retainAll(Collections.singleton(samples.e0)));
+ assertFalse(getMultiset().retainAll(Collections.singleton(e0())));
expectContents(contents);
}
-
+
/**
* Returns {@link Method} instances for the remove tests that assume multisets
* support duplicates so that the test of {@code Multisets.forSet()} can
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetSetCountConditionallyTester.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetSetCountConditionallyTester.java
index 3973434..6a07397 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetSetCountConditionallyTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetSetCountConditionallyTester.java
@@ -51,7 +51,7 @@ public class MultisetSetCountConditionallyTester<E> extends
private void assertSetCountNegativeOldCount() {
try {
- getMultiset().setCount(samples.e3, -1, 1);
+ getMultiset().setCount(e3(), -1, 1);
fail("calling setCount() with a negative oldCount should throw "
+ "IllegalArgumentException");
} catch (IllegalArgumentException expected) {
@@ -78,7 +78,7 @@ public class MultisetSetCountConditionallyTester<E> extends
@CollectionFeature.Require(SUPPORTS_ADD)
public void testSetCountConditional_oldCountTooLarge() {
assertFalse("setCount() with a too-large oldCount should return false",
- getMultiset().setCount(samples.e0, 2, 3));
+ getMultiset().setCount(e0(), 2, 3));
expectUnchanged();
}
@@ -86,7 +86,7 @@ public class MultisetSetCountConditionallyTester<E> extends
@CollectionFeature.Require(SUPPORTS_ADD)
public void testSetCountConditional_oldCountTooSmallZero() {
assertFalse("setCount() with a too-small oldCount should return false",
- getMultiset().setCount(samples.e0, 0, 2));
+ getMultiset().setCount(e0(), 0, 2));
expectUnchanged();
}
@@ -95,8 +95,8 @@ public class MultisetSetCountConditionallyTester<E> extends
public void testSetCountConditional_oldCountTooSmallNonzero() {
initThreeCopies();
assertFalse("setCount() with a too-small oldCount should return false",
- getMultiset().setCount(samples.e0, 1, 5));
- expectContents(nCopies(3, samples.e0));
+ getMultiset().setCount(e0(), 1, 5));
+ expectContents(nCopies(3, e0()));
}
/*
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/MultisetTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/google/MultisetTestSuiteBuilder.java
index f460b5d..007a29a 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/MultisetTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/MultisetTestSuiteBuilder.java
@@ -205,11 +205,11 @@ public class MultisetTestSuiteBuilder<E> extends
public SampleElements<Multiset.Entry<E>> samples() {
SampleElements<E> samples = gen.samples();
return new SampleElements<Multiset.Entry<E>>(
- Multisets.immutableEntry(samples.e0, 3),
- Multisets.immutableEntry(samples.e1, 4),
- Multisets.immutableEntry(samples.e2, 1),
- Multisets.immutableEntry(samples.e3, 5),
- Multisets.immutableEntry(samples.e4, 2));
+ Multisets.immutableEntry(samples.e0(), 3),
+ Multisets.immutableEntry(samples.e1(), 4),
+ Multisets.immutableEntry(samples.e2(), 1),
+ Multisets.immutableEntry(samples.e3(), 5),
+ Multisets.immutableEntry(samples.e4(), 2));
}
@Override
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapAsMapTester.java b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapAsMapTester.java
index 29cced4..50df987 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapAsMapTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapAsMapTester.java
@@ -67,12 +67,12 @@ public class SetMultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, S
@CollectionSize.Require(SEVERAL)
public void testEquals() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e1, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k1(), v0()),
+ Helpers.mapEntry(k0(), v3()));
Map<K, Collection<V>> expected = Maps.newHashMap();
- expected.put(sampleKeys().e0, Sets.newHashSet(sampleValues().e0, sampleValues().e3));
- expected.put(sampleKeys().e1, Sets.newHashSet(sampleValues().e0));
+ expected.put(k0(), Sets.newHashSet(v0(), v3()));
+ expected.put(k1(), Sets.newHashSet(v0()));
new EqualsTester()
.addEqualityGroup(expected, multimap().asMap())
.testEquals();
@@ -81,16 +81,16 @@ public class SetMultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, S
@CollectionSize.Require(SEVERAL)
public void testEntrySetEquals() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e1, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k1(), v0()),
+ Helpers.mapEntry(k0(), v3()));
Set<Entry<K, Collection<V>>> expected = Sets.newHashSet();
expected.add(Helpers.mapEntry(
- sampleKeys().e0,
- (Collection<V>) Sets.newHashSet(sampleValues().e0, sampleValues().e3)));
+ k0(),
+ (Collection<V>) Sets.newHashSet(v0(), v3())));
expected.add(Helpers.mapEntry(
- sampleKeys().e1,
- (Collection<V>) Sets.newHashSet(sampleValues().e0)));
+ k1(),
+ (Collection<V>) Sets.newHashSet(v0())));
new EqualsTester()
.addEqualityGroup(expected, multimap().asMap().entrySet())
.testEquals();
@@ -100,14 +100,14 @@ public class SetMultimapAsMapTester<K, V> extends AbstractMultimapTester<K, V, S
@MapFeature.Require(SUPPORTS_REMOVE)
public void testValuesRemove() {
resetContainer(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e1, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e3));
- assertTrue(multimap().asMap().values().remove(Collections.singleton(sampleValues().e0)));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k1(), v0()),
+ Helpers.mapEntry(k0(), v3()));
+ assertTrue(multimap().asMap().values().remove(Collections.singleton(v0())));
assertEquals(2, multimap().size());
assertEquals(
Collections.singletonMap(
- sampleKeys().e0, Sets.newHashSet(sampleValues().e0, sampleValues().e3)),
+ k0(), Sets.newHashSet(v0(), v3())),
multimap().asMap());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapEqualsTester.java b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapEqualsTester.java
index 6d832d3..c1ddbe6 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapEqualsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapEqualsTester.java
@@ -33,13 +33,13 @@ public class SetMultimapEqualsTester<K, V>
@CollectionSize.Require(SEVERAL)
public void testOrderingDoesntAffectEqualsComparisons() {
SetMultimap<K, V> multimap1 = getSubjectGenerator().create(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e4));
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v1()),
+ Helpers.mapEntry(k0(), v4()));
SetMultimap<K, V> multimap2 = getSubjectGenerator().create(
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e1),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e0),
- Helpers.mapEntry(sampleKeys().e0, sampleValues().e4));
+ Helpers.mapEntry(k0(), v1()),
+ Helpers.mapEntry(k0(), v0()),
+ Helpers.mapEntry(k0(), v4()));
new EqualsTester()
.addEqualityGroup(multimap1, multimap2)
.testEquals();
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutAllTester.java b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutAllTester.java
index 8e56542..b518a09 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutAllTester.java
@@ -36,10 +36,8 @@ public class SetMultimapPutAllTester<K, V>
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAllHandlesDuplicates() {
- V v0 = sampleValues().e3;
- V v1 = sampleValues().e2;
@SuppressWarnings("unchecked")
- List<V> valuesToPut = Arrays.asList(v0, v1, v0);
+ List<V> valuesToPut = Arrays.asList(v0(), v1(), v0());
for (K k : sampleKeys()) {
resetContainer();
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutTester.java b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutTester.java
index 6b7b6c5..833b5e3 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapPutTester.java
@@ -42,7 +42,7 @@ public class SetMultimapPutTester<K, V>
@MapFeature.Require(SUPPORTS_PUT)
@CollectionSize.Require(absent = ZERO)
public void testPutDuplicateValuePreservesSize() {
- assertFalse(multimap().put(sampleKeys().e0, sampleValues().e0));
+ assertFalse(multimap().put(k0(), v0()));
assertEquals(getNumElements(), multimap().size());
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapReplaceValuesTester.java b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapReplaceValuesTester.java
index fa95309..31f81be 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapReplaceValuesTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SetMultimapReplaceValuesTester.java
@@ -35,15 +35,13 @@ public class SetMultimapReplaceValuesTester<K, V>
@MapFeature.Require({SUPPORTS_PUT, SUPPORTS_REMOVE})
public void testReplaceValuesHandlesDuplicates() {
- V v0 = sampleValues().e3;
- V v1 = sampleValues().e2;
@SuppressWarnings("unchecked")
- List<V> values = Arrays.asList(v0, v1, v0);
+ List<V> values = Arrays.asList(v0(), v1(), v0());
for (K k : sampleKeys()) {
resetContainer();
multimap().replaceValues(k, values);
- assertGet(k, v0, v1);
+ assertGet(k, v0(), v1());
}
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SortedMapGenerators.java b/guava-testlib/src/com/google/common/collect/testing/google/SortedMapGenerators.java
index e37ae5f..f27ab7f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SortedMapGenerators.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SortedMapGenerators.java
@@ -27,6 +27,7 @@ import com.google.common.collect.testing.TestListGenerator;
import com.google.common.collect.testing.TestStringListGenerator;
import com.google.common.collect.testing.TestStringSortedMapGenerator;
+import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import java.util.SortedMap;
@@ -53,6 +54,12 @@ public class SortedMapGenerators {
return builder.build();
}
}
+ public static class ImmutableSortedMapCopyOfEntriesGenerator
+ extends TestStringSortedMapGenerator {
+ @Override public SortedMap<String, String> create(Entry<String, String>[] entries) {
+ return ImmutableSortedMap.copyOf(Arrays.asList(entries));
+ }
+ }
public static class ImmutableSortedMapEntryListGenerator
implements TestListGenerator<Entry<String, Integer>> {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SortedMultisetTestSuiteBuilder.java b/guava-testlib/src/com/google/common/collect/testing/google/SortedMultisetTestSuiteBuilder.java
index 1b1abbd..47f354d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SortedMultisetTestSuiteBuilder.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SortedMultisetTestSuiteBuilder.java
@@ -16,6 +16,11 @@
package com.google.common.collect.testing.google;
+import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
+import static com.google.common.collect.testing.features.CollectionFeature.RESTRICTS_ELEMENTS;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS;
+
import com.google.common.collect.BoundType;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@@ -27,7 +32,6 @@ import com.google.common.collect.testing.Helpers;
import com.google.common.collect.testing.OneSizeTestContainerGenerator;
import com.google.common.collect.testing.SampleElements;
import com.google.common.collect.testing.SetTestSuiteBuilder;
-import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.Feature;
import com.google.common.testing.SerializableTester;
@@ -62,7 +66,7 @@ public class SortedMultisetTestSuiteBuilder<E> extends
@Override
public TestSuite createTestSuite() {
- withFeatures(CollectionFeature.KNOWN_ORDER);
+ withFeatures(KNOWN_ORDER);
TestSuite suite = super.createTestSuite();
for (TestSuite subSuite : createDerivedSuites(this)) {
suite.addTest(subSuite);
@@ -81,7 +85,7 @@ public class SortedMultisetTestSuiteBuilder<E> extends
@Override
TestSuite createElementSetTestSuite(FeatureSpecificTestSuiteBuilder<
?, ? extends OneSizeTestContainerGenerator<Collection<E>, E>> parentBuilder) {
- // TODO(user): make a SortedElementSetGenerator
+ // TODO(lowasser): make a SortedElementSetGenerator
return SetTestSuiteBuilder
.using(new ElementSetGenerator<E>(parentBuilder.getSubjectGenerator()))
.named(getName() + ".elementSet")
@@ -118,7 +122,7 @@ public class SortedMultisetTestSuiteBuilder<E> extends
derivedSuites.add(createDescendingSuite(parentBuilder));
}
- if (parentBuilder.getFeatures().contains(CollectionFeature.SERIALIZABLE)) {
+ if (parentBuilder.getFeatures().contains(SERIALIZABLE)) {
derivedSuites.add(createReserializedSuite(parentBuilder));
}
@@ -152,11 +156,11 @@ public class SortedMultisetTestSuiteBuilder<E> extends
Set<Feature<?>> features = new HashSet<Feature<?>>();
features.add(NoRecurse.SUBMULTISET);
- features.add(CollectionFeature.RESTRICTS_ELEMENTS);
+ features.add(RESTRICTS_ELEMENTS);
features.addAll(parentBuilder.getFeatures());
- if (!features.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS)) {
- features.remove(CollectionFeature.SERIALIZABLE);
+ if (!features.remove(SERIALIZABLE_INCLUDING_VIEWS)) {
+ features.remove(SERIALIZABLE);
}
SortedMultiset<E> emptyMultiset = (SortedMultiset<E>) delegate.create();
@@ -164,8 +168,8 @@ public class SortedMultisetTestSuiteBuilder<E> extends
SampleElements<E> samples = delegate.samples();
@SuppressWarnings("unchecked")
List<E> samplesList =
- Arrays.asList(samples.e0, samples.e1, samples.e2, samples.e3,
- samples.e4);
+ Arrays.asList(samples.e0(), samples.e1(), samples.e2(), samples.e3(),
+ samples.e4());
Collections.sort(samplesList, comparator);
final E firstInclusive = samplesList.get(0);
@@ -252,8 +256,8 @@ public class SortedMultisetTestSuiteBuilder<E> extends
Set<Feature<?>> features = new HashSet<Feature<?>>();
features.add(NoRecurse.DESCENDING);
features.addAll(parentBuilder.getFeatures());
- if (!features.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS)) {
- features.remove(CollectionFeature.SERIALIZABLE);
+ if (!features.remove(SERIALIZABLE_INCLUDING_VIEWS)) {
+ features.remove(SERIALIZABLE);
}
return SortedMultisetTestSuiteBuilder
@@ -282,8 +286,8 @@ public class SortedMultisetTestSuiteBuilder<E> extends
Set<Feature<?>> features = new HashSet<Feature<?>>();
features.addAll(parentBuilder.getFeatures());
- features.remove(CollectionFeature.SERIALIZABLE);
- features.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS);
+ features.remove(SERIALIZABLE);
+ features.remove(SERIALIZABLE_INCLUDING_VIEWS);
return SortedMultisetTestSuiteBuilder
.using(new ForwardingTestMultisetGenerator<E>(delegate) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java b/guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java
index ee703d8..27af557 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/SortedSetMultimapGetTester.java
@@ -30,6 +30,6 @@ public class SortedSetMultimapGetTester<K, V>
public void testValueComparator() {
assertEquals(
multimap().valueComparator(),
- multimap().get(sampleKeys().e0).comparator());
+ multimap().get(k0()).comparator());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/google/UnmodifiableCollectionTests.java b/guava-testlib/src/com/google/common/collect/testing/google/UnmodifiableCollectionTests.java
index b136ff3..9c19699 100644
--- a/guava-testlib/src/com/google/common/collect/testing/google/UnmodifiableCollectionTests.java
+++ b/guava-testlib/src/com/google/common/collect/testing/google/UnmodifiableCollectionTests.java
@@ -22,6 +22,7 @@ import static junit.framework.TestCase.fail;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Iterators;
import com.google.common.collect.LinkedHashMultiset;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -115,8 +116,12 @@ public class UnmodifiableCollectionTests {
Collection<E> collection, E sampleElement) {
Collection<E> siblingCollection = new ArrayList<E>();
siblingCollection.add(sampleElement);
+
Collection<E> copy = new ArrayList<E>();
- copy.addAll(collection);
+ // Avoid copy.addAll(collection), which runs afoul of an Android bug in older versions:
+ // http://b.android.com/72073 http://r.android.com/98929
+ Iterators.addAll(copy, collection.iterator());
+
try {
collection.add(sampleElement);
fail("add succeeded on unmodifiable collection");
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/AbstractListIndexOfTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/AbstractListIndexOfTester.java
index 1153d7e..28cdf9c 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/AbstractListIndexOfTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/AbstractListIndexOfTester.java
@@ -50,7 +50,7 @@ public abstract class AbstractListIndexOfTester<E>
public void testFind_no() {
assertEquals(getMethodName() + "(notPresent) should return -1",
- -1, find(samples.e3));
+ -1, find(e3()));
}
@CollectionFeature.Require(ALLOWS_NULL_VALUES)
@@ -74,7 +74,7 @@ public abstract class AbstractListIndexOfTester<E>
public void testFind_nonNullWhenNullContained() {
initCollectionWithNullElement();
assertEquals(getMethodName() + "(notPresent) should return -1",
- -1, find(samples.e3));
+ -1, find(e3()));
}
@CollectionFeature.Require(ALLOWS_NULL_VALUES)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddAllTester.java
index 4add759..ac62c67 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddAllTester.java
@@ -68,7 +68,7 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
public void testAddAll_supportedNonePresent() {
assertTrue("addAll(nonePresent) should return true",
collection.addAll(createDisjointCollection()));
- expectAdded(samples.e3, samples.e4);
+ expectAdded(e3(), e4());
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
@@ -79,23 +79,23 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- expectMissing(samples.e3, samples.e4);
+ expectMissing(e3(), e4());
}
@CollectionFeature.Require(SUPPORTS_ADD)
@CollectionSize.Require(absent = ZERO)
public void testAddAll_supportedSomePresent() {
assertTrue("addAll(somePresent) should return true",
- collection.addAll(MinimalCollection.of(samples.e3, samples.e0)));
- assertTrue("should contain " + samples.e3, collection.contains(samples.e3));
- assertTrue("should contain " + samples.e0, collection.contains(samples.e0));
+ collection.addAll(MinimalCollection.of(e3(), e0())));
+ assertTrue("should contain " + e3(), collection.contains(e3()));
+ assertTrue("should contain " + e0(), collection.contains(e0()));
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
@CollectionSize.Require(absent = ZERO)
public void testAddAll_unsupportedSomePresent() {
try {
- collection.addAll(MinimalCollection.of(samples.e3, samples.e0));
+ collection.addAll(MinimalCollection.of(e3(), e0()));
fail("addAll(somePresent) should throw");
} catch (UnsupportedOperationException expected) {
}
@@ -108,7 +108,7 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
public void testAddAllConcurrentWithIteration() {
try {
Iterator<E> iterator = collection.iterator();
- assertTrue(collection.addAll(MinimalCollection.of(samples.e3, samples.e0)));
+ assertTrue(collection.addAll(MinimalCollection.of(e3(), e0())));
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -121,7 +121,7 @@ public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
public void testAddAll_unsupportedAllPresent() {
try {
assertFalse("addAll(allPresent) should return false or throw",
- collection.addAll(MinimalCollection.of(samples.e0)));
+ collection.addAll(MinimalCollection.of(e0())));
} catch (UnsupportedOperationException tolerated) {
}
expectUnchanged();
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddTester.java
index 1d1b84b..f00e092 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionAddTester.java
@@ -47,19 +47,19 @@ public class CollectionAddTester<E> extends AbstractCollectionTester<E> {
@CollectionFeature.Require(SUPPORTS_ADD)
public void testAdd_supportedNotPresent() {
assertTrue("add(notPresent) should return true",
- collection.add(samples.e3));
- expectAdded(samples.e3);
+ collection.add(e3()));
+ expectAdded(e3());
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
public void testAdd_unsupportedNotPresent() {
try {
- collection.add(samples.e3);
+ collection.add(e3());
fail("add(notPresent) should throw");
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
@@ -67,7 +67,7 @@ public class CollectionAddTester<E> extends AbstractCollectionTester<E> {
public void testAdd_unsupportedPresent() {
try {
assertFalse("add(present) should return false or throw",
- collection.add(samples.e0));
+ collection.add(e0()));
} catch (UnsupportedOperationException tolerated) {
}
expectUnchanged();
@@ -100,7 +100,7 @@ public class CollectionAddTester<E> extends AbstractCollectionTester<E> {
public void testAddConcurrentWithIteration() {
try {
Iterator<E> iterator = collection.iterator();
- assertTrue(collection.add(samples.e3));
+ assertTrue(collection.add(e3()));
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionClearTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionClearTester.java
index 9a2a9fc..276a4aa 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionClearTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionClearTester.java
@@ -43,6 +43,8 @@ public class CollectionClearTester<E> extends AbstractCollectionTester<E> {
collection.clear();
assertTrue("After clear(), a collection should be empty.",
collection.isEmpty());
+ assertEquals(0, collection.size());
+ assertFalse(collection.iterator().hasNext());
}
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsAllTester.java
index 766b2c2..0f0efb8 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsAllTester.java
@@ -49,7 +49,7 @@ public class CollectionContainsAllTester<E>
@CollectionSize.Require(absent = ZERO)
public void testContainsAll_subset() {
assertTrue("containsAll(subset) should return true",
- collection.containsAll(MinimalCollection.of(samples.e0)));
+ collection.containsAll(MinimalCollection.of(e0())));
}
public void testContainsAll_sameElements() {
@@ -65,12 +65,12 @@ public class CollectionContainsAllTester<E>
public void testContainsAll_partialOverlap() {
assertFalse("containsAll(partialOverlap) should return false",
- collection.containsAll(MinimalCollection.of(samples.e0, samples.e3)));
+ collection.containsAll(MinimalCollection.of(e0(), e3())));
}
public void testContainsAll_disjoint() {
assertFalse("containsAll(disjoint) should return false",
- collection.containsAll(MinimalCollection.of(samples.e3)));
+ collection.containsAll(MinimalCollection.of(e3())));
}
@CollectionFeature.Require(absent = ALLOWS_NULL_QUERIES)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsTester.java
index e9806fc..fded53d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionContainsTester.java
@@ -39,12 +39,12 @@ public class CollectionContainsTester<E> extends AbstractCollectionTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testContains_yes() {
assertTrue("contains(present) should return true",
- collection.contains(samples.e0));
+ collection.contains(e0()));
}
public void testContains_no() {
assertFalse("contains(notPresent) should return false",
- collection.contains(samples.e3));
+ collection.contains(e3()));
}
@CollectionFeature.Require(ALLOWS_NULL_QUERIES)
@@ -64,7 +64,7 @@ public class CollectionContainsTester<E> extends AbstractCollectionTester<E> {
public void testContains_nonNullWhenNullContained() {
initCollectionWithNullElement();
assertFalse("contains(notPresent) should return false",
- collection.contains(samples.e3));
+ collection.contains(e3()));
}
@CollectionFeature.Require(ALLOWS_NULL_VALUES)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveAllTester.java
index 361d783..def85cf 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveAllTester.java
@@ -55,7 +55,7 @@ public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemoveAll_nonePresent() {
assertFalse("removeAll(disjointCollection) should return false",
- collection.removeAll(MinimalCollection.of(samples.e3)));
+ collection.removeAll(MinimalCollection.of(e3())));
expectUnchanged();
}
@@ -63,16 +63,16 @@ public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testRemoveAll_allPresent() {
assertTrue("removeAll(intersectingCollection) should return true",
- collection.removeAll(MinimalCollection.of(samples.e0)));
- expectMissing(samples.e0);
+ collection.removeAll(MinimalCollection.of(e0())));
+ expectMissing(e0());
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(absent = ZERO)
public void testRemoveAll_somePresent() {
assertTrue("removeAll(intersectingCollection) should return true",
- collection.removeAll(MinimalCollection.of(samples.e0, samples.e3)));
- expectMissing(samples.e0);
+ collection.removeAll(MinimalCollection.of(e0(), e3())));
+ expectMissing(e0());
}
@CollectionFeature.Require({SUPPORTS_REMOVE,
@@ -81,7 +81,7 @@ public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
public void testRemoveAllSomePresentConcurrentWithIteration() {
try {
Iterator<E> iterator = collection.iterator();
- assertTrue(collection.removeAll(MinimalCollection.of(samples.e0, samples.e3)));
+ assertTrue(collection.removeAll(MinimalCollection.of(e0(), e3())));
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -97,9 +97,9 @@ public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
public void testRemoveAll_somePresentLargeCollectionToRemove() {
assertTrue("removeAll(largeIntersectingCollection) should return true",
collection.removeAll(MinimalCollection.of(
- samples.e0, samples.e0, samples.e0,
- samples.e3, samples.e3, samples.e3)));
- expectMissing(samples.e0);
+ e0(), e0(), e0(),
+ e3(), e3(), e3())));
+ expectMissing(e0());
}
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -118,7 +118,7 @@ public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
try {
assertFalse("removeAll(disjointCollection) should return false or throw "
+ "UnsupportedOperationException",
- collection.removeAll(MinimalCollection.of(samples.e3)));
+ collection.removeAll(MinimalCollection.of(e3())));
} catch (UnsupportedOperationException tolerated) {
}
expectUnchanged();
@@ -128,13 +128,13 @@ public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testRemoveAll_unsupportedPresent() {
try {
- collection.removeAll(MinimalCollection.of(samples.e0));
+ collection.removeAll(MinimalCollection.of(e0()));
fail("removeAll(intersectingCollection) should throw "
+ "UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- assertTrue(collection.contains(samples.e0));
+ assertTrue(collection.contains(e0()));
}
/*
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveTester.java
index a1b67bc..c3bf265 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRemoveTester.java
@@ -47,10 +47,10 @@ public class CollectionRemoveTester<E> extends AbstractCollectionTester<E> {
public void testRemove_present() {
int initialSize = collection.size();
assertTrue("remove(present) should return true",
- collection.remove(samples.e0));
+ collection.remove(e0()));
assertEquals("remove(present) should decrease a collection's size by one.",
initialSize - 1, collection.size());
- expectMissing(samples.e0);
+ expectMissing(e0());
}
@CollectionFeature.Require({SUPPORTS_REMOVE,
@@ -59,7 +59,7 @@ public class CollectionRemoveTester<E> extends AbstractCollectionTester<E> {
public void testRemovePresentConcurrentWithIteration() {
try {
Iterator<E> iterator = collection.iterator();
- assertTrue(collection.remove(samples.e0));
+ assertTrue(collection.remove(e0()));
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -70,7 +70,7 @@ public class CollectionRemoveTester<E> extends AbstractCollectionTester<E> {
@CollectionFeature.Require(SUPPORTS_REMOVE)
public void testRemove_notPresent() {
assertFalse("remove(notPresent) should return false",
- collection.remove(samples.e3));
+ collection.remove(e3()));
expectUnchanged();
}
@@ -90,13 +90,13 @@ public class CollectionRemoveTester<E> extends AbstractCollectionTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testRemove_unsupported() {
try {
- collection.remove(samples.e0);
+ collection.remove(e0());
fail("remove(present) should throw UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
assertTrue("remove(present) should not remove the element",
- collection.contains(samples.e0));
+ collection.contains(e0()));
}
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -104,11 +104,11 @@ public class CollectionRemoveTester<E> extends AbstractCollectionTester<E> {
try {
assertFalse("remove(notPresent) should return false or throw "
+ "UnsupportedOperationException",
- collection.remove(samples.e3));
+ collection.remove(e3()));
} catch (UnsupportedOperationException tolerated) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
@CollectionFeature.Require(
@@ -141,7 +141,7 @@ public class CollectionRemoveTester<E> extends AbstractCollectionTester<E> {
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- assertTrue(collection.contains(samples.e0));
+ assertTrue(collection.contains(e0()));
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRetainAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRetainAllTester.java
index 73fd682..624c2ee 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRetainAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionRetainAllTester.java
@@ -80,22 +80,22 @@ public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
* MinimalCollection, which throws NullPointerException on calls to
* contains(null).
*/
- List<E> disjointList = Arrays.asList(samples.e3, samples.e4);
+ List<E> disjointList = Arrays.asList(e3(), e4());
disjoint
= new Target(disjointList, "disjoint");
superset
= new Target(MinimalCollection.of(
- samples.e0, samples.e1, samples.e2, samples.e3, samples.e4),
+ e0(), e1(), e2(), e3(), e4()),
"superset");
nonEmptyProperSubset
- = new Target(MinimalCollection.of(samples.e1), "subset");
+ = new Target(MinimalCollection.of(e1()), "subset");
sameElements
= new Target(Arrays.asList(createSamplesArray()), "sameElements");
containsDuplicates = new Target(
- MinimalCollection.of(samples.e0, samples.e0, samples.e3, samples.e3),
+ MinimalCollection.of(e0(), e0(), e3(), e3()),
"containsDuplicates");
partialOverlap
- = new Target(MinimalCollection.of(samples.e2, samples.e3),
+ = new Target(MinimalCollection.of(e2(), e3()),
"partialOverlap");
nullSingleton
= new Target(Collections.<E>singleton(null), "nullSingleton");
@@ -122,7 +122,7 @@ public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
public void testRetainAll_emptyPreviouslyNonEmpty() {
expectReturnsTrue(empty);
expectContents();
- expectMissing(samples.e0, samples.e1, samples.e2);
+ expectMissing(e0(), e1(), e2());
}
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -153,7 +153,7 @@ public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
public void testRetainAll_disjointPreviouslyNonEmpty() {
expectReturnsTrue(disjoint);
expectContents();
- expectMissing(samples.e0, samples.e1, samples.e2);
+ expectMissing(e0(), e1(), e2());
}
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -213,7 +213,7 @@ public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
@CollectionSize.Require(absent = {ZERO, ONE})
public void testRetainAll_partialOverlap() {
expectReturnsTrue(partialOverlap);
- expectContents(samples.e2);
+ expectContents(e2());
}
@CollectionFeature.Require(absent = SUPPORTS_REMOVE)
@@ -229,14 +229,14 @@ public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
@CollectionSize.Require(ONE)
public void testRetainAll_containsDuplicatesSizeOne() {
expectReturnsFalse(containsDuplicates);
- expectContents(samples.e0);
+ expectContents(e0());
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(absent = {ZERO, ONE})
public void testRetainAll_containsDuplicatesSizeSeveral() {
expectReturnsTrue(containsDuplicates);
- expectContents(samples.e0);
+ expectContents(e0());
}
// retainAll(nullSingleton)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToArrayTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToArrayTester.java
index 810dfaa..307af33 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToArrayTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToArrayTester.java
@@ -121,8 +121,8 @@ public class CollectionToArrayTester<E> extends AbstractCollectionTester<E> {
public void testToArray_oversizedArray() {
E[] array = getSubjectGenerator().createArray(getNumElements() + 2);
- array[getNumElements()] = samples.e3;
- array[getNumElements() + 1] = samples.e3;
+ array[getNumElements()] = e3();
+ array[getNumElements() + 1] = e3();
assertSame("toArray(overSizedE[]) should return the given array",
array, collection.toArray(array));
@@ -142,8 +142,8 @@ public class CollectionToArrayTester<E> extends AbstractCollectionTester<E> {
@CollectionFeature.Require(KNOWN_ORDER)
public void testToArray_oversizedArray_ordered() {
E[] array = getSubjectGenerator().createArray(getNumElements() + 2);
- array[getNumElements()] = samples.e3;
- array[getNumElements() + 1] = samples.e3;
+ array[getNumElements()] = e3();
+ array[getNumElements() + 1] = e3();
assertSame("toArray(overSizedE[]) should return the given array",
array, collection.toArray(array));
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToStringTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToStringTester.java
index 084ac6f..44d7177 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToStringTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/CollectionToStringTester.java
@@ -54,7 +54,7 @@ public class CollectionToStringTester<E> extends AbstractCollectionTester<E> {
@CollectionFeature.Require(absent = NON_STANDARD_TOSTRING)
public void testToString_size1() {
assertEquals("size1Collection.toString should return [{element}]",
- "[" + samples.e0 + "]", collection.toString());
+ "[" + e0() + "]", collection.toString());
}
@CollectionSize.Require(SEVERAL)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapPutIfAbsentTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapPutIfAbsentTester.java
new file mode 100644
index 0000000..c2cc16f
--- /dev/null
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapPutIfAbsentTester.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.collect.testing.testers;
+
+import static com.google.common.collect.testing.features.CollectionSize.ZERO;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
+import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.testing.AbstractMapTester;
+import com.google.common.collect.testing.features.CollectionSize;
+import com.google.common.collect.testing.features.MapFeature;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * A generic JUnit test which tests {@code putIfAbsent} operations on a concurrent map. Can't be
+ * invoked directly; please see
+ * {@link com.google.common.collect.testing.ConcurrentMapTestSuiteBuilder}.
+ *
+ * @author Louis Wasserman
+ */
+ at GwtCompatible
+public class ConcurrentMapPutIfAbsentTester<K, V> extends AbstractMapTester<K, V> {
+ @Override
+ protected ConcurrentMap<K, V> getMap() {
+ return (ConcurrentMap<K, V>) super.getMap();
+ }
+
+ @MapFeature.Require(SUPPORTS_PUT)
+ public void testPutIfAbsent_supportedAbsent() {
+ assertNull("putIfAbsent(notPresent, value) should return null", putIfAbsent(e3()));
+ expectAdded(e3());
+ }
+
+ @MapFeature.Require(SUPPORTS_PUT)
+ @CollectionSize.Require(absent = ZERO)
+ public void testPutIfAbsent_supportedPresent() {
+ assertEquals("putIfAbsent(present, value) should return existing value",
+ v0(), getMap().putIfAbsent(k0(), v3()));
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(absent = SUPPORTS_PUT)
+ public void testPutIfAbsent_unsupportedAbsent() {
+ try {
+ putIfAbsent(e3());
+ fail("putIfAbsent(notPresent, value) should throw");
+ } catch (UnsupportedOperationException expected) {
+ }
+ expectUnchanged();
+ expectMissing(e3());
+ }
+
+ @MapFeature.Require(absent = SUPPORTS_PUT)
+ @CollectionSize.Require(absent = ZERO)
+ public void testPutIfAbsent_unsupportedPresentExistingValue() {
+ try {
+ assertEquals("putIfAbsent(present, existingValue) should return present or throw",
+ v0(), putIfAbsent(e0()));
+ } catch (UnsupportedOperationException tolerated) {
+ }
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(absent = SUPPORTS_PUT)
+ @CollectionSize.Require(absent = ZERO)
+ public void testPutIfAbsent_unsupportedPresentDifferentValue() {
+ try {
+ getMap().putIfAbsent(k0(), v3());
+ } catch (UnsupportedOperationException tolerated) {
+ }
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_KEYS)
+ public void testPutIfAbsent_nullKeyUnsupported() {
+ try {
+ getMap().putIfAbsent(null, v3());
+ fail("putIfAbsent(null, value) should throw");
+ } catch (NullPointerException expected) {
+ }
+ expectUnchanged();
+ expectNullKeyMissingWhenNullKeysUnsupported(
+ "Should not contain null key after unsupported putIfAbsent(null, value)");
+ }
+
+ @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
+ public void testPutIfAbsent_nullValueUnsupported() {
+ try {
+ getMap().putIfAbsent(k3(), null);
+ fail("putIfAbsent(key, null) should throw");
+ } catch (NullPointerException expected) {
+ }
+ expectUnchanged();
+ expectNullValueMissingWhenNullValuesUnsupported(
+ "Should not contain null value after unsupported put(key, null)");
+ }
+
+ @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
+ @CollectionSize.Require(absent = ZERO)
+ public void testPutIfAbsent_putWithNullValueUnsupported() {
+ try {
+ getMap().putIfAbsent(k0(), null);
+ } catch (NullPointerException tolerated) {
+ }
+ expectUnchanged();
+ expectNullValueMissingWhenNullValuesUnsupported(
+ "Should not contain null after unsupported putIfAbsent(present, null)");
+ }
+
+ private V putIfAbsent(Map.Entry<K, V> entry) {
+ return getMap().putIfAbsent(entry.getKey(), entry.getValue());
+ }
+}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapRemoveTester.java
new file mode 100644
index 0000000..1eaf340
--- /dev/null
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapRemoveTester.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.collect.testing.testers;
+
+import static com.google.common.collect.testing.features.CollectionSize.ZERO;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEY_QUERIES;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
+import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_REMOVE;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.testing.AbstractMapTester;
+import com.google.common.collect.testing.features.CollectionSize;
+import com.google.common.collect.testing.features.MapFeature;
+
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Tester for {@link ConcurrentMap#remove}. Can't be invoked directly; please see
+ * {@link com.google.common.collect.testing.ConcurrentMapTestSuiteBuilder}.
+ *
+ * @author Louis Wasserman
+ */
+ at GwtCompatible
+public class ConcurrentMapRemoveTester<K, V> extends AbstractMapTester<K, V> {
+ @Override
+ protected ConcurrentMap<K, V> getMap() {
+ return (ConcurrentMap<K, V>) super.getMap();
+ }
+
+ @MapFeature.Require(SUPPORTS_REMOVE)
+ @CollectionSize.Require(absent = ZERO)
+ public void testRemove_supportedPresent() {
+ assertTrue(getMap().remove(k0(), v0()));
+ expectMissing(e0());
+ }
+
+ @MapFeature.Require(SUPPORTS_REMOVE)
+ public void testRemove_supportedPresentKeyWrongValue() {
+ assertFalse(getMap().remove(k0(), v3()));
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(SUPPORTS_REMOVE)
+ public void testRemove_supportedWrongKeyPresentValue() {
+ assertFalse(getMap().remove(k3(), v0()));
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(SUPPORTS_REMOVE)
+ public void testRemove_supportedAbsentKeyAbsentValue() {
+ assertFalse(getMap().remove(k3(), v3()));
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_KEY_QUERIES)
+ public void testRemove_nullKeyQueriesUnsupported() {
+ try {
+ assertFalse(getMap().remove(null, v3()));
+ } catch (NullPointerException tolerated) {
+ // since the operation would be a no-op, the exception is not required
+ }
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_VALUE_QUERIES)
+ public void testRemove_nullValueQueriesUnsupported() {
+ try {
+ assertFalse(getMap().remove(k3(), null));
+ } catch (NullPointerException tolerated) {
+ // since the operation would be a no-op, the exception is not required
+ }
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(absent = SUPPORTS_REMOVE)
+ @CollectionSize.Require(absent = ZERO)
+ public void testRemove_unsupportedPresent() {
+ try {
+ getMap().remove(k0(), v0());
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {}
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(absent = SUPPORTS_REMOVE)
+ public void testRemove_unsupportedAbsent() {
+ try {
+ assertFalse(getMap().remove(k0(), v3()));
+ } catch (UnsupportedOperationException tolerated) {
+ // since the operation would be a no-op, the exception is not required
+ }
+ expectUnchanged();
+ }
+}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapReplaceEntryTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapReplaceEntryTester.java
new file mode 100644
index 0000000..92f9be1
--- /dev/null
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapReplaceEntryTester.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.collect.testing.testers;
+
+import static com.google.common.collect.testing.features.CollectionSize.ZERO;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
+import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.testing.AbstractMapTester;
+import com.google.common.collect.testing.features.CollectionSize;
+import com.google.common.collect.testing.features.MapFeature;
+
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * A generic JUnit test which tests {@code replace(K, V, V)} operations on a concurrent map. Can't
+ * be invoked directly; please see
+ * {@link com.google.common.collect.testing.ConcurrentMapTestSuiteBuilder}.
+ *
+ * @author Louis Wasserman
+ */
+ at GwtCompatible
+public class ConcurrentMapReplaceEntryTester<K, V> extends AbstractMapTester<K, V> {
+ @Override
+ protected ConcurrentMap<K, V> getMap() {
+ return (ConcurrentMap<K, V>) super.getMap();
+ }
+
+ @MapFeature.Require(SUPPORTS_PUT)
+ @CollectionSize.Require(absent = ZERO)
+ public void testReplaceEntry_supportedPresent() {
+ assertTrue(getMap().replace(k0(), v0(), v3()));
+ expectReplacement(entry(k0(), v3()));
+ }
+
+ @MapFeature.Require(SUPPORTS_PUT)
+ @CollectionSize.Require(absent = ZERO)
+ public void testReplaceEntry_supportedPresentUnchanged() {
+ assertTrue(getMap().replace(k0(), v0(), v0()));
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(SUPPORTS_PUT)
+ @CollectionSize.Require(absent = ZERO)
+ public void testReplaceEntry_supportedWrongValue() {
+ assertFalse(getMap().replace(k0(), v3(), v4()));
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(SUPPORTS_PUT)
+ public void testReplaceEntry_supportedAbsentKey() {
+ assertFalse(getMap().replace(k3(), v3(), v4()));
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
+ @CollectionSize.Require(absent = ZERO)
+ public void testReplaceEntry_presentNullValueUnsupported() {
+ try {
+ getMap().replace(k0(), v0(), null);
+ fail("Expected NullPointerException");
+ } catch (NullPointerException expected) {}
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUE_QUERIES)
+ @CollectionSize.Require(absent = ZERO)
+ public void testReplaceEntry_wrongValueNullValueUnsupported() {
+ try {
+ assertFalse(getMap().replace(k0(), v3(), null));
+ } catch (NullPointerException tolerated) {
+ // the operation would be a no-op, so exceptions are allowed but not required
+ }
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUE_QUERIES)
+ public void testReplaceEntry_absentKeyNullValueUnsupported() {
+ try {
+ assertFalse(getMap().replace(k3(), v3(), null));
+ } catch (NullPointerException tolerated) {
+ // the operation would be a no-op, so exceptions are allowed but not required
+ }
+ expectUnchanged();
+ }
+
+ @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUE_QUERIES})
+ public void testReplaceEntry_nullDifferentFromAbsent() {
+ assertFalse(getMap().replace(k3(), null, v3()));
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUE_QUERIES)
+ public void testReplaceEntry_expectNullUnsupported() {
+ try {
+ assertFalse(getMap().replace(k3(), null, v3()));
+ } catch (NullPointerException tolerated) {
+ // the operation would be a no-op, so exceptions are allowed but not required
+ }
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(absent = SUPPORTS_PUT)
+ @CollectionSize.Require(absent = ZERO)
+ public void testReplaceEntry_unsupportedPresent() {
+ try {
+ getMap().replace(k0(), v0(), v3());
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {}
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(absent = SUPPORTS_PUT)
+ @CollectionSize.Require(absent = ZERO)
+ public void testReplaceEntry_unsupportedWrongValue() {
+ try {
+ getMap().replace(k0(), v3(), v4());
+ } catch (UnsupportedOperationException tolerated) {
+ // the operation would be a no-op, so exceptions are allowed but not required
+ }
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(absent = SUPPORTS_PUT)
+ public void testReplaceEntry_unsupportedAbsentKey() {
+ try {
+ getMap().replace(k3(), v3(), v4());
+ } catch (UnsupportedOperationException tolerated) {
+ // the operation would be a no-op, so exceptions are allowed but not required
+ }
+ expectUnchanged();
+ }
+}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapReplaceTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapReplaceTester.java
new file mode 100644
index 0000000..34657be
--- /dev/null
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ConcurrentMapReplaceTester.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.collect.testing.testers;
+
+import static com.google.common.collect.testing.features.CollectionSize.ZERO;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEY_QUERIES;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
+import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.testing.AbstractMapTester;
+import com.google.common.collect.testing.features.CollectionSize;
+import com.google.common.collect.testing.features.MapFeature;
+
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * A generic JUnit test which tests {@code replace(K, V)} operations on a concurrent map. Can't be
+ * invoked directly; please see
+ * {@link com.google.common.collect.testing.ConcurrentMapTestSuiteBuilder}.
+ *
+ * @author Louis Wasserman
+ */
+ at GwtCompatible
+public class ConcurrentMapReplaceTester<K, V> extends AbstractMapTester<K, V> {
+ @Override
+ protected ConcurrentMap<K, V> getMap() {
+ return (ConcurrentMap<K, V>) super.getMap();
+ }
+
+ @MapFeature.Require(SUPPORTS_PUT)
+ @CollectionSize.Require(absent = ZERO)
+ public void testReplace_supportedPresent() {
+ assertEquals(v0(), getMap().replace(k0(), v3()));
+ expectReplacement(entry(k0(), v3()));
+ }
+
+ @MapFeature.Require(SUPPORTS_PUT)
+ @CollectionSize.Require(absent = ZERO)
+ public void testReplace_supportedPresentNoChange() {
+ assertEquals(v0(), getMap().replace(k0(), v0()));
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(SUPPORTS_PUT)
+ public void testReplace_supportedAbsent() {
+ assertNull(getMap().replace(k3(), v3()));
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
+ @CollectionSize.Require(absent = ZERO)
+ public void testReplace_presentNullValueUnsupported() {
+ try {
+ getMap().replace(k0(), null);
+ fail("Expected NullPointerException");
+ } catch (NullPointerException expected) {}
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUE_QUERIES)
+ public void testReplace_absentNullValueUnsupported() {
+ try {
+ getMap().replace(k3(), null);
+ } catch (NullPointerException tolerated) {
+ // permitted not to throw because it would be a no-op
+ }
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_KEY_QUERIES)
+ public void testReplace_absentNullKeyUnsupported() {
+ try {
+ getMap().replace(null, v3());
+ } catch (NullPointerException tolerated) {
+ // permitted not to throw because it would be a no-op
+ }
+ expectUnchanged();
+ }
+
+ @MapFeature.Require(absent = SUPPORTS_PUT)
+ @CollectionSize.Require(absent = ZERO)
+ public void testReplace_unsupportedPresent() {
+ try {
+ getMap().replace(k0(), v3());
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {}
+ expectUnchanged();
+ }
+}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllAtIndexTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllAtIndexTester.java
index c1e03fd..35486cd 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllAtIndexTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllAtIndexTester.java
@@ -44,15 +44,15 @@ public class ListAddAllAtIndexTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testAddAllAtIndex_supportedAllPresent() {
assertTrue("addAll(n, allPresent) should return true",
- getList().addAll(0, MinimalCollection.of(samples.e0)));
- expectAdded(0, samples.e0);
+ getList().addAll(0, MinimalCollection.of(e0())));
+ expectAdded(0, e0());
}
@ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
@CollectionSize.Require(absent = ZERO)
public void testAddAllAtIndex_unsupportedAllPresent() {
try {
- getList().addAll(0, MinimalCollection.of(samples.e0));
+ getList().addAll(0, MinimalCollection.of(e0()));
fail("addAll(n, allPresent) should throw");
} catch (UnsupportedOperationException expected) {
}
@@ -63,20 +63,20 @@ public class ListAddAllAtIndexTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testAddAllAtIndex_supportedSomePresent() {
assertTrue("addAll(n, allPresent) should return true",
- getList().addAll(0, MinimalCollection.of(samples.e0, samples.e3)));
- expectAdded(0, samples.e0, samples.e3);
+ getList().addAll(0, MinimalCollection.of(e0(), e3())));
+ expectAdded(0, e0(), e3());
}
@ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
@CollectionSize.Require(absent = ZERO)
public void testAddAllAtIndex_unsupportedSomePresent() {
try {
- getList().addAll(0, MinimalCollection.of(samples.e0, samples.e3));
+ getList().addAll(0, MinimalCollection.of(e0(), e3()));
fail("addAll(n, allPresent) should throw");
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@@ -99,10 +99,10 @@ public class ListAddAllAtIndexTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
public void testAddAllAtIndex_withDuplicates() {
MinimalCollection<E> elementsToAdd
- = MinimalCollection.of(samples.e0, samples.e1, samples.e0, samples.e1);
+ = MinimalCollection.of(e0(), e1(), e0(), e1());
assertTrue("addAll(n, hasDuplicates) should return true",
getList().addAll(0, elementsToAdd));
- expectAdded(0, samples.e0, samples.e1, samples.e0, samples.e1);
+ expectAdded(0, e0(), e1(), e0(), e1());
}
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@@ -161,22 +161,22 @@ public class ListAddAllAtIndexTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
public void testAddAllAtIndex_negative() {
try {
- getList().addAll(-1, MinimalCollection.of(samples.e3));
+ getList().addAll(-1, MinimalCollection.of(e3()));
fail("addAll(-1, e) should throw");
} catch (IndexOutOfBoundsException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
public void testAddAllAtIndex_tooLarge() {
try {
- getList().addAll(getNumElements() + 1, MinimalCollection.of(samples.e3));
+ getList().addAll(getNumElements() + 1, MinimalCollection.of(e3()));
fail("addAll(size + 1, e) should throw");
} catch (IndexOutOfBoundsException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllTester.java
index c667937..c799c5b 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAllTester.java
@@ -38,15 +38,15 @@ public class ListAddAllTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testAddAll_supportedAllPresent() {
assertTrue("addAll(allPresent) should return true",
- getList().addAll(MinimalCollection.of(samples.e0)));
- expectAdded(samples.e0);
+ getList().addAll(MinimalCollection.of(e0())));
+ expectAdded(e0());
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
@CollectionSize.Require(absent = ZERO)
public void testAddAll_unsupportedAllPresent() {
try {
- getList().addAll(MinimalCollection.of(samples.e0));
+ getList().addAll(MinimalCollection.of(e0()));
fail("addAll(allPresent) should throw");
} catch (UnsupportedOperationException expected) {
}
@@ -56,9 +56,9 @@ public class ListAddAllTester<E> extends AbstractListTester<E> {
@CollectionFeature.Require(SUPPORTS_ADD)
public void testAddAll_withDuplicates() {
MinimalCollection<E> elementsToAdd
- = MinimalCollection.of(samples.e0, samples.e1, samples.e0, samples.e1);
+ = MinimalCollection.of(e0(), e1(), e0(), e1());
assertTrue("addAll(hasDuplicates) should return true",
getList().addAll(elementsToAdd));
- expectAdded(samples.e0, samples.e1, samples.e0, samples.e1);
+ expectAdded(e0(), e1(), e0(), e1());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAtIndexTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAtIndexTester.java
index 7e6acd4..c9b21d3 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAtIndexTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddAtIndexTester.java
@@ -46,8 +46,8 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@CollectionSize.Require(absent = ZERO)
public void testAddAtIndex_supportedPresent() {
- getList().add(0, samples.e0);
- expectAdded(0, samples.e0);
+ getList().add(0, e0());
+ expectAdded(0, e0());
}
@ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
@@ -58,7 +58,7 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
*/
public void testAddAtIndex_unsupportedPresent() {
try {
- getList().add(0, samples.e0);
+ getList().add(0, e0());
fail("add(n, present) should throw");
} catch (UnsupportedOperationException expected) {
}
@@ -67,8 +67,8 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
public void testAddAtIndex_supportedNotPresent() {
- getList().add(0, samples.e3);
- expectAdded(0, samples.e3);
+ getList().add(0, e3());
+ expectAdded(0, e3());
}
@CollectionFeature.Require(FAILS_FAST_ON_CONCURRENT_MODIFICATION)
@@ -76,7 +76,7 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
public void testAddAtIndexConcurrentWithIteration() {
try {
Iterator<E> iterator = collection.iterator();
- getList().add(0, samples.e3);
+ getList().add(0, e3());
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -87,26 +87,26 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
@ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
public void testAddAtIndex_unsupportedNotPresent() {
try {
- getList().add(0, samples.e3);
+ getList().add(0, e3());
fail("add(n, notPresent) should throw");
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@CollectionSize.Require(absent = {ZERO, ONE})
public void testAddAtIndex_middle() {
- getList().add(getNumElements() / 2, samples.e3);
- expectAdded(getNumElements() / 2, samples.e3);
+ getList().add(getNumElements() / 2, e3());
+ expectAdded(getNumElements() / 2, e3());
}
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@CollectionSize.Require(absent = ZERO)
public void testAddAtIndex_end() {
- getList().add(getNumElements(), samples.e3);
- expectAdded(getNumElements(), samples.e3);
+ getList().add(getNumElements(), e3());
+ expectAdded(getNumElements(), e3());
}
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
@@ -132,23 +132,23 @@ public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
public void testAddAtIndex_negative() {
try {
- getList().add(-1, samples.e3);
+ getList().add(-1, e3());
fail("add(-1, e) should throw");
} catch (IndexOutOfBoundsException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
public void testAddAtIndex_tooLarge() {
try {
- getList().add(getNumElements() + 1, samples.e3);
+ getList().add(getNumElements() + 1, e3());
fail("add(size + 1, e) should throw");
} catch (IndexOutOfBoundsException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
/**
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddTester.java
index 9a65375..a2b80f0 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListAddTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListAddTester.java
@@ -42,8 +42,8 @@ public class ListAddTester<E> extends AbstractListTester<E> {
@CollectionFeature.Require(SUPPORTS_ADD)
@CollectionSize.Require(absent = ZERO)
public void testAdd_supportedPresent() {
- assertTrue("add(present) should return true", getList().add(samples.e0));
- expectAdded(samples.e0);
+ assertTrue("add(present) should return true", getList().add(e0()));
+ expectAdded(e0());
}
@CollectionFeature.Require(absent = SUPPORTS_ADD)
@@ -54,7 +54,7 @@ public class ListAddTester<E> extends AbstractListTester<E> {
*/
public void testAdd_unsupportedPresent() {
try {
- getList().add(samples.e0);
+ getList().add(e0());
fail("add(present) should throw");
} catch (UnsupportedOperationException expected) {
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListCreationTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListCreationTester.java
index af1cd76..bf4f142 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListCreationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListCreationTester.java
@@ -37,7 +37,7 @@ public class ListCreationTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(absent = {ZERO, ONE})
public void testCreateWithDuplicates() {
E[] array = createSamplesArray();
- array[1] = samples.e0;
+ array[1] = e0();
collection = getSubjectGenerator().create(array);
expectContents(array);
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListEqualsTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListEqualsTester.java
index 937ed6a..31e5352 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListEqualsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListEqualsTester.java
@@ -43,7 +43,7 @@ public class ListEqualsTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(absent = CollectionSize.ZERO)
public void testEquals_otherListWithDifferentElements() {
ArrayList<E> other = new ArrayList<E>(getSampleElements());
- other.set(other.size() / 2, getSubjectGenerator().samples().e3);
+ other.set(other.size() / 2, getSubjectGenerator().samples().e3());
assertFalse(
"A List should not equal another List containing different elements.",
getList().equals(other));
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListIndexOfTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListIndexOfTester.java
index d92b191..8798b02 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListIndexOfTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListIndexOfTester.java
@@ -45,9 +45,9 @@ public class ListIndexOfTester<E> extends AbstractListIndexOfTester<E> {
@CollectionSize.Require(absent = {ZERO, ONE})
public void testIndexOf_duplicate() {
E[] array = createSamplesArray();
- array[getNumElements() / 2] = samples.e0;
+ array[getNumElements() / 2] = e0();
collection = getSubjectGenerator().create(array);
assertEquals("indexOf(duplicate) should return index of first occurrence",
- 0, getList().indexOf(samples.e0));
+ 0, getList().indexOf(e0()));
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListLastIndexOfTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListLastIndexOfTester.java
index b750878..5950faf 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListLastIndexOfTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListLastIndexOfTester.java
@@ -45,10 +45,10 @@ public class ListLastIndexOfTester<E> extends AbstractListIndexOfTester<E> {
@CollectionSize.Require(absent = {ZERO, ONE})
public void testLastIndexOf_duplicate() {
E[] array = createSamplesArray();
- array[getNumElements() / 2] = samples.e0;
+ array[getNumElements() / 2] = e0();
collection = getSubjectGenerator().create(array);
assertEquals(
"lastIndexOf(duplicate) should return index of last occurrence",
- getNumElements() / 2, getList().lastIndexOf(samples.e0));
+ getNumElements() / 2, getList().lastIndexOf(e0()));
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListListIteratorTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListListIteratorTester.java
index 589273d..e87c764 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListListIteratorTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListListIteratorTester.java
@@ -68,7 +68,7 @@ public class ListListIteratorTester<E> extends AbstractListTester<E> {
private void runListIteratorTest(Set<IteratorFeature> features) {
new ListIteratorTester<E>(
- listListIteratorTesterNumIterations(), singleton(samples.e4), features,
+ listListIteratorTesterNumIterations(), singleton(e4()), features,
Helpers.copyToList(getOrderedElements()), 0) {
{
// TODO: don't set this universally
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListRetainAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListRetainAllTester.java
index 96a005d..befc3d2 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListRetainAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListRetainAllTester.java
@@ -16,11 +16,11 @@
package com.google.common.collect.testing.testers;
+import static com.google.common.collect.testing.Helpers.assertContentsInOrder;
import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
import static com.google.common.collect.testing.features.CollectionSize.ONE;
import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.testing.MinimalCollection;
@@ -42,7 +42,7 @@ public class ListRetainAllTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(absent = {ZERO, ONE})
public void testRetainAll_duplicatesKept() {
E[] array = createSamplesArray();
- array[1] = samples.e0;
+ array[1] = e0();
collection = getSubjectGenerator().create(array);
assertFalse("containsDuplicates.retainAll(superset) should return false",
collection.retainAll(MinimalCollection.of(createSamplesArray())));
@@ -54,19 +54,20 @@ public class ListRetainAllTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(SEVERAL)
public void testRetainAll_duplicatesRemoved() {
E[] array = createSamplesArray();
- array[1] = samples.e0;
+ array[1] = e0();
collection = getSubjectGenerator().create(array);
assertTrue("containsDuplicates.retainAll(subset) should return true",
- collection.retainAll(MinimalCollection.of(samples.e2)));
- expectContents(samples.e2);
+ collection.retainAll(MinimalCollection.of(e2())));
+ expectContents(e2());
}
-
+
@SuppressWarnings("unchecked")
@CollectionFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(SEVERAL)
public void testRetainAll_countIgnored() {
- resetContainer(getSubjectGenerator().create(samples.e0, samples.e2, samples.e1, samples.e0));
- assertTrue(getList().retainAll(Arrays.asList(samples.e0, samples.e1)));
- assertThat(getList()).has().exactly(samples.e0, samples.e1, samples.e0).inOrder();
+ resetContainer(
+ getSubjectGenerator().create(e0(), e2(), e1(), e0()));
+ assertTrue(getList().retainAll(Arrays.asList(e0(), e1())));
+ assertContentsInOrder(getList(), e0(), e1(), e0());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListSetTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListSetTester.java
index 94f418c..768173b 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListSetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListSetTester.java
@@ -41,7 +41,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_SET)
@CollectionSize.Require(absent = ZERO)
public void testSet() {
- doTestSet(samples.e3);
+ doTestSet(e3());
}
@CollectionSize.Require(absent = ZERO)
@@ -60,7 +60,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
elements[i] = null;
collection = getSubjectGenerator().create(elements);
- doTestSet(samples.e3);
+ doTestSet(e3());
}
private void doTestSet(E newValue) {
@@ -77,7 +77,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_SET)
public void testSet_indexTooLow() {
try {
- getList().set(-1, samples.e3);
+ getList().set(-1, e3());
fail("set(-1) should throw IndexOutOfBoundsException");
} catch (IndexOutOfBoundsException expected) {
}
@@ -88,7 +88,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
public void testSet_indexTooHigh() {
int index = getNumElements();
try {
- getList().set(index, samples.e3);
+ getList().set(index, e3());
fail("set(size) should throw IndexOutOfBoundsException");
} catch (IndexOutOfBoundsException expected) {
}
@@ -99,7 +99,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
@ListFeature.Require(absent = SUPPORTS_SET)
public void testSet_unsupported() {
try {
- getList().set(aValidIndex(), samples.e3);
+ getList().set(aValidIndex(), e3());
fail("set() should throw UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
@@ -110,7 +110,7 @@ public class ListSetTester<E> extends AbstractListTester<E> {
@ListFeature.Require(absent = SUPPORTS_SET)
public void testSet_unsupportedByEmptyList() {
try {
- getList().set(0, samples.e3);
+ getList().set(0, e3());
fail("set() should throw UnsupportedOperationException "
+ "or IndexOutOfBoundsException");
} catch (UnsupportedOperationException tolerated) {
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/ListSubListTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/ListSubListTester.java
index 2883f3d..5309ca8 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/ListSubListTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/ListSubListTester.java
@@ -113,17 +113,17 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
@ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
public void testSubList_subListAddAffectsOriginal() {
List<E> subList = getList().subList(0, 0);
- subList.add(samples.e3);
- expectAdded(0, samples.e3);
+ subList.add(e3());
+ expectAdded(0, e3());
}
@ListFeature.Require(SUPPORTS_SET)
@CollectionSize.Require(absent = ZERO)
public void testSubList_subListSetAffectsOriginal() {
List<E> subList = getList().subList(0, 1);
- subList.set(0, samples.e3);
+ subList.set(0, e3());
List<E> expected = Helpers.copyToList(createSamplesArray());
- expected.set(0, samples.e3);
+ expected.set(0, e3());
expectContents(expected);
}
@@ -131,17 +131,17 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testSubList_originalListSetAffectsSubList() {
List<E> subList = getList().subList(0, 1);
- getList().set(0, samples.e3);
+ getList().set(0, e3());
assertEquals("A set() call to a list after a sublist has been created "
+ "should be reflected in the sublist",
- Collections.singletonList(samples.e3), subList);
+ Collections.singletonList(e3()), subList);
}
@ListFeature.Require(SUPPORTS_REMOVE_WITH_INDEX)
@CollectionSize.Require(absent = {ZERO, ONE})
public void testSubList_subListRemoveAffectsOriginalLargeList() {
List<E> subList = getList().subList(1, 3);
- subList.remove(samples.e2);
+ subList.remove(e2());
List<E> expected = Helpers.copyToList(createSamplesArray());
expected.remove(2);
expectContents(expected);
@@ -151,17 +151,17 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(absent = {ZERO, ONE})
public void testSubList_subListAddAtIndexAffectsOriginalLargeList() {
List<E> subList = getList().subList(2, 3);
- subList.add(0, samples.e3);
- expectAdded(2, samples.e3);
+ subList.add(0, e3());
+ expectAdded(2, e3());
}
@ListFeature.Require(SUPPORTS_SET)
@CollectionSize.Require(absent = {ZERO, ONE})
public void testSubList_subListSetAffectsOriginalLargeList() {
List<E> subList = getList().subList(1, 2);
- subList.set(0, samples.e3);
+ subList.set(0, e3());
List<E> expected = Helpers.copyToList(createSamplesArray());
- expected.set(1, samples.e3);
+ expected.set(1, e3());
expectContents(expected);
}
@@ -169,10 +169,10 @@ public class ListSubListTester<E> extends AbstractListTester<E> {
@CollectionSize.Require(absent = {ZERO, ONE})
public void testSubList_originalListSetAffectsSubListLargeList() {
List<E> subList = getList().subList(1, 3);
- getList().set(1, samples.e3);
+ getList().set(1, e3());
assertEquals("A set() call to a list after a sublist has been created "
+ "should be reflected in the sublist",
- Arrays.asList(samples.e3, samples.e2), subList);
+ Arrays.asList(e3(), e2()), subList);
}
public void testSubList_ofSubListEmpty() {
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapClearTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapClearTester.java
index 8de9998..92640a4 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapClearTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapClearTester.java
@@ -45,6 +45,8 @@ public class MapClearTester<K, V> extends AbstractMapTester<K, V> {
getMap().clear();
assertTrue("After clear(), a map should be empty.",
getMap().isEmpty());
+ assertEquals(0, getMap().size());
+ assertFalse(getMap().entrySet().iterator().hasNext());
}
@MapFeature.Require({FAILS_FAST_ON_CONCURRENT_MODIFICATION,
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsKeyTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsKeyTester.java
index d933efd..8c49b74 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsKeyTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsKeyTester.java
@@ -38,12 +38,12 @@ public class MapContainsKeyTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testContains_yes() {
assertTrue("containsKey(present) should return true",
- getMap().containsKey(samples.e0.getKey()));
+ getMap().containsKey(k0()));
}
public void testContains_no() {
assertFalse("containsKey(notPresent) should return false",
- getMap().containsKey(samples.e3.getKey()));
+ getMap().containsKey(k3()));
}
@MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
@@ -63,7 +63,7 @@ public class MapContainsKeyTester<K, V> extends AbstractMapTester<K, V> {
public void testContains_nonNullWhenNullContained() {
initMapWithNullKey();
assertFalse("containsKey(notPresent) should return false",
- getMap().containsKey(samples.e3.getKey()));
+ getMap().containsKey(k3()));
}
@MapFeature.Require(ALLOWS_NULL_KEYS)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsValueTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsValueTester.java
index 8ddfe27..a114dce 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsValueTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapContainsValueTester.java
@@ -17,7 +17,8 @@
package com.google.common.collect.testing.testers;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.collect.testing.features.MapFeature.*;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.testing.AbstractMapTester;
@@ -38,12 +39,12 @@ public class MapContainsValueTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testContains_yes() {
assertTrue("containsValue(present) should return true",
- getMap().containsValue(samples.e0.getValue()));
+ getMap().containsValue(v0()));
}
public void testContains_no() {
assertFalse("containsValue(notPresent) should return false",
- getMap().containsValue(samples.e3.getValue()));
+ getMap().containsValue(v3()));
}
@MapFeature.Require(ALLOWS_NULL_VALUE_QUERIES)
@@ -63,7 +64,7 @@ public class MapContainsValueTester<K, V> extends AbstractMapTester<K, V> {
public void testContains_nonNullWhenNullContained() {
initMapWithNullValue();
assertFalse("containsValue(notPresent) should return false",
- getMap().containsValue(samples.e3.getValue()));
+ getMap().containsValue(v3()));
}
@MapFeature.Require(ALLOWS_NULL_VALUES)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapCreationTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapCreationTester.java
index 1a3f86b..2369fca 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapCreationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapCreationTester.java
@@ -130,7 +130,7 @@ public class MapCreationTester<K, V> extends AbstractMapTester<K, V> {
private Entry<K, V>[] getEntriesMultipleNonNullKeys() {
Entry<K, V>[] entries = createSamplesArray();
- entries[0] = entry(samples.e1.getKey(), samples.e0.getValue());
+ entries[0] = entry(k1(), v0());
return entries;
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapEntrySetTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapEntrySetTester.java
index 447cc06..b7fe855 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapEntrySetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapEntrySetTester.java
@@ -55,26 +55,34 @@ public class MapEntrySetTester<K, V> extends AbstractMapTester<K, V> {
public void testEntrySetIteratorRemove() {
Set<Entry<K, V>> entrySet = getMap().entrySet();
Iterator<Entry<K, V>> entryItr = entrySet.iterator();
- assertEquals(samples.e0, entryItr.next());
+ assertEquals(e0(), entryItr.next());
entryItr.remove();
assertTrue(getMap().isEmpty());
- assertFalse(entrySet.contains(samples.e0));
+ assertFalse(entrySet.contains(e0()));
}
public void testContainsEntryWithIncomparableKey() {
- assertFalse(getMap()
- .entrySet().contains(Helpers.mapEntry(IncomparableType.INSTANCE, samples.e0.getValue())));
+ try {
+ assertFalse(getMap()
+ .entrySet().contains(Helpers.mapEntry(IncomparableType.INSTANCE, v0())));
+ } catch (ClassCastException acceptable) {
+ // allowed by the spec
+ }
}
public void testContainsEntryWithIncomparableValue() {
- assertFalse(getMap()
- .entrySet().contains(Helpers.mapEntry(samples.e0.getKey(), IncomparableType.INSTANCE)));
+ try {
+ assertFalse(getMap()
+ .entrySet().contains(Helpers.mapEntry(k0(), IncomparableType.INSTANCE)));
+ } catch (ClassCastException acceptable) {
+ // allowed by the spec
+ }
}
@MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
public void testContainsEntryWithNullKeyAbsent() {
assertFalse(getMap()
- .entrySet().contains(Helpers.mapEntry(null, samples.e0.getValue())));
+ .entrySet().contains(Helpers.mapEntry(null, v0())));
}
@CollectionSize.Require(absent = ZERO)
@@ -88,7 +96,7 @@ public class MapEntrySetTester<K, V> extends AbstractMapTester<K, V> {
@MapFeature.Require(ALLOWS_NULL_VALUE_QUERIES)
public void testContainsEntryWithNullValueAbsent() {
assertFalse(getMap()
- .entrySet().contains(Helpers.mapEntry(samples.e0.getKey(), null)));
+ .entrySet().contains(Helpers.mapEntry(k0(), null)));
}
@CollectionSize.Require(absent = ZERO)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapEqualsTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapEqualsTester.java
index f2b2cbc..a01b206 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapEqualsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapEqualsTester.java
@@ -28,7 +28,6 @@ import com.google.common.collect.testing.features.MapFeature;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
-import java.util.Map.Entry;
/**
* Tests {@link java.util.Map#equals}.
@@ -47,8 +46,7 @@ public class MapEqualsTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = CollectionSize.ZERO)
public void testEquals_otherMapWithDifferentEntries() {
Map<K, V> other = newHashMap(getSampleEntries(getNumEntries() - 1));
- Entry<K, V> e3 = getSubjectGenerator().samples().e3;
- other.put(e3.getKey(), e3.getValue());
+ other.put(k3(), v3());
assertFalse(
"A Map should not equal another Map containing different entries.",
getMap().equals(other)
@@ -59,7 +57,7 @@ public class MapEqualsTester<K, V> extends AbstractMapTester<K, V> {
@MapFeature.Require(ALLOWS_NULL_KEYS)
public void testEquals_containingNullKey() {
Collection<Map.Entry<K, V>> entries = getSampleEntries(getNumEntries() - 1);
- entries.add(entry(null, samples.e3.getValue()));
+ entries.add(entry(null, v3()));
resetContainer(getSubjectGenerator().create(entries.toArray()));
assertTrue("A Map should equal any other Map containing the same entries,"
@@ -70,7 +68,7 @@ public class MapEqualsTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = CollectionSize.ZERO)
public void testEquals_otherContainsNullKey() {
Collection<Map.Entry<K, V>> entries = getSampleEntries(getNumEntries() - 1);
- entries.add(entry(null, samples.e3.getValue()));
+ entries.add(entry(null, v3()));
Map<K, V> other = newHashMap(entries);
assertFalse(
@@ -83,7 +81,7 @@ public class MapEqualsTester<K, V> extends AbstractMapTester<K, V> {
@MapFeature.Require(ALLOWS_NULL_VALUES)
public void testEquals_containingNullValue() {
Collection<Map.Entry<K, V>> entries = getSampleEntries(getNumEntries() - 1);
- entries.add(entry(samples.e3.getKey(), null));
+ entries.add(entry(k3(), null));
resetContainer(getSubjectGenerator().create(entries.toArray()));
assertTrue("A Map should equal any other Map containing the same entries,"
@@ -94,7 +92,7 @@ public class MapEqualsTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = CollectionSize.ZERO)
public void testEquals_otherContainsNullValue() {
Collection<Map.Entry<K, V>> entries = getSampleEntries(getNumEntries() - 1);
- entries.add(entry(samples.e3.getKey(), null));
+ entries.add(entry(k3(), null));
Map<K, V> other = newHashMap(entries);
assertFalse(
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapGetTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapGetTester.java
index f5e0ba7..8aa817d 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapGetTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapGetTester.java
@@ -39,11 +39,11 @@ public class MapGetTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testGet_yes() {
assertEquals("get(present) should return the associated value",
- samples.e0.getValue(), get(samples.e0.getKey()));
+ v0(), get(k0()));
}
public void testGet_no() {
- assertNull("get(notPresent) should return null", get(samples.e3.getKey()));
+ assertNull("get(notPresent) should return null", get(k3()));
}
@MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
@@ -63,7 +63,7 @@ public class MapGetTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testGet_nonNullWhenNullContained() {
initMapWithNullKey();
- assertNull("get(notPresent) should return null", get(samples.e3.getKey()));
+ assertNull("get(notPresent) should return null", get(k3()));
}
@MapFeature.Require(ALLOWS_NULL_KEYS)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapHashCodeTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapHashCodeTester.java
index e030a54..712b124 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapHashCodeTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapHashCodeTester.java
@@ -48,14 +48,14 @@ public class MapHashCodeTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = CollectionSize.ZERO)
@MapFeature.Require(ALLOWS_NULL_KEYS)
public void testHashCode_containingNullKey() {
- Map.Entry<K, V> entryWithNull = entry(null, samples.e3.getValue());
+ Map.Entry<K, V> entryWithNull = entry(null, v3());
runEntryWithNullTest(entryWithNull);
}
@CollectionSize.Require(absent = CollectionSize.ZERO)
@MapFeature.Require(ALLOWS_NULL_VALUES)
public void testHashCode_containingNullValue() {
- Map.Entry<K, V> entryWithNull = entry(samples.e3.getKey(), null);
+ Map.Entry<K, V> entryWithNull = entry(k3(), null);
runEntryWithNullTest(entryWithNull);
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapPutAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapPutAllTester.java
index 075fa82..3bef211 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapPutAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapPutAllTester.java
@@ -56,8 +56,8 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
@Override public void setUp() throws Exception {
super.setUp();
- containsNullKey = singletonList(entry(null, samples.e3.getValue()));
- containsNullValue = singletonList(entry(samples.e3.getKey(), null));
+ containsNullKey = singletonList(entry(null, v3()));
+ containsNullValue = singletonList(entry(k3(), null));
}
@MapFeature.Require(SUPPORTS_PUT)
@@ -78,7 +78,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
@MapFeature.Require(SUPPORTS_PUT)
public void testPutAll_supportedNonePresent() {
putAll(createDisjointCollection());
- expectAdded(samples.e3, samples.e4);
+ expectAdded(e3(), e4());
}
@MapFeature.Require(absent = SUPPORTS_PUT)
@@ -89,14 +89,14 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- expectMissing(samples.e3, samples.e4);
+ expectMissing(e3(), e4());
}
@MapFeature.Require(SUPPORTS_PUT)
@CollectionSize.Require(absent = ZERO)
public void testPutAll_supportedSomePresent() {
- putAll(MinimalCollection.of(samples.e3, samples.e0));
- expectAdded(samples.e3);
+ putAll(MinimalCollection.of(e3(), e0()));
+ expectAdded(e3());
}
@MapFeature.Require({ FAILS_FAST_ON_CONCURRENT_MODIFICATION,
@@ -105,7 +105,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
public void testPutAllSomePresentConcurrentWithEntrySetIteration() {
try {
Iterator<Entry<K, V>> iterator = getMap().entrySet().iterator();
- putAll(MinimalCollection.of(samples.e3, samples.e0));
+ putAll(MinimalCollection.of(e3(), e0()));
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -117,7 +117,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testPutAll_unsupportedSomePresent() {
try {
- putAll(MinimalCollection.of(samples.e3, samples.e0));
+ putAll(MinimalCollection.of(e3(), e0()));
fail("putAll(somePresent) should throw");
} catch (UnsupportedOperationException expected) {
}
@@ -128,7 +128,7 @@ public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testPutAll_unsupportedAllPresent() {
try {
- putAll(MinimalCollection.of(samples.e0));
+ putAll(MinimalCollection.of(e0()));
} catch (UnsupportedOperationException tolerated) {
}
expectUnchanged();
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapPutTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapPutTester.java
index 6fb2918..13ee949 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapPutTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapPutTester.java
@@ -53,16 +53,16 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
@Override public void setUp() throws Exception {
super.setUp();
- nullKeyEntry = entry(null, samples.e3.getValue());
- nullValueEntry = entry(samples.e3.getKey(), null);
+ nullKeyEntry = entry(null, v3());
+ nullValueEntry = entry(k3(), null);
nullKeyValueEntry = entry(null, null);
- presentKeyNullValueEntry = entry(samples.e0.getKey(), null);
+ presentKeyNullValueEntry = entry(k0(), null);
}
@MapFeature.Require(SUPPORTS_PUT)
public void testPut_supportedNotPresent() {
- assertNull("put(notPresent, value) should return null", put(samples.e3));
- expectAdded(samples.e3);
+ assertNull("put(notPresent, value) should return null", put(e3()));
+ expectAdded(e3());
}
@MapFeature.Require({FAILS_FAST_ON_CONCURRENT_MODIFICATION, SUPPORTS_PUT})
@@ -70,7 +70,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
public void testPutAbsentConcurrentWithEntrySetIteration() {
try {
Iterator<Entry<K, V>> iterator = getMap().entrySet().iterator();
- put(samples.e3);
+ put(e3());
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -83,7 +83,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
public void testPutAbsentConcurrentWithKeySetIteration() {
try {
Iterator<K> iterator = getMap().keySet().iterator();
- put(samples.e3);
+ put(e3());
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -96,7 +96,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
public void testPutAbsentConcurrentWithValueIteration() {
try {
Iterator<V> iterator = getMap().values().iterator();
- put(samples.e3);
+ put(e3());
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -107,12 +107,12 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
@MapFeature.Require(absent = SUPPORTS_PUT)
public void testPut_unsupportedNotPresent() {
try {
- put(samples.e3);
+ put(e3());
fail("put(notPresent, value) should throw");
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
@MapFeature.Require(absent = SUPPORTS_PUT)
@@ -120,7 +120,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
public void testPut_unsupportedPresentExistingValue() {
try {
assertEquals("put(present, existingValue) should return present or throw",
- samples.e0.getValue(), put(samples.e0));
+ v0(), put(e0()));
} catch (UnsupportedOperationException tolerated) {
}
expectUnchanged();
@@ -130,7 +130,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testPut_unsupportedPresentDifferentValue() {
try {
- getMap().put(samples.e0.getKey(), samples.e3.getValue());
+ getMap().put(k0(), v3());
fail("put(present, differentValue) should throw");
} catch (UnsupportedOperationException expected) {
}
@@ -146,7 +146,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
@MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS})
@CollectionSize.Require(absent = ZERO)
public void testPut_nullKeySupportedPresent() {
- Entry<K, V> newEntry = entry(null, samples.e3.getValue());
+ Entry<K, V> newEntry = entry(null, v3());
initMapWithNullKey();
assertEquals("put(present, value) should return the associated value",
getValueForNullKey(), put(newEntry));
@@ -190,7 +190,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testPut_replaceWithNullValueSupported() {
assertEquals("put(present, null) should return the associated value",
- samples.e0.getValue(), put(presentKeyNullValueEntry));
+ v0(), put(presentKeyNullValueEntry));
expectReplacement(presentKeyNullValueEntry);
}
@@ -219,7 +219,7 @@ public class MapPutTester<K, V> extends AbstractMapTester<K, V> {
@MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
@CollectionSize.Require(absent = ZERO)
public void testPut_replaceNullValueWithNonNullSupported() {
- Entry<K, V> newEntry = entry(getKeyForNullValue(), samples.e3.getValue());
+ Entry<K, V> newEntry = entry(getKeyForNullValue(), v3());
initMapWithNullValue();
assertNull("put(present, value) should return the associated value (null)",
put(newEntry));
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapRemoveTester.java
index 5310a8e..7cc960e 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapRemoveTester.java
@@ -49,10 +49,10 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
public void testRemove_present() {
int initialSize = getMap().size();
assertEquals("remove(present) should return the associated value",
- samples.e0.getValue(), getMap().remove(samples.e0.getKey()));
+ v0(), getMap().remove(k0()));
assertEquals("remove(present) should decrease a map's size by one.",
initialSize - 1, getMap().size());
- expectMissing(samples.e0);
+ expectMissing(e0());
}
@MapFeature.Require({FAILS_FAST_ON_CONCURRENT_MODIFICATION,
@@ -61,7 +61,7 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
public void testRemovePresentConcurrentWithEntrySetIteration() {
try {
Iterator<Entry<K, V>> iterator = getMap().entrySet().iterator();
- getMap().remove(samples.e0.getKey());
+ getMap().remove(k0());
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -75,7 +75,7 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
public void testRemovePresentConcurrentWithKeySetIteration() {
try {
Iterator<K> iterator = getMap().keySet().iterator();
- getMap().remove(samples.e0.getKey());
+ getMap().remove(k0());
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -89,7 +89,7 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
public void testRemovePresentConcurrentWithValuesIteration() {
try {
Iterator<V> iterator = getMap().values().iterator();
- getMap().remove(samples.e0.getKey());
+ getMap().remove(k0());
iterator.next();
fail("Expected ConcurrentModificationException");
} catch (ConcurrentModificationException expected) {
@@ -100,7 +100,7 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
@MapFeature.Require(SUPPORTS_REMOVE)
public void testRemove_notPresent() {
assertNull("remove(notPresent) should return null",
- getMap().remove(samples.e3.getKey()));
+ getMap().remove(k3()));
expectUnchanged();
}
@@ -121,13 +121,13 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(absent = ZERO)
public void testRemove_unsupported() {
try {
- getMap().remove(samples.e0.getKey());
+ getMap().remove(k0());
fail("remove(present) should throw UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
expectUnchanged();
assertEquals("remove(present) should not remove the element",
- samples.e0.getValue(), get(samples.e0.getKey()));
+ v0(), get(k0()));
}
@MapFeature.Require(absent = SUPPORTS_REMOVE)
@@ -135,11 +135,11 @@ public class MapRemoveTester<K, V> extends AbstractMapTester<K, V> {
try {
assertNull("remove(notPresent) should return null or throw "
+ "UnsupportedOperationException",
- getMap().remove(samples.e3.getKey()));
+ getMap().remove(k3()));
} catch (UnsupportedOperationException tolerated) {
}
expectUnchanged();
- expectMissing(samples.e3);
+ expectMissing(e3());
}
@MapFeature.Require(
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/MapToStringTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/MapToStringTester.java
index 2d01349..2b9709f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/MapToStringTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/MapToStringTester.java
@@ -50,7 +50,7 @@ public class MapToStringTester<K, V> extends AbstractMapTester<K, V> {
@CollectionSize.Require(ONE)
public void testToString_size1() {
assertEquals(
- "size1Map.toString should return {entry}", "{" + samples.e0 + "}", getMap().toString());
+ "size1Map.toString should return {entry}", "{" + e0() + "}", getMap().toString());
}
@CollectionSize.Require(absent = ZERO)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/NavigableMapNavigationTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/NavigableMapNavigationTester.java
index daf46ff..dbb3489 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/NavigableMapNavigationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/NavigableMapNavigationTester.java
@@ -88,14 +88,14 @@ public class NavigableMapNavigationTester<K, V> extends AbstractMapTester<K, V>
@CollectionSize.Require(ZERO)
public void testEmptyMapNearby() {
- assertNull(navigableMap.lowerEntry(samples.e0.getKey()));
- assertNull(navigableMap.lowerKey(samples.e0.getKey()));
- assertNull(navigableMap.floorEntry(samples.e0.getKey()));
- assertNull(navigableMap.floorKey(samples.e0.getKey()));
- assertNull(navigableMap.ceilingEntry(samples.e0.getKey()));
- assertNull(navigableMap.ceilingKey(samples.e0.getKey()));
- assertNull(navigableMap.higherEntry(samples.e0.getKey()));
- assertNull(navigableMap.higherKey(samples.e0.getKey()));
+ assertNull(navigableMap.lowerEntry(k0()));
+ assertNull(navigableMap.lowerKey(k0()));
+ assertNull(navigableMap.floorEntry(k0()));
+ assertNull(navigableMap.floorKey(k0()));
+ assertNull(navigableMap.ceilingEntry(k0()));
+ assertNull(navigableMap.ceilingKey(k0()));
+ assertNull(navigableMap.higherEntry(k0()));
+ assertNull(navigableMap.higherKey(k0()));
}
@CollectionSize.Require(ZERO)
@@ -123,14 +123,14 @@ public class NavigableMapNavigationTester<K, V> extends AbstractMapTester<K, V>
@CollectionSize.Require(ONE)
public void testSingletonMapNearby() {
- assertNull(navigableMap.lowerEntry(samples.e0.getKey()));
- assertNull(navigableMap.lowerKey(samples.e0.getKey()));
- assertEquals(a, navigableMap.floorEntry(samples.e0.getKey()));
- assertEquals(a.getKey(), navigableMap.floorKey(samples.e0.getKey()));
- assertEquals(a, navigableMap.ceilingEntry(samples.e0.getKey()));
- assertEquals(a.getKey(), navigableMap.ceilingKey(samples.e0.getKey()));
- assertNull(navigableMap.higherEntry(samples.e0.getKey()));
- assertNull(navigableMap.higherKey(samples.e0.getKey()));
+ assertNull(navigableMap.lowerEntry(k0()));
+ assertNull(navigableMap.lowerKey(k0()));
+ assertEquals(a, navigableMap.floorEntry(k0()));
+ assertEquals(a.getKey(), navigableMap.floorKey(k0()));
+ assertEquals(a, navigableMap.ceilingEntry(k0()));
+ assertEquals(a.getKey(), navigableMap.ceilingKey(k0()));
+ assertNull(navigableMap.higherEntry(k0()));
+ assertNull(navigableMap.higherKey(k0()));
}
@CollectionSize.Require(ONE)
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/NavigableSetNavigationTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/NavigableSetNavigationTester.java
index 14c6a47..b1ba7ff 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/NavigableSetNavigationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/NavigableSetNavigationTester.java
@@ -82,10 +82,10 @@ public class NavigableSetNavigationTester<E> extends AbstractSetTester<E> {
@CollectionSize.Require(ZERO)
public void testEmptySetNearby() {
- assertNull(navigableSet.lower(samples.e0));
- assertNull(navigableSet.floor(samples.e0));
- assertNull(navigableSet.ceiling(samples.e0));
- assertNull(navigableSet.higher(samples.e0));
+ assertNull(navigableSet.lower(e0()));
+ assertNull(navigableSet.floor(e0()));
+ assertNull(navigableSet.ceiling(e0()));
+ assertNull(navigableSet.higher(e0()));
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
@@ -103,10 +103,10 @@ public class NavigableSetNavigationTester<E> extends AbstractSetTester<E> {
@CollectionSize.Require(ONE)
public void testSingletonSetNearby() {
- assertNull(navigableSet.lower(samples.e0));
- assertEquals(a, navigableSet.floor(samples.e0));
- assertEquals(a, navigableSet.ceiling(samples.e0));
- assertNull(navigableSet.higher(samples.e0));
+ assertNull(navigableSet.lower(e0()));
+ assertEquals(a, navigableSet.floor(e0()));
+ assertEquals(a, navigableSet.ceiling(e0()));
+ assertNull(navigableSet.higher(e0()));
}
@CollectionFeature.Require(SUPPORTS_REMOVE)
@@ -226,7 +226,7 @@ public class NavigableSetNavigationTester<E> extends AbstractSetTester<E> {
}
public void testEmptySubSet() {
- NavigableSet<E> empty = navigableSet.subSet(samples.e0, false, samples.e0, false);
+ NavigableSet<E> empty = navigableSet.subSet(e0(), false, e0(), false);
assertEquals(new TreeSet<E>(), empty);
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/Platform.java b/guava-testlib/src/com/google/common/collect/testing/testers/Platform.java
index bb40f8e..e76f5f2 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/Platform.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/Platform.java
@@ -18,6 +18,8 @@ package com.google.common.collect.testing.testers;
import com.google.common.annotations.GwtCompatible;
+import java.util.Locale;
+
/**
* This class is emulated in GWT.
*
@@ -31,7 +33,7 @@ final class Platform {
* {@code %s}.
*/
static String format(String template, Object... args) {
- return String.format(template, args);
+ return String.format(Locale.ROOT, template, args);
}
/** See {@link ListListIteratorTester} */
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/QueueElementTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/QueueElementTester.java
index 6282c1b..efa6b0f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/QueueElementTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/QueueElementTester.java
@@ -48,7 +48,7 @@ public class QueueElementTester<E> extends AbstractQueueTester<E> {
@CollectionSize.Require(ONE)
public void testElement_size1() {
assertEquals("size1Queue.element() should return first element",
- samples.e0, getQueue().element());
+ e0(), getQueue().element());
expectUnchanged();
}
@@ -56,7 +56,7 @@ public class QueueElementTester<E> extends AbstractQueueTester<E> {
@CollectionSize.Require(SEVERAL)
public void testElement_sizeMany() {
assertEquals("sizeManyQueue.element() should return first element",
- samples.e0, getQueue().element());
+ e0(), getQueue().element());
expectUnchanged();
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/QueueOfferTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/QueueOfferTester.java
index e38b6a2..92a9a23 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/QueueOfferTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/QueueOfferTester.java
@@ -35,8 +35,8 @@ public class QueueOfferTester<E> extends AbstractQueueTester<E> {
@CollectionFeature.Require(SUPPORTS_ADD)
public void testOffer_supportedNotPresent() {
assertTrue("offer(notPresent) should return true",
- getQueue().offer(samples.e3));
- expectAdded(samples.e3);
+ getQueue().offer(e3()));
+ expectAdded(e3());
}
@CollectionFeature.Require({SUPPORTS_ADD, ALLOWS_NULL_VALUES})
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/QueuePeekTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/QueuePeekTester.java
index 5d270c5..fa83281 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/QueuePeekTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/QueuePeekTester.java
@@ -43,7 +43,7 @@ public class QueuePeekTester<E> extends AbstractQueueTester<E> {
@CollectionSize.Require(ONE)
public void testPeek_size1() {
assertEquals("size1Queue.peek() should return first element",
- samples.e0, getQueue().peek());
+ e0(), getQueue().peek());
expectUnchanged();
}
@@ -51,7 +51,7 @@ public class QueuePeekTester<E> extends AbstractQueueTester<E> {
@CollectionSize.Require(SEVERAL)
public void testPeek_sizeMany() {
assertEquals("sizeManyQueue.peek() should return first element",
- samples.e0, getQueue().peek());
+ e0(), getQueue().peek());
expectUnchanged();
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/QueuePollTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/QueuePollTester.java
index fd10a3d..ae0cba8 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/QueuePollTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/QueuePollTester.java
@@ -47,15 +47,15 @@ public class QueuePollTester<E> extends AbstractQueueTester<E> {
@CollectionSize.Require(ONE)
public void testPoll_size1() {
assertEquals("size1Queue.poll() should return first element",
- samples.e0, getQueue().poll());
- expectMissing(samples.e0);
+ e0(), getQueue().poll());
+ expectMissing(e0());
}
@CollectionFeature.Require({KNOWN_ORDER, SUPPORTS_REMOVE})
@CollectionSize.Require(SEVERAL)
public void testPoll_sizeMany() {
assertEquals("sizeManyQueue.poll() should return first element",
- samples.e0, getQueue().poll());
- expectMissing(samples.e0);
+ e0(), getQueue().poll());
+ expectMissing(e0());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/QueueRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/QueueRemoveTester.java
index 07f447f..70c9513 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/QueueRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/QueueRemoveTester.java
@@ -52,15 +52,15 @@ public class QueueRemoveTester<E> extends AbstractQueueTester<E> {
@CollectionSize.Require(ONE)
public void testRemove_size1() {
assertEquals("size1Queue.remove() should return first element",
- samples.e0, getQueue().remove());
- expectMissing(samples.e0);
+ e0(), getQueue().remove());
+ expectMissing(e0());
}
@CollectionFeature.Require({KNOWN_ORDER, SUPPORTS_REMOVE})
@CollectionSize.Require(SEVERAL)
public void testRemove_sizeMany() {
assertEquals("sizeManyQueue.remove() should return first element",
- samples.e0, getQueue().remove());
- expectMissing(samples.e0);
+ e0(), getQueue().remove());
+ expectMissing(e0());
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/SetAddAllTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/SetAddAllTester.java
index 4d2bfcc..b9d55f7 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/SetAddAllTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/SetAddAllTester.java
@@ -38,24 +38,24 @@ public class SetAddAllTester<E> extends AbstractSetTester<E> {
@CollectionSize.Require(absent = ZERO)
public void testAddAll_supportedSomePresent() {
assertTrue("add(somePresent) should return true",
- getSet().addAll(MinimalCollection.of(samples.e3, samples.e0)));
- expectAdded(samples.e3);
+ getSet().addAll(MinimalCollection.of(e3(), e0())));
+ expectAdded(e3());
}
@CollectionFeature.Require(SUPPORTS_ADD)
public void testAddAll_withDuplicates() {
MinimalCollection<E> elementsToAdd
- = MinimalCollection.of(samples.e3, samples.e4, samples.e3, samples.e4);
+ = MinimalCollection.of(e3(), e4(), e3(), e4());
assertTrue("add(hasDuplicates) should return true",
getSet().addAll(elementsToAdd));
- expectAdded(samples.e3, samples.e4);
+ expectAdded(e3(), e4());
}
@CollectionFeature.Require(SUPPORTS_ADD)
@CollectionSize.Require(absent = ZERO)
public void testAddAll_supportedAllPresent() {
assertFalse("add(allPresent) should return false",
- getSet().addAll(MinimalCollection.of(samples.e0)));
+ getSet().addAll(MinimalCollection.of(e0())));
expectUnchanged();
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/SetAddTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/SetAddTester.java
index 47755e3..90dab5f 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/SetAddTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/SetAddTester.java
@@ -40,7 +40,7 @@ public class SetAddTester<E> extends AbstractSetTester<E> {
@CollectionFeature.Require(SUPPORTS_ADD)
@CollectionSize.Require(absent = ZERO)
public void testAdd_supportedPresent() {
- assertFalse("add(present) should return false", getSet().add(samples.e0));
+ assertFalse("add(present) should return false", getSet().add(e0()));
expectUnchanged();
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/SetCreationTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/SetCreationTester.java
index 6602852..6a25297 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/SetCreationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/SetCreationTester.java
@@ -54,7 +54,7 @@ public class SetCreationTester<E> extends AbstractSetTester<E> {
@CollectionSize.Require(absent = {ZERO, ONE})
public void testCreateWithDuplicates_nonNullDuplicatesNotRejected() {
E[] array = createSamplesArray();
- array[1] = samples.e0;
+ array[1] = e0();
collection = getSubjectGenerator().create(array);
List<E> expectedWithDuplicateRemoved =
@@ -79,7 +79,7 @@ public class SetCreationTester<E> extends AbstractSetTester<E> {
@CollectionSize.Require(absent = {ZERO, ONE})
public void testCreateWithDuplicates_nonNullDuplicatesRejected() {
E[] array = createSamplesArray();
- array[1] = samples.e0;
+ array[1] = e0();
try {
collection = getSubjectGenerator().create(array);
fail("Should reject duplicate non-null elements at creation");
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/SetEqualsTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/SetEqualsTester.java
index 25e0dc6..8d94ac4 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/SetEqualsTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/SetEqualsTester.java
@@ -43,7 +43,7 @@ public class SetEqualsTester<E> extends AbstractSetTester<E> {
@CollectionSize.Require(absent = CollectionSize.ZERO)
public void testEquals_otherSetWithDifferentElements() {
Collection<E> elements = getSampleElements(getNumElements() - 1);
- elements.add(getSubjectGenerator().samples().e3);
+ elements.add(getSubjectGenerator().samples().e3());
assertFalse(
"A Set should not equal another Set containing different elements.",
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/SetRemoveTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/SetRemoveTester.java
index 5bef4c4..e700e00 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/SetRemoveTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/SetRemoveTester.java
@@ -35,9 +35,9 @@ public class SetRemoveTester<E> extends AbstractSetTester<E> {
@CollectionFeature.Require(SUPPORTS_REMOVE)
@CollectionSize.Require(absent = ZERO)
public void testRemove_present() {
- getSet().remove(samples.e0);
+ getSet().remove(e0());
assertFalse("After remove(present) a set should not contain "
+ "the removed element.",
- getSet().contains(samples.e0));
+ getSet().contains(e0()));
}
}
diff --git a/guava-testlib/src/com/google/common/collect/testing/testers/SortedMapNavigationTester.java b/guava-testlib/src/com/google/common/collect/testing/testers/SortedMapNavigationTester.java
index 99446b5..94655d9 100644
--- a/guava-testlib/src/com/google/common/collect/testing/testers/SortedMapNavigationTester.java
+++ b/guava-testlib/src/com/google/common/collect/testing/testers/SortedMapNavigationTester.java
@@ -16,10 +16,10 @@
package com.google.common.collect.testing.testers;
+import static com.google.common.collect.testing.Helpers.assertEqualInOrder;
import static com.google.common.collect.testing.features.CollectionSize.ONE;
import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
import static com.google.common.collect.testing.features.CollectionSize.ZERO;
-import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.testing.AbstractMapTester;
@@ -101,51 +101,49 @@ public class SortedMapNavigationTester<K, V> extends AbstractMapTester<K, V> {
public void testLast() {
assertEquals(c.getKey(), navigableMap.lastKey());
}
-
+
@CollectionSize.Require(absent = ZERO)
public void testHeadMapExclusive() {
assertFalse(navigableMap.headMap(a.getKey()).containsKey(a.getKey()));
}
-
+
@CollectionSize.Require(absent = ZERO)
public void testTailMapInclusive() {
assertTrue(navigableMap.tailMap(a.getKey()).containsKey(a.getKey()));
}
-
+
public void testHeadMap() {
List<Entry<K, V>> entries = Helpers.copyToList(getSubjectGenerator().getSampleElements(
getSubjectGenerator().getCollectionSize().getNumElements()));
Collections.sort(entries, Helpers.<K, V>entryComparator(navigableMap.comparator()));
for (int i = 0; i < entries.size(); i++) {
- assertThat(navigableMap.headMap(entries.get(i).getKey()).entrySet())
- .iteratesAs(entries.subList(0, i));
+ assertEqualInOrder(entries.subList(0, i),
+ navigableMap.headMap(entries.get(i).getKey()).entrySet());
}
}
-
+
public void testTailMap() {
List<Entry<K, V>> entries = Helpers.copyToList(getSubjectGenerator().getSampleElements(
getSubjectGenerator().getCollectionSize().getNumElements()));
Collections.sort(entries, Helpers.<K, V>entryComparator(navigableMap.comparator()));
for (int i = 0; i < entries.size(); i++) {
- assertThat(navigableMap.tailMap(entries.get(i).getKey()).entrySet())
- .iteratesAs(entries.subList(i, entries.size()));
+ assertEqualInOrder(entries.subList(i, entries.size()),
+ navigableMap.tailMap(entries.get(i).getKey()).entrySet());
}
}
-
+
public void testSubMap() {
List<Entry<K, V>> entries = Helpers.copyToList(getSubjectGenerator().getSampleElements(
getSubjectGenerator().getCollectionSize().getNumElements()));
Collections.sort(entries, Helpers.<K, V>entryComparator(navigableMap.comparator()));
for (int i = 0; i < entries.size(); i++) {
for (int j = i + 1; j < entries.size(); j++) {
- assertThat(navigableMap
- .subMap(entries.get(i).getKey(), entries.get(j).getKey())
- .entrySet())
- .iteratesAs(entries.subList(i, j));
+ assertEqualInOrder(entries.subList(i, j),
+ navigableMap.subMap(entries.get(i).getKey(), entries.get(j).getKey()).entrySet());
}
}
}
-
+
@CollectionSize.Require(SEVERAL)
public void testSubMapIllegal() {
try {
@@ -153,7 +151,7 @@ public class SortedMapNavigationTester<K, V> extends AbstractMapTester<K, V> {
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {}
}
-
+
@CollectionSize.Require(absent = ZERO)
public void testOrderedByComparator() {
@SuppressWarnings("unchecked")
diff --git a/guava-testlib/src/com/google/common/testing/AbstractPackageSanityTests.java b/guava-testlib/src/com/google/common/testing/AbstractPackageSanityTests.java
index d324a38..228e795 100644
--- a/guava-testlib/src/com/google/common/testing/AbstractPackageSanityTests.java
+++ b/guava-testlib/src/com/google/common/testing/AbstractPackageSanityTests.java
@@ -33,6 +33,7 @@ import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.reflect.ClassPath;
import com.google.common.testing.NullPointerTester.Visibility;
+import com.google.j2objc.annotations.J2ObjCIncompatible;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
@@ -43,6 +44,7 @@ import java.io.IOException;
import java.io.Serializable;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Locale;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -84,7 +86,9 @@ import java.util.logging.Logger;
* <p>please use {@link ClassSanityTester#forAllPublicStaticMethods}.
*
* <p>If not all classes on the classpath should be covered, {@link
- * #ignoreClasses} can be used to exclude certain classes.
+ * #ignoreClasses} can be used to exclude certain classes. As a special case, classes with an
+ * underscore in the name (like {@code AutoValue_Foo}) can be excluded using
+ * <code>ignoreClasses({@link #UNDERSCORE_IN_NAME})</code>.
*
* <p>{@link #setDefault} allows subclasses to specify default values for types.
*
@@ -95,8 +99,22 @@ import java.util.logging.Logger;
*/
@Beta
// TODO: Switch to JUnit 4 and use @Parameterized and @BeforeClass
+ at J2ObjCIncompatible // com.google.common.reflect.ClassPath
public abstract class AbstractPackageSanityTests extends TestCase {
+ /**
+ * A predicate that matches classes with an underscore in the class name. This can be used with
+ * {@link #ignoreClasses} to exclude generated classes, such as the {@code AutoValue_Foo} classes
+ * generated by <a href="https://github.com/google/auto/tree/master/value">AutoValue</a>.
+ *
+ * @since 19.0
+ */
+ public static final Predicate<Class<?>> UNDERSCORE_IN_NAME = new Predicate<Class<?>>() {
+ @Override public boolean apply(Class<?> c) {
+ return c.getSimpleName().contains("_");
+ }
+ };
+
/* The names of the expected method that tests null checks. */
private static final ImmutableList<String> NULL_TEST_METHOD_NAMES = ImmutableList.of(
"testNulls", "testNull",
@@ -281,7 +299,7 @@ public abstract class AbstractPackageSanityTests extends TestCase {
private static AssertionFailedError sanityError(
Class<?> cls, List<String> explicitTestNames, String description, Throwable e) {
- String message = String.format(
+ String message = String.format(Locale.ROOT,
"Error in automated %s of %s\n"
+ "If the class is better tested explicitly, you can add %s() to %sTest",
description, cls, explicitTestNames.get(0), cls.getName());
@@ -368,7 +386,7 @@ public abstract class AbstractPackageSanityTests extends TestCase {
}
}
- static abstract class Chopper {
+ abstract static class Chopper {
final Chopper or(final Chopper you) {
final Chopper i = this;
diff --git a/guava-testlib/src/com/google/common/testing/ArbitraryInstances.java b/guava-testlib/src/com/google/common/testing/ArbitraryInstances.java
index 6e28db7..846ee9b 100644
--- a/guava-testlib/src/com/google/common/testing/ArbitraryInstances.java
+++ b/guava-testlib/src/com/google/common/testing/ArbitraryInstances.java
@@ -150,7 +150,7 @@ import javax.annotation.Nullable;
/**
* Supplies an arbitrary "default" instance for a wide range of types, often useful in testing
* utilities.
- *
+ *
* <p>Covers arrays, enums and common types defined in {@code java.lang}, {@code java.lang.reflect},
* {@code java.io}, {@code java.nio}, {@code java.math}, {@code java.util}, {@code
* java.util.concurrent}, {@code java.util.regex}, {@code com.google.common.base}, {@code
@@ -158,7 +158,7 @@ import javax.annotation.Nullable;
* exposes at least one public static final constant of the same type, one of the constants will be
* used; or if the class exposes a public parameter-less constructor then it will be "new"d and
* returned.
- *
+ *
* <p>All default instances returned by {@link #get} are generics-safe. Clients won't get type
* errors for using {@code get(Comparator.class)} as a {@code Comparator<Foo>}, for example.
* Immutable empty instances are returned for collection types; {@code ""} for string;
@@ -235,7 +235,7 @@ public final class ArbitraryInstances {
.put(CharSink.class, NullByteSink.INSTANCE.asCharSink(Charsets.UTF_8))
// All collections are immutable empty. So safe for any type parameter.
.put(Iterator.class, ImmutableSet.of().iterator())
- .put(PeekingIterator.class, Iterators.peekingIterator(Iterators.emptyIterator()))
+ .put(PeekingIterator.class, Iterators.peekingIterator(ImmutableSet.of().iterator()))
.put(ListIterator.class, ImmutableList.of().listIterator())
.put(Iterable.class, ImmutableSet.of())
.put(Collection.class, ImmutableList.of())
@@ -420,7 +420,6 @@ public final class ArbitraryInstances {
}
public static final class DeterministicRandom extends Random {
- @SuppressWarnings("unused") // invoked by reflection
public DeterministicRandom() {
super(0);
}
diff --git a/guava-testlib/src/com/google/common/testing/ClassSanityTester.java b/guava-testlib/src/com/google/common/testing/ClassSanityTester.java
index 3eeb1f1..c7d70e8 100644
--- a/guava-testlib/src/com/google/common/testing/ClassSanityTester.java
+++ b/guava-testlib/src/com/google/common/testing/ClassSanityTester.java
@@ -124,7 +124,7 @@ public final class ClassSanityTester {
/**
* Sets the default value for {@code type}. The default value isn't used in testing {@link
* Object#equals} because more than one sample instances are needed for testing inequality.
- * To set sample instances for equality testing, use {@link #setSampleInstances} instead.
+ * To set distinct values for equality testing, use {@link #setDistinctValues} instead.
*/
public <T> ClassSanityTester setDefault(Class<T> type, T value) {
nullPointerTester.setDefault(type, value);
@@ -142,13 +142,14 @@ public final class ClassSanityTester {
* exception that if the sample instance is to be passed to a {@link Nullable} parameter, one
* non-null sample is sufficient. Setting an empty list will clear sample instances for {@code
* type}.
-
*
-
- * @deprecated Use {@link #setDistinctValues} instead.
+ * @deprecated To supply multiple values, use {@link #setDistinctValues}. It accepts only two
+ * values, which is enough for any {@code equals} testing. To supply a single value, use
+ * {@link #setDefault}. This method will be removed in Guava release 20.0.
*/
@Deprecated
- public <T> ClassSanityTester setSampleInstances(Class<T> type, Iterable<? extends T> instances) {
+ public <T> ClassSanityTester setSampleInstances(
+ Class<T> type, Iterable<? extends T> instances) {
ImmutableList<? extends T> samples = ImmutableList.copyOf(instances);
Set<Object> uniqueValues = new HashSet<Object>();
for (T instance : instances) {
@@ -300,7 +301,7 @@ public final class ClassSanityTester {
throw Throwables.propagate(e);
}
}
-
+
void doTestEquals(Class<?> cls)
throws ParameterNotInstantiableException, ParameterHasNoDistinctValueException,
IllegalAccessException, InvocationTargetException, FactoryMethodReturnsNullException {
@@ -594,7 +595,7 @@ public final class ClassSanityTester {
tester.addEqualityGroup(instance, createInstance(factory, equalArgs));
for (int i = 0; i < params.size(); i++) {
List<Object> newArgs = Lists.newArrayList(args);
- Object newArg = argGenerators.get(i).generate(params.get(i).getType());
+ Object newArg = argGenerators.get(i).generateFresh(params.get(i).getType());
if (newArg == null || Objects.equal(args.get(i), newArg)) {
if (params.get(i).getType().getRawType().isEnum()) {
@@ -662,12 +663,12 @@ public final class ClassSanityTester {
return generator;
}
- private static @Nullable Object generateDummyArg(Parameter param, FreshValueGenerator generator)
+ @Nullable private static Object generateDummyArg(Parameter param, FreshValueGenerator generator)
throws ParameterNotInstantiableException {
if (param.isAnnotationPresent(Nullable.class)) {
return null;
}
- Object arg = generator.generate(param.getType());
+ Object arg = generator.generateFresh(param.getType());
if (arg == null) {
throw new ParameterNotInstantiableException(param);
}
@@ -688,7 +689,7 @@ public final class ClassSanityTester {
if (!invokable.isPrivate()
&& !invokable.isSynthetic()
&& invokable.isStatic()
- && type.isAssignableFrom(invokable.getReturnType())) {
+ && type.isSupertypeOf(invokable.getReturnType())) {
@SuppressWarnings("unchecked") // guarded by isAssignableFrom()
Invokable<?, ? extends T> factory = (Invokable<?, ? extends T>) invokable;
factories.add(factory);
@@ -802,7 +803,7 @@ public final class ClassSanityTester {
private static final class SerializableDummyProxy extends DummyProxy
implements Serializable {
- private transient final ClassSanityTester tester;
+ private final transient ClassSanityTester tester;
SerializableDummyProxy(ClassSanityTester tester) {
this.tester = tester;
@@ -821,4 +822,3 @@ public final class ClassSanityTester {
}
}
}
-
diff --git a/guava-testlib/src/com/google/common/testing/ForwardingWrapperTester.java b/guava-testlib/src/com/google/common/testing/ForwardingWrapperTester.java
index 74710e3..d3f0c75 100644
--- a/guava-testlib/src/com/google/common/testing/ForwardingWrapperTester.java
+++ b/guava-testlib/src/com/google/common/testing/ForwardingWrapperTester.java
@@ -148,17 +148,17 @@ public final class ForwardingWrapperTester {
private static <T> void testEquals(
Class<T> interfaceType, Function<? super T, ? extends T> wrapperFunction) {
FreshValueGenerator generator = new FreshValueGenerator();
- T instance = generator.newProxy(interfaceType);
+ T instance = generator.newFreshProxy(interfaceType);
new EqualsTester()
.addEqualityGroup(wrapperFunction.apply(instance), wrapperFunction.apply(instance))
- .addEqualityGroup(wrapperFunction.apply(generator.newProxy(interfaceType)))
+ .addEqualityGroup(wrapperFunction.apply(generator.newFreshProxy(interfaceType)))
// TODO: add an overload to EqualsTester to print custom error message?
.testEquals();
}
private static <T> void testToString(
Class<T> interfaceType, Function<? super T, ? extends T> wrapperFunction) {
- T proxy = new FreshValueGenerator().newProxy(interfaceType);
+ T proxy = new FreshValueGenerator().newFreshProxy(interfaceType);
assertEquals("toString() isn't properly forwarded",
proxy.toString(), wrapperFunction.apply(proxy).toString());
}
@@ -167,7 +167,7 @@ public final class ForwardingWrapperTester {
FreshValueGenerator paramValues = new FreshValueGenerator();
final List<Object> passedArgs = Lists.newArrayList();
for (Class<?> paramType : method.getParameterTypes()) {
- passedArgs.add(paramValues.generate(paramType));
+ passedArgs.add(paramValues.generateFresh(paramType));
}
return passedArgs.toArray();
}
@@ -185,7 +185,7 @@ public final class ForwardingWrapperTester {
this.interfaceType = interfaceType;
this.method = method;
this.passedArgs = getParameterValues(method);
- this.returnValue = new FreshValueGenerator().generate(method.getReturnType());
+ this.returnValue = new FreshValueGenerator().generateFresh(method.getReturnType());
}
@Override protected Object handleInvocation(Object p, Method calledMethod, Object[] args)
diff --git a/guava-testlib/src/com/google/common/testing/FreshValueGenerator.java b/guava-testlib/src/com/google/common/testing/FreshValueGenerator.java
index a656c83..9a178f3 100644
--- a/guava-testlib/src/com/google/common/testing/FreshValueGenerator.java
+++ b/guava-testlib/src/com/google/common/testing/FreshValueGenerator.java
@@ -141,11 +141,28 @@ class FreshValueGenerator {
GENERATORS = builder.build();
}
- private final AtomicInteger differentiator = new AtomicInteger(1);
+ private static final ImmutableMap<Class<?>, Method> EMPTY_GENERATORS;
+ static {
+ ImmutableMap.Builder<Class<?>, Method> builder =
+ ImmutableMap.builder();
+ for (Method method : FreshValueGenerator.class.getDeclaredMethods()) {
+ if (method.isAnnotationPresent(Empty.class)) {
+ builder.put(method.getReturnType(), method);
+ }
+ }
+ EMPTY_GENERATORS = builder.build();
+ }
+
+ private final AtomicInteger freshness = new AtomicInteger(1);
private final ListMultimap<Class<?>, Object> sampleInstances = ArrayListMultimap.create();
- private final Set<Type> generatedOptionalTypes = Sets.newHashSet();
- <T> void addSampleInstances(Class<T> type, Iterable<? extends T> instances) {
+ /**
+ * The freshness level at which the {@link Empty @Empty} annotated method was invoked to generate
+ * instance.
+ */
+ private final Map<Type, Integer> emptyInstanceGenerated = new HashMap<Type, Integer>();
+
+ final <T> void addSampleInstances(Class<T> type, Iterable<? extends T> instances) {
sampleInstances.putAll(checkNotNull(type), checkNotNull(instances));
}
@@ -155,18 +172,40 @@ class FreshValueGenerator {
* <li>exactly of the given type, including generic type parameters, such as
* {@code ImmutableList<String>};
* <li>of the raw type;
- * <li>null if no fresh value can be generated.
+ * <li>null if no value can be generated.
* </ul>
*/
- @Nullable Object generate(TypeToken<?> type) {
+ @Nullable final Object generateFresh(TypeToken<?> type) {
+ Object generated = generate(type);
+ if (generated != null) {
+ freshness.incrementAndGet();
+ }
+ return generated;
+ }
+
+ @Nullable final <T> T generateFresh(Class<T> type) {
+ return Primitives.wrap(type).cast(generateFresh(TypeToken.of(type)));
+ }
+
+ final <T> T newFreshProxy(final Class<T> interfaceType) {
+ T proxy = newProxy(interfaceType);
+ freshness.incrementAndGet();
+ return proxy;
+ }
+
+ /**
+ * Generates an instance for {@code type} using the current {@link #freshness}.
+ * The generated instance may or may not be unique across different calls.
+ */
+ private Object generate(TypeToken<?> type) {
Class<?> rawType = type.getRawType();
List<Object> samples = sampleInstances.get(rawType);
- Object sample = nextInstance(samples, null);
+ Object sample = pickInstance(samples, null);
if (sample != null) {
return sample;
}
if (rawType.isEnum()) {
- return nextInstance(rawType.getEnumConstants(), null);
+ return pickInstance(rawType.getEnumConstants(), null);
}
if (type.isArray()) {
TypeToken<?> componentType = type.getComponentType();
@@ -174,20 +213,32 @@ class FreshValueGenerator {
Array.set(array, 0, generate(componentType));
return array;
}
- if (rawType == Optional.class && generatedOptionalTypes.add(type.getType())) {
- // For any Optional<T>, we'll first generate absent(). The next call generates a distinct
- // value of T to be wrapped in Optional.of().
- return Optional.absent();
+ Method emptyGenerate = EMPTY_GENERATORS.get(rawType);
+ if (emptyGenerate != null) {
+ if (emptyInstanceGenerated.containsKey(type.getType())) {
+ // empty instance already generated
+ if (emptyInstanceGenerated.get(type.getType()).intValue() == freshness.get()) {
+ // same freshness, generate again.
+ return invokeGeneratorMethod(emptyGenerate);
+ } else {
+ // Cannot use empty generator. Proceed with other generators.
+ }
+ } else {
+ // never generated empty instance for this type before.
+ Object emptyInstance = invokeGeneratorMethod(emptyGenerate);
+ emptyInstanceGenerated.put(type.getType(), freshness.get());
+ return emptyInstance;
+ }
}
- Method generator = GENERATORS.get(rawType);
- if (generator != null) {
- ImmutableList<Parameter> params = Invokable.from(generator).getParameters();
+ Method generate = GENERATORS.get(rawType);
+ if (generate != null) {
+ ImmutableList<Parameter> params = Invokable.from(generate).getParameters();
List<Object> args = Lists.newArrayListWithCapacity(params.size());
TypeVariable<?>[] typeVars = rawType.getTypeParameters();
for (int i = 0; i < params.size(); i++) {
TypeToken<?> paramType = type.resolveType(typeVars[i]);
// We require all @Generates methods to either be parameter-less or accept non-null
- // fresh values for their generic parameter types.
+ // values for their generic parameter types.
Object argValue = generate(paramType);
if (argValue == null) {
// When a parameter of a @Generates method cannot be created,
@@ -198,21 +249,11 @@ class FreshValueGenerator {
}
args.add(argValue);
}
- try {
- return generator.invoke(this, args.toArray());
- } catch (InvocationTargetException e) {
- Throwables.propagate(e.getCause());
- } catch (Exception e) {
- throw Throwables.propagate(e);
- }
+ return invokeGeneratorMethod(generate, args.toArray());
}
return defaultGenerate(rawType);
}
- @Nullable final <T> T generate(Class<T> type) {
- return Primitives.wrap(type).cast(generate(TypeToken.of(type)));
- }
-
private <T> T defaultGenerate(Class<T> rawType) {
if (rawType.isInterface()) {
// always create a new proxy
@@ -221,12 +262,22 @@ class FreshValueGenerator {
return ArbitraryInstances.get(rawType);
}
- final <T> T newProxy(final Class<T> interfaceType) {
+ private <T> T newProxy(final Class<T> interfaceType) {
return Reflection.newProxy(interfaceType, new FreshInvocationHandler(interfaceType));
}
+ private Object invokeGeneratorMethod(Method generator, Object... args) {
+ try {
+ return generator.invoke(this, args);
+ } catch (InvocationTargetException e) {
+ throw Throwables.propagate(e.getCause());
+ } catch (Exception e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
private final class FreshInvocationHandler extends AbstractInvocationHandler {
- private final int identity = freshInt();
+ private final int identity = generateInt();
private final Class<?> interfaceType;
FreshInvocationHandler(Class<?> interfaceType) {
@@ -255,22 +306,20 @@ class FreshValueGenerator {
}
/** Subclasses can override to provide different return value for proxied interface methods. */
- Object interfaceMethodCalled(
- @SuppressWarnings("unused") Class<?> interfaceType,
- @SuppressWarnings("unused") Method method) {
+ Object interfaceMethodCalled(Class<?> interfaceType, Method method) {
throw new UnsupportedOperationException();
}
- private <T> T nextInstance(T[] instances, T defaultValue) {
- return nextInstance(Arrays.asList(instances), defaultValue);
+ private <T> T pickInstance(T[] instances, T defaultValue) {
+ return pickInstance(Arrays.asList(instances), defaultValue);
}
- private <T> T nextInstance(Collection<T> instances, T defaultValue) {
+ private <T> T pickInstance(Collection<T> instances, T defaultValue) {
if (instances.isEmpty()) {
return defaultValue;
}
- // freshInt() is 1-based.
- return Iterables.get(instances, (freshInt() - 1) % instances.size());
+ // generateInt() is 1-based.
+ return Iterables.get(instances, (generateInt() - 1) % instances.size());
}
private static String paramString(Class<?> type, int i) {
@@ -279,136 +328,161 @@ class FreshValueGenerator {
/**
* Annotates a method to be the instance generator of a certain type. The return type is the
- * generated type. The method parameters are non-null fresh values for each method type variable
- * in the same type variable declaration order of the return type.
+ * generated type. The method parameters correspond to the generated type's type parameters.
+ * For example, if the annotated method returns {@code Map<K, V>}, the method signature should be:
+ * {@code Map<K, V> generateMap(K key, V value)}.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
private @interface Generates {}
- @Generates private Class<?> freshClass() {
- return nextInstance(
+ /**
+ * Annotates a method to generate the "empty" instance of a collection. This method should accept
+ * no parameter. The value it generates should be unequal to the values generated by methods
+ * annotated with {@link Generates}.
+ */
+ @Target(ElementType.METHOD)
+ @Retention(RetentionPolicy.RUNTIME)
+ private @interface Empty {}
+
+ @Generates private Class<?> generateClass() {
+ return pickInstance(
ImmutableList.of(
int.class, long.class, void.class,
Object.class, Object[].class, Iterable.class),
Object.class);
}
- @Generates private Object freshObject() {
- return freshString();
+ @Generates private Object generateObject() {
+ return generateString();
}
- @Generates private Number freshNumber() {
- return freshInt();
+ @Generates private Number generateNumber() {
+ return generateInt();
}
- @Generates private int freshInt() {
- return differentiator.getAndIncrement();
+ @Generates private int generateInt() {
+ return freshness.get();
}
- @Generates private Integer freshInteger() {
- return new Integer(freshInt());
+ @Generates private Integer generateInteger() {
+ return new Integer(generateInt());
}
- @Generates private long freshLong() {
- return freshInt();
+ @Generates private long generateLong() {
+ return generateInt();
}
- @Generates private Long freshLongObject() {
- return new Long(freshLong());
+ @Generates private Long generateLongObject() {
+ return new Long(generateLong());
}
- @Generates private float freshFloat() {
- return freshInt();
+ @Generates private float generateFloat() {
+ return generateInt();
}
- @Generates private Float freshFloatObject() {
- return new Float(freshFloat());
+ @Generates private Float generateFloatObject() {
+ return new Float(generateFloat());
}
- @Generates private double freshDouble() {
- return freshInt();
+ @Generates private double generateDouble() {
+ return generateInt();
}
- @Generates private Double freshDoubleObject() {
- return new Double(freshDouble());
+ @Generates private Double generateDoubleObject() {
+ return new Double(generateDouble());
}
- @Generates private short freshShort() {
- return (short) freshInt();
+ @Generates private short generateShort() {
+ return (short) generateInt();
}
- @Generates private Short freshShortObject() {
- return new Short(freshShort());
+ @Generates private Short generateShortObject() {
+ return new Short(generateShort());
}
- @Generates private byte freshByte() {
- return (byte) freshInt();
+ @Generates private byte generateByte() {
+ return (byte) generateInt();
}
- @Generates private Byte freshByteObject() {
- return new Byte(freshByte());
+ @Generates private Byte generateByteObject() {
+ return new Byte(generateByte());
}
- @Generates private char freshChar() {
- return freshString().charAt(0);
+ @Generates private char generateChar() {
+ return generateString().charAt(0);
}
- @Generates private Character freshCharacter() {
- return new Character(freshChar());
+ @Generates private Character generateCharacter() {
+ return new Character(generateChar());
}
- @Generates private boolean freshBoolean() {
- return freshInt() % 2 == 0;
+ @Generates private boolean generateBoolean() {
+ return generateInt() % 2 == 0;
}
- @Generates private Boolean freshBooleanObject() {
- return new Boolean(freshBoolean());
+ @Generates private Boolean generateBooleanObject() {
+ return new Boolean(generateBoolean());
}
- @Generates private UnsignedInteger freshUnsignedInteger() {
- return UnsignedInteger.fromIntBits(freshInt());
+ @Generates private UnsignedInteger generateUnsignedInteger() {
+ return UnsignedInteger.fromIntBits(generateInt());
}
- @Generates private UnsignedLong freshUnsignedLong() {
- return UnsignedLong.fromLongBits(freshLong());
+ @Generates private UnsignedLong generateUnsignedLong() {
+ return UnsignedLong.fromLongBits(generateLong());
}
- @Generates private BigInteger freshBigInteger() {
- return BigInteger.valueOf(freshInt());
+ @Generates private BigInteger generateBigInteger() {
+ return BigInteger.valueOf(generateInt());
}
- @Generates private BigDecimal freshBigDecimal() {
- return BigDecimal.valueOf(freshInt());
+ @Generates private BigDecimal generateBigDecimal() {
+ return BigDecimal.valueOf(generateInt());
}
- @Generates private CharSequence freshCharSequence() {
- return freshString();
+ @Generates private CharSequence generateCharSequence() {
+ return generateString();
}
- @Generates private String freshString() {
- return Integer.toString(freshInt());
+ @Generates private String generateString() {
+ return Integer.toString(generateInt());
}
- @Generates private Comparable<?> freshComparable() {
- return freshString();
+ @Generates private Comparable<?> generateComparable() {
+ return generateString();
}
- @Generates private Pattern freshPattern() {
- return Pattern.compile(freshString());
+ @Generates private Pattern generatePattern() {
+ return Pattern.compile(generateString());
}
- @Generates private Charset freshCharset() {
- return nextInstance(Charset.availableCharsets().values(), Charsets.UTF_8);
+ @Generates private Charset generateCharset() {
+ return pickInstance(Charset.availableCharsets().values(), Charsets.UTF_8);
}
- @Generates private Locale freshLocale() {
- return nextInstance(Locale.getAvailableLocales(), Locale.US);
+ @Generates private Locale generateLocale() {
+ return pickInstance(Locale.getAvailableLocales(), Locale.US);
}
- @Generates private Currency freshCurrency() {
+ @Generates private Currency generateCurrency() {
+ try {
+ Method method = Currency.class.getMethod("getAvailableCurrencies");
+ @SuppressWarnings("unchecked") // getAvailableCurrencies() returns Set<Currency>.
+ Set<Currency> currencies = (Set<Currency>) method.invoke(null);
+ return pickInstance(currencies, Currency.getInstance(Locale.US));
+ } catch (NoSuchMethodException notJava7) {
+ return preJava7FreshCurrency();
+ } catch (InvocationTargetException cantCallGetAvailableCurrencies) {
+ return preJava7FreshCurrency();
+ } catch (IllegalAccessException impossible) {
+ throw new AssertionError(impossible);
+ }
+ }
+
+ private Currency preJava7FreshCurrency() {
for (Set<Locale> uselessLocales = Sets.newHashSet(); ; ) {
- Locale locale = freshLocale();
+ Locale locale = generateLocale();
if (uselessLocales.contains(locale)) { // exhausted all locales
return Currency.getInstance(Locale.US);
}
@@ -421,19 +495,23 @@ class FreshValueGenerator {
}
// common.base
- @Generates private <T> Optional<T> freshOptional(T value) {
+ @Empty private <T> Optional<T> generateOptional() {
+ return Optional.absent();
+ }
+
+ @Generates private <T> Optional<T> generateOptional(T value) {
return Optional.of(value);
}
- @Generates private Joiner freshJoiner() {
- return Joiner.on(freshString());
+ @Generates private Joiner generateJoiner() {
+ return Joiner.on(generateString());
}
- @Generates private Splitter freshSplitter() {
- return Splitter.on(freshString());
+ @Generates private Splitter generateSplitter() {
+ return Splitter.on(generateString());
}
- @Generates private <T> Equivalence<T> freshEquivalence() {
+ @Generates private <T> Equivalence<T> generateEquivalence() {
return new Equivalence<T>() {
@Override protected boolean doEquivalent(T a, T b) {
return false;
@@ -441,31 +519,31 @@ class FreshValueGenerator {
@Override protected int doHash(T t) {
return 0;
}
- final String string = paramString(Equivalence.class, freshInt());
+ final String string = paramString(Equivalence.class, generateInt());
@Override public String toString() {
return string;
}
};
}
- @Generates private CharMatcher freshCharMatcher() {
+ @Generates private CharMatcher generateCharMatcher() {
return new CharMatcher() {
@Override public boolean matches(char c) {
return false;
}
- final String string = paramString(CharMatcher.class, freshInt());
+ final String string = paramString(CharMatcher.class, generateInt());
@Override public String toString() {
return string;
}
};
}
- @Generates private Ticker freshTicker() {
+ @Generates private Ticker generateTicker() {
return new Ticker() {
@Override public long read() {
return 0;
}
- final String string = paramString(Ticker.class, freshInt());
+ final String string = paramString(Ticker.class, generateInt());
@Override public String toString() {
return string;
}
@@ -473,87 +551,91 @@ class FreshValueGenerator {
}
// collect
- @Generates private <T> Comparator<T> freshComparator() {
- return freshOrdering();
+ @Generates private <T> Comparator<T> generateComparator() {
+ return generateOrdering();
}
- @Generates private <T> Ordering<T> freshOrdering() {
+ @Generates private <T> Ordering<T> generateOrdering() {
return new Ordering<T>() {
@Override public int compare(T left, T right) {
return 0;
}
- final String string = paramString(Ordering.class, freshInt());
+ final String string = paramString(Ordering.class, generateInt());
@Override public String toString() {
return string;
}
};
}
- @Generates private static <C extends Comparable> Range<C> freshRange(C freshElement) {
+ @Empty private static <C extends Comparable<?>> Range<C> generateRange() {
+ return Range.all();
+ }
+
+ @Generates private static <C extends Comparable<?>> Range<C> generateRange(C freshElement) {
return Range.singleton(freshElement);
}
- @Generates private static <E> Iterable<E> freshIterable(E freshElement) {
- return freshList(freshElement);
+ @Generates private static <E> Iterable<E> generateIterable(E freshElement) {
+ return generateList(freshElement);
}
- @Generates private static <E> Collection<E> freshCollection(E freshElement) {
- return freshList(freshElement);
+ @Generates private static <E> Collection<E> generateCollection(E freshElement) {
+ return generateList(freshElement);
}
- @Generates private static <E> List<E> freshList(E freshElement) {
- return freshArrayList(freshElement);
+ @Generates private static <E> List<E> generateList(E freshElement) {
+ return generateArrayList(freshElement);
}
- @Generates private static <E> ArrayList<E> freshArrayList(E freshElement) {
+ @Generates private static <E> ArrayList<E> generateArrayList(E freshElement) {
ArrayList<E> list = Lists.newArrayList();
list.add(freshElement);
return list;
}
- @Generates private static <E> LinkedList<E> freshLinkedList(E freshElement) {
+ @Generates private static <E> LinkedList<E> generateLinkedList(E freshElement) {
LinkedList<E> list = Lists.newLinkedList();
list.add(freshElement);
return list;
}
- @Generates private static <E> ImmutableList<E> freshImmutableList(E freshElement) {
+ @Generates private static <E> ImmutableList<E> generateImmutableList(E freshElement) {
return ImmutableList.of(freshElement);
}
- @Generates private static <E> ImmutableCollection<E> freshImmutableCollection(E freshElement) {
- return freshImmutableList(freshElement);
+ @Generates private static <E> ImmutableCollection<E> generateImmutableCollection(E freshElement) {
+ return generateImmutableList(freshElement);
}
- @Generates private static <E> Set<E> freshSet(E freshElement) {
- return freshHashSet(freshElement);
+ @Generates private static <E> Set<E> generateSet(E freshElement) {
+ return generateHashSet(freshElement);
}
- @Generates private static <E> HashSet<E> freshHashSet(E freshElement) {
- return freshLinkedHashSet(freshElement);
+ @Generates private static <E> HashSet<E> generateHashSet(E freshElement) {
+ return generateLinkedHashSet(freshElement);
}
- @Generates private static <E> LinkedHashSet<E> freshLinkedHashSet(E freshElement) {
+ @Generates private static <E> LinkedHashSet<E> generateLinkedHashSet(E freshElement) {
LinkedHashSet<E> set = Sets.newLinkedHashSet();
set.add(freshElement);
return set;
}
- @Generates private static <E> ImmutableSet<E> freshImmutableSet(E freshElement) {
+ @Generates private static <E> ImmutableSet<E> generateImmutableSet(E freshElement) {
return ImmutableSet.of(freshElement);
}
@Generates private static <E extends Comparable<? super E>> SortedSet<E>
- freshSortedSet(E freshElement) {
- return freshNavigableSet(freshElement);
+ generateSortedSet(E freshElement) {
+ return generateNavigableSet(freshElement);
}
@Generates private static <E extends Comparable<? super E>> NavigableSet<E>
- freshNavigableSet(E freshElement) {
- return freshTreeSet(freshElement);
+ generateNavigableSet(E freshElement) {
+ return generateTreeSet(freshElement);
}
- @Generates private static <E extends Comparable<? super E>> TreeSet<E> freshTreeSet(
+ @Generates private static <E extends Comparable<? super E>> TreeSet<E> generateTreeSet(
E freshElement) {
TreeSet<E> set = Sets.newTreeSet();
set.add(freshElement);
@@ -561,36 +643,36 @@ class FreshValueGenerator {
}
@Generates private static <E extends Comparable<? super E>> ImmutableSortedSet<E>
- freshImmutableSortedSet(E freshElement) {
+ generateImmutableSortedSet(E freshElement) {
return ImmutableSortedSet.of(freshElement);
}
- @Generates private static <E> Multiset<E> freshMultiset(E freshElement) {
- return freshHashMultiset(freshElement);
+ @Generates private static <E> Multiset<E> generateMultiset(E freshElement) {
+ return generateHashMultiset(freshElement);
}
- @Generates private static <E> HashMultiset<E> freshHashMultiset(E freshElement) {
+ @Generates private static <E> HashMultiset<E> generateHashMultiset(E freshElement) {
HashMultiset<E> multiset = HashMultiset.create();
multiset.add(freshElement);
return multiset;
}
- @Generates private static <E> LinkedHashMultiset<E> freshLinkedHashMultiset(E freshElement) {
+ @Generates private static <E> LinkedHashMultiset<E> generateLinkedHashMultiset(E freshElement) {
LinkedHashMultiset<E> multiset = LinkedHashMultiset.create();
multiset.add(freshElement);
return multiset;
}
- @Generates private static <E> ImmutableMultiset<E> freshImmutableMultiset(E freshElement) {
+ @Generates private static <E> ImmutableMultiset<E> generateImmutableMultiset(E freshElement) {
return ImmutableMultiset.of(freshElement);
}
- @Generates private static <E extends Comparable<E>> SortedMultiset<E> freshSortedMultiset(
+ @Generates private static <E extends Comparable<E>> SortedMultiset<E> generateSortedMultiset(
E freshElement) {
- return freshTreeMultiset(freshElement);
+ return generateTreeMultiset(freshElement);
}
- @Generates private static <E extends Comparable<E>> TreeMultiset<E> freshTreeMultiset(
+ @Generates private static <E extends Comparable<E>> TreeMultiset<E> generateTreeMultiset(
E freshElement) {
TreeMultiset<E> multiset = TreeMultiset.create();
multiset.add(freshElement);
@@ -598,45 +680,49 @@ class FreshValueGenerator {
}
@Generates private static <E extends Comparable<E>> ImmutableSortedMultiset<E>
- freshImmutableSortedMultiset(E freshElement) {
+ generateImmutableSortedMultiset(E freshElement) {
return ImmutableSortedMultiset.of(freshElement);
}
- @Generates private static <K, V> Map<K, V> freshMap(K key, V value) {
- return freshHashdMap(key, value);
+ @Generates private static <K, V> Map<K, V> generateMap(K key, V value) {
+ return generateHashdMap(key, value);
}
- @Generates private static <K, V> HashMap<K, V> freshHashdMap(K key, V value) {
- return freshLinkedHashMap(key, value);
+ @Generates private static <K, V> HashMap<K, V> generateHashdMap(K key, V value) {
+ return generateLinkedHashMap(key, value);
}
- @Generates private static <K, V> LinkedHashMap<K, V> freshLinkedHashMap(K key, V value) {
+ @Generates private static <K, V> LinkedHashMap<K, V> generateLinkedHashMap(K key, V value) {
LinkedHashMap<K, V> map = Maps.newLinkedHashMap();
map.put(key, value);
return map;
}
- @Generates private static <K, V> ImmutableMap<K, V> freshImmutableMap(K key, V value) {
+ @Generates private static <K, V> ImmutableMap<K, V> generateImmutableMap(K key, V value) {
return ImmutableMap.of(key, value);
}
- @Generates private static <K, V> ConcurrentMap<K, V> freshConcurrentMap(K key, V value) {
+ @Empty private static <K, V> ConcurrentMap<K, V> generateConcurrentMap() {
+ return Maps.newConcurrentMap();
+ }
+
+ @Generates private static <K, V> ConcurrentMap<K, V> generateConcurrentMap(K key, V value) {
ConcurrentMap<K, V> map = Maps.newConcurrentMap();
map.put(key, value);
return map;
}
@Generates private static <K extends Comparable<? super K>, V> SortedMap<K, V>
- freshSortedMap(K key, V value) {
- return freshNavigableMap(key, value);
+ generateSortedMap(K key, V value) {
+ return generateNavigableMap(key, value);
}
@Generates private static <K extends Comparable<? super K>, V> NavigableMap<K, V>
- freshNavigableMap(K key, V value) {
- return freshTreeMap(key, value);
+ generateNavigableMap(K key, V value) {
+ return generateTreeMap(key, value);
}
- @Generates private static <K extends Comparable<? super K>, V> TreeMap<K, V> freshTreeMap(
+ @Generates private static <K extends Comparable<? super K>, V> TreeMap<K, V> generateTreeMap(
K key, V value) {
TreeMap<K, V> map = Maps.newTreeMap();
map.put(key, value);
@@ -644,75 +730,77 @@ class FreshValueGenerator {
}
@Generates private static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
- freshImmutableSortedMap(K key, V value) {
+ generateImmutableSortedMap(K key, V value) {
return ImmutableSortedMap.of(key, value);
}
- @Generates private static <K, V> Multimap<K, V> freshMultimap(K key, V value) {
- return freshListMultimap(key, value);
+ @Generates private static <K, V> Multimap<K, V> generateMultimap(K key, V value) {
+ return generateListMultimap(key, value);
}
- @Generates private static <K, V> ImmutableMultimap<K, V> freshImmutableMultimap(K key, V value) {
+ @Generates private static <K, V> ImmutableMultimap<K, V> generateImmutableMultimap(
+ K key, V value) {
return ImmutableMultimap.of(key, value);
}
- @Generates private static <K, V> ListMultimap<K, V> freshListMultimap(K key, V value) {
- return freshArrayListMultimap(key, value);
+ @Generates private static <K, V> ListMultimap<K, V> generateListMultimap(K key, V value) {
+ return generateArrayListMultimap(key, value);
}
- @Generates private static <K, V> ArrayListMultimap<K, V> freshArrayListMultimap(K key, V value) {
+ @Generates private static <K, V> ArrayListMultimap<K, V> generateArrayListMultimap(
+ K key, V value) {
ArrayListMultimap<K, V> multimap = ArrayListMultimap.create();
multimap.put(key, value);
return multimap;
}
- @Generates private static <K, V> ImmutableListMultimap<K, V> freshImmutableListMultimap(
+ @Generates private static <K, V> ImmutableListMultimap<K, V> generateImmutableListMultimap(
K key, V value) {
return ImmutableListMultimap.of(key, value);
}
- @Generates private static <K, V> SetMultimap<K, V> freshSetMultimap(K key, V value) {
- return freshLinkedHashMultimap(key, value);
+ @Generates private static <K, V> SetMultimap<K, V> generateSetMultimap(K key, V value) {
+ return generateLinkedHashMultimap(key, value);
}
- @Generates private static <K, V> HashMultimap<K, V> freshHashMultimap(K key, V value) {
+ @Generates private static <K, V> HashMultimap<K, V> generateHashMultimap(K key, V value) {
HashMultimap<K, V> multimap = HashMultimap.create();
multimap.put(key, value);
return multimap;
}
- @Generates private static <K, V> LinkedHashMultimap<K, V> freshLinkedHashMultimap(
+ @Generates private static <K, V> LinkedHashMultimap<K, V> generateLinkedHashMultimap(
K key, V value) {
LinkedHashMultimap<K, V> multimap = LinkedHashMultimap.create();
multimap.put(key, value);
return multimap;
}
- @Generates private static <K, V> ImmutableSetMultimap<K, V> freshImmutableSetMultimap(
+ @Generates private static <K, V> ImmutableSetMultimap<K, V> generateImmutableSetMultimap(
K key, V value) {
return ImmutableSetMultimap.of(key, value);
}
- @Generates private static <K, V> BiMap<K, V> freshBimap(K key, V value) {
- return freshHashBiMap(key, value);
+ @Generates private static <K, V> BiMap<K, V> generateBimap(K key, V value) {
+ return generateHashBiMap(key, value);
}
- @Generates private static <K, V> HashBiMap<K, V> freshHashBiMap(K key, V value) {
+ @Generates private static <K, V> HashBiMap<K, V> generateHashBiMap(K key, V value) {
HashBiMap<K, V> bimap = HashBiMap.create();
bimap.put(key, value);
return bimap;
}
- @Generates private static <K, V> ImmutableBiMap<K, V> freshImmutableBimap(
+ @Generates private static <K, V> ImmutableBiMap<K, V> generateImmutableBimap(
K key, V value) {
return ImmutableBiMap.of(key, value);
}
- @Generates private static <R, C, V> Table<R, C, V> freshTable(R row, C column, V value) {
- return freshHashBasedTable(row, column, value);
+ @Generates private static <R, C, V> Table<R, C, V> generateTable(R row, C column, V value) {
+ return generateHashBasedTable(row, column, value);
}
- @Generates private static <R, C, V> HashBasedTable<R, C, V> freshHashBasedTable(
+ @Generates private static <R, C, V> HashBasedTable<R, C, V> generateHashBasedTable(
R row, C column, V value) {
HashBasedTable<R, C, V> table = HashBasedTable.create();
table.put(row, column, value);
@@ -721,82 +809,82 @@ class FreshValueGenerator {
@SuppressWarnings("rawtypes") // TreeBasedTable.create() is defined as such
@Generates private static <R extends Comparable, C extends Comparable, V> RowSortedTable<R, C, V>
- freshRowSortedTable(R row, C column, V value) {
- return freshTreeBasedTable(row, column, value);
+ generateRowSortedTable(R row, C column, V value) {
+ return generateTreeBasedTable(row, column, value);
}
@SuppressWarnings("rawtypes") // TreeBasedTable.create() is defined as such
@Generates private static <R extends Comparable, C extends Comparable, V> TreeBasedTable<R, C, V>
- freshTreeBasedTable(R row, C column, V value) {
+ generateTreeBasedTable(R row, C column, V value) {
TreeBasedTable<R, C, V> table = TreeBasedTable.create();
table.put(row, column, value);
return table;
}
- @Generates private static <R, C, V> ImmutableTable<R, C, V> freshImmutableTable(
+ @Generates private static <R, C, V> ImmutableTable<R, C, V> generateImmutableTable(
R row, C column, V value) {
return ImmutableTable.of(row, column, value);
}
// common.reflect
- @Generates private TypeToken<?> freshTypeToken() {
- return TypeToken.of(freshClass());
+ @Generates private TypeToken<?> generateTypeToken() {
+ return TypeToken.of(generateClass());
}
// io types
- @Generates private File freshFile() {
- return new File(freshString());
+ @Generates private File generateFile() {
+ return new File(generateString());
}
- @Generates private static ByteArrayInputStream freshByteArrayInputStream() {
+ @Generates private static ByteArrayInputStream generateByteArrayInputStream() {
return new ByteArrayInputStream(new byte[0]);
}
- @Generates private static InputStream freshInputStream() {
- return freshByteArrayInputStream();
+ @Generates private static InputStream generateInputStream() {
+ return generateByteArrayInputStream();
}
- @Generates private StringReader freshStringReader() {
- return new StringReader(freshString());
+ @Generates private StringReader generateStringReader() {
+ return new StringReader(generateString());
}
- @Generates private Reader freshReader() {
- return freshStringReader();
+ @Generates private Reader generateReader() {
+ return generateStringReader();
}
- @Generates private Readable freshReadable() {
- return freshReader();
+ @Generates private Readable generateReadable() {
+ return generateReader();
}
- @Generates private Buffer freshBuffer() {
- return freshCharBuffer();
+ @Generates private Buffer generateBuffer() {
+ return generateCharBuffer();
}
- @Generates private CharBuffer freshCharBuffer() {
- return CharBuffer.allocate(freshInt());
+ @Generates private CharBuffer generateCharBuffer() {
+ return CharBuffer.allocate(generateInt());
}
- @Generates private ByteBuffer freshByteBuffer() {
- return ByteBuffer.allocate(freshInt());
+ @Generates private ByteBuffer generateByteBuffer() {
+ return ByteBuffer.allocate(generateInt());
}
- @Generates private ShortBuffer freshShortBuffer() {
- return ShortBuffer.allocate(freshInt());
+ @Generates private ShortBuffer generateShortBuffer() {
+ return ShortBuffer.allocate(generateInt());
}
- @Generates private IntBuffer freshIntBuffer() {
- return IntBuffer.allocate(freshInt());
+ @Generates private IntBuffer generateIntBuffer() {
+ return IntBuffer.allocate(generateInt());
}
- @Generates private LongBuffer freshLongBuffer() {
- return LongBuffer.allocate(freshInt());
+ @Generates private LongBuffer generateLongBuffer() {
+ return LongBuffer.allocate(generateInt());
}
- @Generates private FloatBuffer freshFloatBuffer() {
- return FloatBuffer.allocate(freshInt());
+ @Generates private FloatBuffer generateFloatBuffer() {
+ return FloatBuffer.allocate(generateInt());
}
- @Generates private DoubleBuffer freshDoubleBuffer() {
- return DoubleBuffer.allocate(freshInt());
+ @Generates private DoubleBuffer generateDoubleBuffer() {
+ return DoubleBuffer.allocate(generateInt());
}
}
diff --git a/guava-testlib/src/com/google/common/testing/GcFinalization.java b/guava-testlib/src/com/google/common/testing/GcFinalization.java
index f1371b5..7041450 100644
--- a/guava-testlib/src/com/google/common/testing/GcFinalization.java
+++ b/guava-testlib/src/com/google/common/testing/GcFinalization.java
@@ -19,8 +19,10 @@ package com.google.common.testing;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.annotations.Beta;
+import com.google.j2objc.annotations.J2ObjCIncompatible;
import java.lang.ref.WeakReference;
+import java.util.Locale;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
@@ -99,6 +101,7 @@ import java.util.concurrent.TimeoutException;
* @since 11.0
*/
@Beta
+ at J2ObjCIncompatible // gc
public final class GcFinalization {
private GcFinalization() {}
@@ -152,8 +155,7 @@ public final class GcFinalization {
/* OK */
}
} while (System.nanoTime() - deadline < 0);
- throw new RuntimeException(
- String.format("Future not done within %d second timeout", timeoutSeconds));
+ throw formatRuntimeException("Future not done within %d second timeout", timeoutSeconds);
}
/**
@@ -182,8 +184,8 @@ public final class GcFinalization {
throw new RuntimeException("Unexpected interrupt while waiting for latch", ie);
}
} while (System.nanoTime() - deadline < 0);
- throw new RuntimeException(
- String.format("Latch failed to count down within %d second timeout", timeoutSeconds));
+ throw formatRuntimeException(
+ "Latch failed to count down within %d second timeout", timeoutSeconds);
}
/**
@@ -233,8 +235,8 @@ public final class GcFinalization {
return;
}
} while (System.nanoTime() - deadline < 0);
- throw new RuntimeException(
- String.format("Predicate did not become true within %d second timeout", timeoutSeconds));
+ throw formatRuntimeException(
+ "Predicate did not become true within %d second timeout", timeoutSeconds);
}
/**
@@ -294,4 +296,8 @@ public final class GcFinalization {
// Hope to catch some stragglers queued up behind our finalizable object
System.runFinalization();
}
+
+ private static RuntimeException formatRuntimeException(String format, Object... args) {
+ return new RuntimeException(String.format(Locale.ROOT, format, args));
+ }
}
diff --git a/guava-testlib/src/com/google/common/testing/NullPointerTester.java b/guava-testlib/src/com/google/common/testing/NullPointerTester.java
index 209b949..190d0d0 100644
--- a/guava-testlib/src/com/google/common/testing/NullPointerTester.java
+++ b/guava-testlib/src/com/google/common/testing/NullPointerTester.java
@@ -291,7 +291,6 @@ public final class NullPointerTester {
}
}
- // TODO(benyu): Use labs/reflect/Signature if it graduates.
private static final class Signature {
private final String name;
private final ImmutableList<Class<?>> parameterTypes;
diff --git a/guava-testlib/src/com/google/common/testing/TestLogHandler.java b/guava-testlib/src/com/google/common/testing/TestLogHandler.java
index cb5bcbd..6ef3018 100644
--- a/guava-testlib/src/com/google/common/testing/TestLogHandler.java
+++ b/guava-testlib/src/com/google/common/testing/TestLogHandler.java
@@ -17,6 +17,7 @@
package com.google.common.testing;
import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
import java.util.ArrayList;
import java.util.Collections;
@@ -54,16 +55,16 @@ import javax.annotation.Nullable;
* @since 10.0
*/
@Beta
+ at GwtCompatible
public class TestLogHandler extends Handler {
/** We will keep a private list of all logged records */
- private final List<LogRecord> list =
- Collections.synchronizedList(new ArrayList<LogRecord>());
+ private final List<LogRecord> list = new ArrayList<LogRecord>();
/**
* Adds the most recently logged record to our list.
*/
@Override
- public void publish(@Nullable LogRecord record) {
+ public synchronized void publish(@Nullable LogRecord record) {
list.add(record);
}
@@ -73,15 +74,21 @@ public class TestLogHandler extends Handler {
@Override
public void close() {}
- public void clear() {
+ public synchronized void clear() {
list.clear();
}
/**
- * Fetch the list of logged records
- * @return unmodifiable LogRecord list of all logged records
+ * Returns a snapshot of the logged records.
*/
- public List<LogRecord> getStoredLogRecords() {
+ /*
+ * TODO(cpovirk): consider higher-level APIs here (say, assertNoRecordsLogged(),
+ * getOnlyRecordLogged(), getAndClearLogRecords()...)
+ *
+ * TODO(cpovirk): consider renaming this method to reflect that it takes a snapshot (and/or return
+ * an ImmutableList)
+ */
+ public synchronized List<LogRecord> getStoredLogRecords() {
List<LogRecord> result = new ArrayList<LogRecord>(list);
return Collections.unmodifiableList(result);
}
diff --git a/guava-testlib/test/com/google/common/collect/testing/HelpersTest.java b/guava-testlib/test/com/google/common/collect/testing/HelpersTest.java
index 68b9cfa..682ef97 100644
--- a/guava-testlib/test/com/google/common/collect/testing/HelpersTest.java
+++ b/guava-testlib/test/com/google/common/collect/testing/HelpersTest.java
@@ -23,6 +23,12 @@ import com.google.common.annotations.GwtCompatible;
import junit.framework.TestCase;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* Unit test for {@link Helpers}.
*
@@ -33,4 +39,127 @@ public class HelpersTest extends TestCase {
public void testNullsBeforeB() {
testComparator(NullsBeforeB.INSTANCE, "a", "azzzzzz", null, "b", "c");
}
+
+ public void testIsEmpty_iterable() {
+ List<Object> list = new ArrayList<Object>();
+ Helpers.assertEmpty(list);
+
+ list.add("a");
+ try {
+ Helpers.assertEmpty(list);
+ fail();
+ } catch (AssertionError expected) {
+ }
+ }
+
+ public void testIsEmpty_map() {
+ Map<Object, Object> map = new HashMap<Object, Object>();
+ Helpers.assertEmpty(map);
+
+ map.put("a", "b");
+ try {
+ Helpers.assertEmpty(map);
+ fail();
+ } catch (AssertionError expected) {
+ }
+ }
+
+ public void testAssertEqualInOrder() {
+ List<?> list = Arrays.asList("a", "b", "c");
+ Helpers.assertEqualInOrder(list, list);
+
+ List<?> fewer = Arrays.asList("a", "b");
+ try {
+ Helpers.assertEqualInOrder(list, fewer);
+ fail();
+ } catch (AssertionError expected) {
+ }
+
+ try {
+ Helpers.assertEqualInOrder(fewer, list);
+ fail();
+ } catch (AssertionError expected) {
+ }
+
+ List<?> differentOrder = Arrays.asList("a", "c", "b");
+ try {
+ Helpers.assertEqualInOrder(list, differentOrder);
+ fail();
+ } catch (AssertionError expected) {
+ }
+
+ List<?> differentContents = Arrays.asList("a", "b", "C");
+ try {
+ Helpers.assertEqualInOrder(list, differentContents);
+ fail();
+ } catch (AssertionError expected) {
+ }
+ }
+
+ public void testAssertContentsInOrder() {
+ List<?> list = Arrays.asList("a", "b", "c");
+ Helpers.assertContentsInOrder(list, "a", "b", "c");
+
+ try {
+ Helpers.assertContentsInOrder(list, "a", "b");
+ fail();
+ } catch (AssertionError expected) {
+ }
+
+ try {
+ Helpers.assertContentsInOrder(list, "a", "b", "c", "d");
+ fail();
+ } catch (AssertionError expected) {
+ }
+
+ try {
+ Helpers.assertContentsInOrder(list, "a", "c", "b");
+ fail();
+ } catch (AssertionError expected) {
+ }
+
+ try {
+ Helpers.assertContentsInOrder(list, "a", "B", "c");
+ fail();
+ } catch (AssertionError expected) {
+ }
+ }
+
+ public void testAssertContains() {
+ List<?> list = Arrays.asList("a", "b");
+ Helpers.assertContains(list, "a");
+ Helpers.assertContains(list, "b");
+
+ try {
+ Helpers.assertContains(list, "c");
+ fail();
+ } catch (AssertionError expected) {
+ }
+ }
+
+ public void testAssertContainsAllOf() {
+ List<?> list = Arrays.asList("a", "a", "b", "c");
+ Helpers.assertContainsAllOf(list, "a");
+ Helpers.assertContainsAllOf(list, "a", "a");
+ Helpers.assertContainsAllOf(list, "a", "b", "c");
+ Helpers.assertContainsAllOf(list, "a", "b", "c", "a");
+
+ try {
+ Helpers.assertContainsAllOf(list, "d");
+ fail();
+ } catch (AssertionError expected) {
+ }
+
+ try {
+ Helpers.assertContainsAllOf(list, "a", "b", "c", "d");
+ fail();
+ } catch (AssertionError expected) {
+ }
+
+ try {
+ Helpers.assertContainsAllOf(list, "a", "a", "a");
+ fail();
+ } catch (AssertionError expected) {
+ }
+ }
}
diff --git a/guava-testlib/test/com/google/common/collect/testing/features/FeatureEnumTest.java b/guava-testlib/test/com/google/common/collect/testing/features/FeatureEnumTest.java
index 394dcd4..7ebcae0 100644
--- a/guava-testlib/test/com/google/common/collect/testing/features/FeatureEnumTest.java
+++ b/guava-testlib/test/com/google/common/collect/testing/features/FeatureEnumTest.java
@@ -23,6 +23,7 @@ import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
+import java.util.Locale;
/**
* Since annotations have some reusability issues that force copy and paste
@@ -35,19 +36,19 @@ public class FeatureEnumTest extends TestCase {
private static void assertGoodTesterAnnotation(
Class<? extends Annotation> annotationClass) {
assertNotNull(
- String.format("%s must be annotated with @TesterAnnotation.",
+ rootLocaleFormat("%s must be annotated with @TesterAnnotation.",
annotationClass),
annotationClass.getAnnotation(TesterAnnotation.class));
final Retention retentionPolicy =
annotationClass.getAnnotation(Retention.class);
assertNotNull(
- String.format("%s must have a @Retention annotation.", annotationClass),
+ rootLocaleFormat("%s must have a @Retention annotation.", annotationClass),
retentionPolicy);
assertEquals(
- String.format("%s must have RUNTIME RetentionPolicy.", annotationClass),
+ rootLocaleFormat("%s must have RUNTIME RetentionPolicy.", annotationClass),
RetentionPolicy.RUNTIME, retentionPolicy.value());
assertNotNull(
- String.format("%s must be inherited.", annotationClass),
+ rootLocaleFormat("%s must be inherited.", annotationClass),
annotationClass.getAnnotation(Inherited.class));
for (String propertyName : new String[]{"value", "absent"}) {
@@ -55,14 +56,14 @@ public class FeatureEnumTest extends TestCase {
try {
method = annotationClass.getMethod(propertyName);
} catch (NoSuchMethodException e) {
- fail(String.format("%s must have a property named '%s'.",
+ fail(rootLocaleFormat("%s must have a property named '%s'.",
annotationClass, propertyName));
}
final Class<?> returnType = method.getReturnType();
- assertTrue(String.format("%s.%s() must return an array.",
+ assertTrue(rootLocaleFormat("%s.%s() must return an array.",
annotationClass, propertyName),
returnType.isArray());
- assertSame(String.format("%s.%s() must return an array of %s.",
+ assertSame(rootLocaleFormat("%s.%s() must return an array of %s.",
annotationClass, propertyName, annotationClass.getDeclaringClass()),
annotationClass.getDeclaringClass(), returnType.getComponentType());
}
@@ -78,14 +79,14 @@ public class FeatureEnumTest extends TestCase {
if (containedClass.isAnnotation()) {
assertGoodTesterAnnotation(asAnnotation(containedClass));
} else {
- fail(String.format("Feature enum %s contains a class named " +
- "'Require' but it is not an annotation.", featureEnumClass));
+ fail(rootLocaleFormat("Feature enum %s contains a class named "
+ + "'Require' but it is not an annotation.", featureEnumClass));
}
return;
}
}
- fail(String.format("Feature enum %s should contain an " +
- "annotation named 'Require'.", featureEnumClass));
+ fail(rootLocaleFormat("Feature enum %s should contain an "
+ + "annotation named 'Require'.", featureEnumClass));
}
@SuppressWarnings("unchecked")
@@ -94,7 +95,7 @@ public class FeatureEnumTest extends TestCase {
return (Class<? extends Annotation>) clazz;
} else {
throw new IllegalArgumentException(
- String.format("%s is not an annotation.", clazz));
+ rootLocaleFormat("%s is not an annotation.", clazz));
}
}
@@ -105,4 +106,8 @@ public class FeatureEnumTest extends TestCase {
assertGoodFeatureEnum(CollectionSize.class);
assertGoodFeatureEnum(MapFeature.class);
}
+
+ private static String rootLocaleFormat(String format, Object... args) {
+ return String.format(Locale.ROOT, format, args);
+ }
}
diff --git a/guava-testlib/test/com/google/common/collect/testing/features/FeatureUtilTest.java b/guava-testlib/test/com/google/common/collect/testing/features/FeatureUtilTest.java
index 70ec78a..9fcfa51 100644
--- a/guava-testlib/test/com/google/common/collect/testing/features/FeatureUtilTest.java
+++ b/guava-testlib/test/com/google/common/collect/testing/features/FeatureUtilTest.java
@@ -159,18 +159,17 @@ public class FeatureUtilTest extends TestCase {
features = Sets.<Feature<?>>newHashSet(
ExampleDerivedFeature.DERIVED_FEATURE_1);
- assertThat(FeatureUtil.addImpliedFeatures(features)).has().item(
- ExampleDerivedFeature.DERIVED_FEATURE_1);
+ assertThat(FeatureUtil.addImpliedFeatures(features))
+ .contains(ExampleDerivedFeature.DERIVED_FEATURE_1);
- features = Sets.<Feature<?>>newHashSet(
- ExampleDerivedFeature.DERIVED_FEATURE_2);
- assertThat(FeatureUtil.addImpliedFeatures(features)).has().exactly(
+ features = Sets.<Feature<?>>newHashSet(ExampleDerivedFeature.DERIVED_FEATURE_2);
+ assertThat(FeatureUtil.addImpliedFeatures(features)).containsExactly(
ExampleDerivedFeature.DERIVED_FEATURE_2,
ExampleBaseFeature.BASE_FEATURE_1);
features = Sets.<Feature<?>>newHashSet(
ExampleDerivedFeature.COMPOUND_DERIVED_FEATURE);
- assertThat(FeatureUtil.addImpliedFeatures(features)).has().exactly(
+ assertThat(FeatureUtil.addImpliedFeatures(features)).containsExactly(
ExampleDerivedFeature.COMPOUND_DERIVED_FEATURE,
ExampleDerivedFeature.DERIVED_FEATURE_1,
ExampleDerivedFeature.DERIVED_FEATURE_2,
@@ -193,12 +192,10 @@ public class FeatureUtilTest extends TestCase {
features = Sets.<Feature<?>>newHashSet(
ExampleDerivedFeature.DERIVED_FEATURE_2);
- assertThat(FeatureUtil.impliedFeatures(features)).has().item(
- ExampleBaseFeature.BASE_FEATURE_1);
+ assertThat(FeatureUtil.impliedFeatures(features)).contains(ExampleBaseFeature.BASE_FEATURE_1);
- features = Sets.<Feature<?>>newHashSet(
- ExampleDerivedFeature.COMPOUND_DERIVED_FEATURE);
- assertThat(FeatureUtil.impliedFeatures(features)).has().exactly(
+ features = Sets.<Feature<?>>newHashSet(ExampleDerivedFeature.COMPOUND_DERIVED_FEATURE);
+ assertThat(FeatureUtil.impliedFeatures(features)).containsExactly(
ExampleDerivedFeature.DERIVED_FEATURE_1,
ExampleDerivedFeature.DERIVED_FEATURE_2,
ExampleBaseFeature.BASE_FEATURE_1,
@@ -250,8 +247,7 @@ public class FeatureUtilTest extends TestCase {
ExampleDerivedInterfaceTester_Conflict.class);
fail("Expected ConflictingRequirementsException");
} catch (ConflictingRequirementsException e) {
- assertThat(e.getConflicts()).has().item(
- ExampleBaseFeature.BASE_FEATURE_1);
+ assertThat(e.getConflicts()).contains(ExampleBaseFeature.BASE_FEATURE_1);
assertEquals(ExampleDerivedInterfaceTester_Conflict.class, e.getSource());
}
}
@@ -264,8 +260,7 @@ public class FeatureUtilTest extends TestCase {
FeatureUtil.buildTesterRequirements(method);
fail("Expected ConflictingRequirementsException");
} catch (ConflictingRequirementsException e) {
- assertThat(e.getConflicts()).has().item(
- ExampleBaseFeature.BASE_FEATURE_1);
+ assertThat(e.getConflicts()).contains(ExampleBaseFeature.BASE_FEATURE_1);
assertEquals(method, e.getSource());
}
}
diff --git a/guava-testlib/test/com/google/common/testing/AbstractPackageSanityTestsTest.java b/guava-testlib/test/com/google/common/testing/AbstractPackageSanityTestsTest.java
index 43dcc1c..b0f2787 100644
--- a/guava-testlib/test/com/google/common/testing/AbstractPackageSanityTestsTest.java
+++ b/guava-testlib/test/com/google/common/testing/AbstractPackageSanityTestsTest.java
@@ -47,31 +47,38 @@ public class AbstractPackageSanityTestsTest extends TestCase {
}
public void testFindClassesToTest_noCorrespondingTestClass() {
- assertThat(findClassesToTest(ImmutableList.of(Foo.class)))
- .has().exactly(Foo.class).inOrder();
+ assertThat(findClassesToTest(ImmutableList.of(Foo.class))).containsExactly(Foo.class);
assertThat(findClassesToTest(ImmutableList.of(Foo.class, Foo2Test.class)))
- .has().exactly(Foo.class).inOrder();
+ .containsExactly(Foo.class);
}
public void testFindClassesToTest_publicApiOnly() {
sanityTests.publicApiOnly();
assertThat(findClassesToTest(ImmutableList.of(Foo.class)))
.isEmpty();
- assertThat(findClassesToTest(ImmutableList.of(PublicFoo.class))).has().item(PublicFoo.class);
+ assertThat(findClassesToTest(ImmutableList.of(PublicFoo.class))).contains(PublicFoo.class);
}
public void testFindClassesToTest_ignoreClasses() {
sanityTests.ignoreClasses(Predicates.<Object>equalTo(PublicFoo.class));
assertThat(findClassesToTest(ImmutableList.of(PublicFoo.class)))
.isEmpty();
- assertThat(findClassesToTest(ImmutableList.of(Foo.class))).has().item(Foo.class);
+ assertThat(findClassesToTest(ImmutableList.of(Foo.class))).contains(Foo.class);
+ }
+
+ public void testFindClassesToTeset_ignoreUnderscores() {
+ assertThat(findClassesToTest(ImmutableList.of(Foo.class, Foo_Bar.class)))
+ .containsExactly(Foo.class, Foo_Bar.class);
+ sanityTests.ignoreClasses(AbstractPackageSanityTests.UNDERSCORE_IN_NAME);
+ assertThat(findClassesToTest(ImmutableList.of(Foo.class, Foo_Bar.class)))
+ .containsExactly(Foo.class);
}
public void testFindClassesToTest_withCorrespondingTestClassButNotExplicitlyTested() {
assertThat(findClassesToTest(ImmutableList.of(Foo.class, FooTest.class), "testNotThere"))
- .has().exactly(Foo.class).inOrder();
+ .containsExactly(Foo.class);
assertThat(findClassesToTest(ImmutableList.of(Foo.class, FooTest.class), "testNotPublic"))
- .has().exactly(Foo.class).inOrder();
+ .containsExactly(Foo.class);
}
public void testFindClassesToTest_withCorrespondingTestClassAndExplicitlyTested() {
@@ -84,7 +91,7 @@ public class AbstractPackageSanityTestsTest extends TestCase {
public void testFindClassesToTest_withCorrespondingTestClass_noTestName() {
assertThat(findClassesToTest(ImmutableList.of(Foo.class, FooTest.class)))
- .has().exactly(Foo.class).inOrder();
+ .containsExactly(Foo.class);
}
static class EmptyTestCase {}
@@ -97,6 +104,8 @@ public class AbstractPackageSanityTestsTest extends TestCase {
static class Foo {}
+ static class Foo_Bar {}
+
public static class PublicFoo {}
static class FooTest {
diff --git a/guava-testlib/test/com/google/common/testing/ArbitraryInstancesTest.java b/guava-testlib/test/com/google/common/testing/ArbitraryInstancesTest.java
index bf2be65..e94d283 100644
--- a/guava-testlib/test/com/google/common/testing/ArbitraryInstancesTest.java
+++ b/guava-testlib/test/com/google/common/testing/ArbitraryInstancesTest.java
@@ -16,6 +16,8 @@
package com.google.common.testing;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.base.CharMatcher;
import com.google.common.base.Charsets;
import com.google.common.base.Equivalence;
@@ -222,9 +224,9 @@ public class ArbitraryInstancesTest extends TestCase {
assertNotNull(ArbitraryInstances.get(CharMatcher.class));
assertNotNull(ArbitraryInstances.get(Currency.class).getCurrencyCode());
assertNotNull(ArbitraryInstances.get(Locale.class));
- ArbitraryInstances.get(Joiner.class).join(ImmutableList.of("a"));
- ArbitraryInstances.get(Splitter.class).split("a,b");
- assertFalse(ArbitraryInstances.get(Optional.class).isPresent());
+ assertNotNull(ArbitraryInstances.get(Joiner.class).join(ImmutableList.of("a")));
+ assertNotNull(ArbitraryInstances.get(Splitter.class).split("a,b"));
+ assertThat(ArbitraryInstances.get(Optional.class)).isAbsent();
ArbitraryInstances.get(Stopwatch.class).start();
assertNotNull(ArbitraryInstances.get(Ticker.class));
assertNotNull(ArbitraryInstances.get(MapConstraint.class));
@@ -271,9 +273,9 @@ public class ArbitraryInstancesTest extends TestCase {
}
public void testGet_array() {
- assertEquals(0, ArbitraryInstances.get(int[].class).length);
- assertEquals(0, ArbitraryInstances.get(Object[].class).length);
- assertEquals(0, ArbitraryInstances.get(String[].class).length);
+ assertThat(ArbitraryInstances.get(int[].class)).isEmpty();
+ assertThat(ArbitraryInstances.get(Object[].class)).isEmpty();
+ assertThat(ArbitraryInstances.get(String[].class)).isEmpty();
}
public void testGet_enum() {
@@ -302,13 +304,17 @@ public class ArbitraryInstancesTest extends TestCase {
public void testGet_mutable() {
assertEquals(0, ArbitraryInstances.get(ArrayList.class).size());
assertEquals(0, ArbitraryInstances.get(HashMap.class).size());
- assertEquals("", ArbitraryInstances.get(Appendable.class).toString());
- assertEquals("", ArbitraryInstances.get(StringBuilder.class).toString());
- assertEquals("", ArbitraryInstances.get(StringBuffer.class).toString());
+ assertThat(ArbitraryInstances.get(Appendable.class).toString()).isEmpty();
+ assertThat(ArbitraryInstances.get(StringBuilder.class).toString()).isEmpty();
+ assertThat(ArbitraryInstances.get(StringBuffer.class).toString()).isEmpty();
assertFreshInstanceReturned(
- ArrayList.class, HashMap.class,
- Appendable.class, StringBuilder.class, StringBuffer.class,
- Throwable.class, Exception.class);
+ ArrayList.class,
+ HashMap.class,
+ Appendable.class,
+ StringBuilder.class,
+ StringBuffer.class,
+ Throwable.class,
+ Exception.class);
}
public void testGet_io() throws IOException {
diff --git a/guava-testlib/test/com/google/common/testing/ClassSanityTesterTest.java b/guava-testlib/test/com/google/common/testing/ClassSanityTesterTest.java
index 4848293..639b73f 100644
--- a/guava-testlib/test/com/google/common/testing/ClassSanityTesterTest.java
+++ b/guava-testlib/test/com/google/common/testing/ClassSanityTesterTest.java
@@ -35,6 +35,7 @@ import java.lang.reflect.InvocationTargetException;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -83,10 +84,11 @@ public class ClassSanityTesterTest extends TestCase {
try {
tester.forAllPublicStaticMethods(NoPublicStaticMethods.class).testEquals();
} catch (AssertionFailedError expected) {
- assertEquals(
- "No public static methods that return java.lang.Object or subtype are found in "
- + NoPublicStaticMethods.class + ".",
- expected.getMessage());
+ assertThat(expected)
+ .hasMessage(
+ "No public static methods that return java.lang.Object or subtype are found in "
+ + NoPublicStaticMethods.class
+ + ".");
return;
}
fail();
@@ -140,10 +142,11 @@ public class ClassSanityTesterTest extends TestCase {
.thatReturn(Iterable.class)
.testNulls();
} catch (AssertionFailedError expected) {
- assertEquals(
- "No public static methods that return java.lang.Iterable or subtype are found in "
- + BadNullsFactory.class + ".",
- expected.getMessage());
+ assertThat(expected)
+ .hasMessage(
+ "No public static methods that return java.lang.Iterable or subtype are found in "
+ + BadNullsFactory.class
+ + ".");
return;
}
fail();
@@ -543,6 +546,7 @@ public class ClassSanityTesterTest extends TestCase {
NotInstantiable y = new NotInstantiable();
tester.setDistinctValues(NotInstantiable.class, x, y);
assertNotNull(tester.instantiate(ConstructorParameterNotInstantiable.class));
+ tester.testEquals(ConstructorParameterMapOfNotInstantiable.class);
}
public void testInstantiate_setSampleInstances_empty() throws Exception {
@@ -1185,6 +1189,25 @@ public class ClassSanityTesterTest extends TestCase {
public ConstructorParameterNotInstantiable(@SuppressWarnings("unused") NotInstantiable x) {}
}
+ static class ConstructorParameterMapOfNotInstantiable {
+ private final Map<NotInstantiable, NotInstantiable> m;
+
+ public ConstructorParameterMapOfNotInstantiable(
+ Map<NotInstantiable, NotInstantiable> m) {
+ this.m = checkNotNull(m);
+ }
+ @Override public boolean equals(@Nullable Object obj) {
+ if (obj instanceof ConstructorParameterMapOfNotInstantiable) {
+ return m.equals(((ConstructorParameterMapOfNotInstantiable) obj).m);
+ } else {
+ return false;
+ }
+ }
+ @Override public int hashCode() {
+ return m.hashCode();
+ }
+ }
+
// Test that we should get a distinct parameter error when doing equals test.
static class ConstructorParameterWithOptionalNotInstantiable {
public ConstructorParameterWithOptionalNotInstantiable(Optional<NotInstantiable> x) {
diff --git a/guava-testlib/test/com/google/common/testing/EqualsTesterTest.java b/guava-testlib/test/com/google/common/testing/EqualsTesterTest.java
index 9c5bf13..2476a12 100644
--- a/guava-testlib/test/com/google/common/testing/EqualsTesterTest.java
+++ b/guava-testlib/test/com/google/common/testing/EqualsTesterTest.java
@@ -389,10 +389,7 @@ public class EqualsTesterTest extends TestCase {
private static class InvalidEqualsIncompatibleClassObject {
@Override public boolean equals(Object o) {
- if (o == null) {
- return false;
- }
- return true;
+ return o != null;
}
@Override public int hashCode() {
diff --git a/guava-testlib/test/com/google/common/testing/FreshValueGeneratorTest.java b/guava-testlib/test/com/google/common/testing/FreshValueGeneratorTest.java
index b45fc03..b0547d1 100644
--- a/guava-testlib/test/com/google/common/testing/FreshValueGeneratorTest.java
+++ b/guava-testlib/test/com/google/common/testing/FreshValueGeneratorTest.java
@@ -46,7 +46,6 @@ import com.google.common.collect.ImmutableTable;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.LinkedHashMultiset;
import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multiset;
@@ -54,7 +53,6 @@ import com.google.common.collect.Ordering;
import com.google.common.collect.Range;
import com.google.common.collect.RowSortedTable;
import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
import com.google.common.collect.SortedMultiset;
import com.google.common.collect.Table;
import com.google.common.collect.TreeBasedTable;
@@ -153,15 +151,15 @@ public class FreshValueGeneratorTest extends TestCase {
public void testStringArray() {
FreshValueGenerator generator = new FreshValueGenerator();
- String[] a1 = generator.generate(String[].class);
- String[] a2 = generator.generate(String[].class);
+ String[] a1 = generator.generateFresh(String[].class);
+ String[] a2 = generator.generateFresh(String[].class);
assertFalse(a1[0].equals(a2[0]));
}
public void testPrimitiveArray() {
FreshValueGenerator generator = new FreshValueGenerator();
- int[] a1 = generator.generate(int[].class);
- int[] a2 = generator.generate(int[].class);
+ int[] a1 = generator.generateFresh(int[].class);
+ int[] a2 = generator.generateFresh(int[].class);
assertTrue(a1[0] != a2[0]);
}
@@ -171,503 +169,261 @@ public class FreshValueGeneratorTest extends TestCase {
public void testImmutableList() {
assertFreshInstance(new TypeToken<ImmutableList<String>>() {});
- assertValueAndTypeEquals(ImmutableList.of(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableList<String>>() {}));
- assertValueAndTypeEquals(ImmutableList.of(new FreshValueGenerator().generate(int.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableList<Integer>>() {}));
- assertValueAndTypeEquals(ImmutableList.of(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableList<?>>() {}));
}
public void testImmutableSet() {
assertFreshInstance(new TypeToken<ImmutableSet<String>>() {});
- assertValueAndTypeEquals(ImmutableSet.of(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableSet<String>>() {}));
- assertValueAndTypeEquals(ImmutableSet.of(new FreshValueGenerator().generate(Number.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableSet<Number>>() {}));
- assertValueAndTypeEquals(ImmutableSet.of(new FreshValueGenerator().generate(Number.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableSet<? extends Number>>() {}));
}
public void testImmutableSortedSet() {
assertFreshInstance(new TypeToken<ImmutableSortedSet<String>>() {});
- assertValueAndTypeEquals(
- ImmutableSortedSet.of(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableSortedSet<String>>() {}));
}
public void testImmutableMultiset() {
assertFreshInstance(new TypeToken<ImmutableSortedSet<String>>() {});
- assertValueAndTypeEquals(ImmutableMultiset.of(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableMultiset<String>>() {}));
- assertValueAndTypeEquals(ImmutableMultiset.of(new FreshValueGenerator().generate(Number.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableMultiset<Number>>() {}));
assertNotInstantiable(new TypeToken<ImmutableMultiset<EmptyEnum>>() {});
}
public void testImmutableCollection() {
assertFreshInstance(new TypeToken<ImmutableCollection<String>>() {});
- assertValueAndTypeEquals(ImmutableList.of(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableCollection<String>>() {}));
assertNotInstantiable(new TypeToken<ImmutableCollection<EmptyEnum>>() {});
}
public void testImmutableMap() {
assertFreshInstance(new TypeToken<ImmutableMap<String, Integer>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- assertValueAndTypeEquals(
- ImmutableMap.of(generator.generate(String.class), generator.generate(int.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableMap<String, Integer>>() {}));
}
public void testImmutableSortedMap() {
assertFreshInstance(new TypeToken<ImmutableSortedMap<String, Integer>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- assertValueAndTypeEquals(
- ImmutableSortedMap.of(generator.generate(String.class), generator.generate(int.class)),
- new FreshValueGenerator().generate(
- new TypeToken<ImmutableSortedMap<String, Integer>>() {}));
}
public void testImmutableMultimap() {
assertFreshInstance(new TypeToken<ImmutableMultimap<String, Integer>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- assertValueAndTypeEquals(
- ImmutableMultimap.of(generator.generate(String.class), generator.generate(int.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableMultimap<String, Integer>>() {}));
assertNotInstantiable(new TypeToken<ImmutableMultimap<EmptyEnum, String>>() {});
}
public void testImmutableListMultimap() {
assertFreshInstance(new TypeToken<ImmutableListMultimap<String, Integer>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- assertValueAndTypeEquals(
- ImmutableListMultimap.of(generator.generate(String.class), generator.generate(int.class)),
- new FreshValueGenerator().generate(
- new TypeToken<ImmutableListMultimap<String, Integer>>() {}));
}
public void testImmutableSetMultimap() {
assertFreshInstance(new TypeToken<ImmutableSetMultimap<String, Integer>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- assertValueAndTypeEquals(
- ImmutableSetMultimap.of(generator.generate(String.class), generator.generate(int.class)),
- new FreshValueGenerator().generate(
- new TypeToken<ImmutableSetMultimap<String, Integer>>() {}));
}
public void testImmutableBiMap() {
assertFreshInstance(new TypeToken<ImmutableBiMap<String, Integer>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- assertValueAndTypeEquals(
- ImmutableBiMap.of(generator.generate(String.class), generator.generate(int.class)),
- new FreshValueGenerator().generate(
- new TypeToken<ImmutableBiMap<String, Integer>>() {}));
}
public void testImmutableTable() {
assertFreshInstance(new TypeToken<ImmutableTable<String, Integer, ImmutableList<String>>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- assertValueAndTypeEquals(
- ImmutableTable.of(
- generator.generate(String.class), generator.generate(int.class),
- generator.generate(new TypeToken<ImmutableList<String>>() {})),
- new FreshValueGenerator().generate(
- new TypeToken<ImmutableTable<String, Integer, ImmutableList<String>>>() {}));
}
public void testList() {
assertFreshInstance(new TypeToken<List<String>>() {});
- assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<List<String>>() {}));
- assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(int.class)),
- new FreshValueGenerator().generate(new TypeToken<List<Integer>>() {}));
- assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<List<?>>() {}));
assertNotInstantiable(new TypeToken<List<EmptyEnum>>() {});
}
public void testArrayList() {
assertFreshInstance(new TypeToken<ArrayList<String>>() {});
- assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<ArrayList<String>>() {}));
- assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(int.class)),
- new FreshValueGenerator().generate(new TypeToken<ArrayList<Integer>>() {}));
- assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<ArrayList<?>>() {}));
assertNotInstantiable(new TypeToken<ArrayList<EmptyEnum>>() {});
}
public void testLinkedList() {
assertFreshInstance(new TypeToken<LinkedList<String>>() {});
- assertValueAndTypeEquals(newLinkedList(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<LinkedList<String>>() {}));
}
public void testSet() {
assertFreshInstance(new TypeToken<Set<String>>() {});
- assertValueAndTypeEquals(
- newLinkedHashSet(new FreshValueGenerator().generate(Number.class)),
- new FreshValueGenerator().generate(new TypeToken<Set<? extends Number>>() {}));
assertNotInstantiable(new TypeToken<Set<EmptyEnum>>() {});
}
public void testHashSet() {
assertFreshInstance(new TypeToken<HashSet<String>>() {});
- assertValueAndTypeEquals(
- newLinkedHashSet(new FreshValueGenerator().generate(Number.class)),
- new FreshValueGenerator().generate(new TypeToken<HashSet<? extends Number>>() {}));
}
public void testLinkedHashSet() {
assertFreshInstance(new TypeToken<LinkedHashSet<String>>() {});
- assertValueAndTypeEquals(
- newLinkedHashSet(new FreshValueGenerator().generate(Number.class)),
- new FreshValueGenerator().generate(new TypeToken<LinkedHashSet<? extends Number>>() {}));
}
public void testTreeSet() {
assertFreshInstance(new TypeToken<TreeSet<String>>() {});
- TreeSet<String> expected = Sets.newTreeSet();
- expected.add(new FreshValueGenerator().generate(String.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<TreeSet<? extends CharSequence>>() {}));
- assertNotInstantiable(new TypeToken<TreeSet<EmptyEnum>>() {});
}
public void testSortedSet() {
assertFreshInstance(new TypeToken<SortedSet<String>>() {});
- TreeSet<String> expected = Sets.newTreeSet();
- expected.add(new FreshValueGenerator().generate(String.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<SortedSet<String>>() {}));
- assertNotInstantiable(new TypeToken<SortedSet<EmptyEnum>>() {});
}
public void testNavigableSet() {
assertFreshInstance(new TypeToken<NavigableSet<String>>() {});
- TreeSet<String> expected = Sets.newTreeSet();
- expected.add(new FreshValueGenerator().generate(String.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<NavigableSet<String>>() {}));
- assertNotInstantiable(new TypeToken<NavigableSet<EmptyEnum>>() {});
}
public void testMultiset() {
assertFreshInstance(new TypeToken<Multiset<String>>() {});
- Multiset<String> expected = HashMultiset.create();
- expected.add(new FreshValueGenerator().generate(String.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<Multiset<String>>() {}));
- assertNotInstantiable(new TypeToken<Multiset<EmptyEnum>>() {});
}
public void testSortedMultiset() {
assertFreshInstance(new TypeToken<SortedMultiset<String>>() {});
- SortedMultiset<String> expected = TreeMultiset.create();
- expected.add(new FreshValueGenerator().generate(String.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<SortedMultiset<String>>() {}));
- assertNotInstantiable(new TypeToken<Multiset<EmptyEnum>>() {});
}
public void testHashMultiset() {
assertFreshInstance(new TypeToken<HashMultiset<String>>() {});
- HashMultiset<String> expected = HashMultiset.create();
- expected.add(new FreshValueGenerator().generate(String.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<HashMultiset<String>>() {}));
}
public void testLinkedHashMultiset() {
assertFreshInstance(new TypeToken<LinkedHashMultiset<String>>() {});
- LinkedHashMultiset<String> expected = LinkedHashMultiset.create();
- expected.add(new FreshValueGenerator().generate(String.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<LinkedHashMultiset<String>>() {}));
}
public void testTreeMultiset() {
assertFreshInstance(new TypeToken<TreeMultiset<String>>() {});
- TreeMultiset<String> expected = TreeMultiset.create();
- expected.add(new FreshValueGenerator().generate(String.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<TreeMultiset<String>>() {}));
}
public void testImmutableSortedMultiset() {
assertFreshInstance(new TypeToken<ImmutableSortedMultiset<String>>() {});
- assertValueAndTypeEquals(
- ImmutableSortedMultiset.of(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<ImmutableSortedMultiset<String>>() {}));
- assertNotInstantiable(new TypeToken<Multiset<EmptyEnum>>() {});
}
public void testCollection() {
assertFreshInstance(new TypeToken<Collection<String>>() {});
- assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<Collection<String>>() {}));
- assertNotInstantiable(new TypeToken<Collection<EmptyEnum>>() {});
}
public void testIterable() {
assertFreshInstance(new TypeToken<Iterable<String>>() {});
- assertValueAndTypeEquals(Lists.newArrayList(new FreshValueGenerator().generate(String.class)),
- new FreshValueGenerator().generate(new TypeToken<Iterable<String>>() {}));
- assertNotInstantiable(new TypeToken<Iterable<EmptyEnum>>() {});
}
public void testMap() {
assertFreshInstance(new TypeToken<Map<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- Map<String, Integer> expected = Maps.newLinkedHashMap();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<Map<String, Integer>>() {}));
- assertNotInstantiable(new TypeToken<Map<EmptyEnum, String>>() {});
}
public void testHashMap() {
assertFreshInstance(new TypeToken<HashMap<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- HashMap<String, Integer> expected = Maps.newLinkedHashMap();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<HashMap<String, Integer>>() {}));
}
public void testLinkedHashMap() {
assertFreshInstance(new TypeToken<LinkedHashMap<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- LinkedHashMap<String, Integer> expected = Maps.newLinkedHashMap();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<LinkedHashMap<String, Integer>>() {}));
}
public void testTreeMap() {
assertFreshInstance(new TypeToken<TreeMap<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- TreeMap<String, Integer> expected = Maps.newTreeMap();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<TreeMap<String, Integer>>() {}));
- assertNotInstantiable(new TypeToken<LinkedHashSet<EmptyEnum>>() {});
}
public void testSortedMap() {
assertFreshInstance(new TypeToken<SortedMap<?, String>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- TreeMap<String, Integer> expected = Maps.newTreeMap();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(
- new TypeToken<SortedMap<String, Integer>>() {}));
- assertNotInstantiable(new TypeToken<SortedMap<EmptyEnum, String>>() {});
}
public void testNavigableMap() {
assertFreshInstance(new TypeToken<NavigableMap<?, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- TreeMap<String, Integer> expected = Maps.newTreeMap();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(
- new TypeToken<NavigableMap<String, Integer>>() {}));
- assertNotInstantiable(new TypeToken<NavigableMap<EmptyEnum, String>>() {});
}
public void testConcurrentMap() {
assertFreshInstance(new TypeToken<ConcurrentMap<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- ConcurrentMap<String, Integer> expected = Maps.newConcurrentMap();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<ConcurrentMap<String, Integer>>() {}));
- assertNotInstantiable(new TypeToken<ConcurrentMap<EmptyEnum, String>>() {});
+ assertCanGenerateOnly(new TypeToken<ConcurrentMap<EmptyEnum, String>>() {},
+ Maps.newConcurrentMap());
}
public void testMultimap() {
assertFreshInstance(new TypeToken<Multimap<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- Multimap<String, Integer> expected = ArrayListMultimap.create();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<Multimap<String, Integer>>() {}));
- assertNotInstantiable(new TypeToken<Multimap<EmptyEnum, String>>() {});
}
public void testHashMultimap() {
assertFreshInstance(new TypeToken<HashMultimap<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- HashMultimap<String, Integer> expected = HashMultimap.create();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(new TypeToken<HashMultimap<String, Integer>>() {}));
}
public void testLinkedHashMultimap() {
assertFreshInstance(new TypeToken<LinkedHashMultimap<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- LinkedHashMultimap<String, Integer> expected = LinkedHashMultimap.create();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(
- new TypeToken<LinkedHashMultimap<String, Integer>>() {}));
}
public void testListMultimap() {
assertFreshInstance(new TypeToken<ListMultimap<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- ListMultimap<String, Integer> expected = ArrayListMultimap.create();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(
- new TypeToken<ListMultimap<String, Integer>>() {}));
- assertNotInstantiable(new TypeToken<ListMultimap<EmptyEnum, String>>() {});
}
public void testArrayListMultimap() {
assertFreshInstance(new TypeToken<ArrayListMultimap<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- ArrayListMultimap<String, Integer> expected = ArrayListMultimap.create();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(
- new TypeToken<ArrayListMultimap<String, Integer>>() {}));
}
public void testSetMultimap() {
assertFreshInstance(new TypeToken<SetMultimap<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- SetMultimap<String, Integer> expected = LinkedHashMultimap.create();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(
- new TypeToken<SetMultimap<String, Integer>>() {}));
- assertNotInstantiable(new TypeToken<SetMultimap<EmptyEnum, String>>() {});
}
public void testBiMap() {
assertFreshInstance(new TypeToken<BiMap<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- BiMap<String, Integer> expected = HashBiMap.create();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(
- new TypeToken<BiMap<String, Integer>>() {}));
assertNotInstantiable(new TypeToken<BiMap<EmptyEnum, String>>() {});
}
public void testHashBiMap() {
assertFreshInstance(new TypeToken<HashBiMap<String, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- HashBiMap<String, Integer> expected = HashBiMap.create();
- expected.put(generator.generate(String.class), generator.generate(int.class));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(
- new TypeToken<HashBiMap<String, Integer>>() {}));
}
public void testTable() {
assertFreshInstance(new TypeToken<Table<String, ?, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- Table<String, Integer, Object> expected = HashBasedTable.create();
- expected.put(generator.generate(String.class), generator.generate(int.class),
- generator.generate(new TypeToken<List<String>>() {}));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(
- new TypeToken<Table<String, Integer, List<String>>>() {}));
assertNotInstantiable(new TypeToken<Table<EmptyEnum, String, Integer>>() {});
}
public void testHashBasedTable() {
assertFreshInstance(new TypeToken<HashBasedTable<String, ?, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- HashBasedTable<String, Integer, Object> expected = HashBasedTable.create();
- expected.put(generator.generate(String.class), generator.generate(int.class),
- generator.generate(new TypeToken<List<String>>() {}));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(
- new TypeToken<HashBasedTable<String, Integer, List<String>>>() {}));
}
public void testRowSortedTable() {
assertFreshInstance(new TypeToken<RowSortedTable<String, ?, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- RowSortedTable<String, Integer, Object> expected = TreeBasedTable.create();
- expected.put(generator.generate(String.class), generator.generate(int.class),
- generator.generate(new TypeToken<List<String>>() {}));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(
- new TypeToken<RowSortedTable<String, Integer, List<String>>>() {}));
- assertNotInstantiable(new TypeToken<RowSortedTable<EmptyEnum, String, Integer>>() {});
}
public void testTreeBasedTable() {
assertFreshInstance(new TypeToken<TreeBasedTable<String, ?, ?>>() {});
- FreshValueGenerator generator = new FreshValueGenerator();
- TreeBasedTable<String, Integer, Object> expected = TreeBasedTable.create();
- expected.put(generator.generate(String.class), generator.generate(int.class),
- generator.generate(new TypeToken<List<String>>() {}));
- assertValueAndTypeEquals(expected,
- new FreshValueGenerator().generate(
- new TypeToken<TreeBasedTable<String, Integer, List<String>>>() {}));
}
public void testObject() {
- assertEquals(new FreshValueGenerator().generate(String.class),
- new FreshValueGenerator().generate(Object.class));
+ assertEquals(new FreshValueGenerator().generateFresh(String.class),
+ new FreshValueGenerator().generateFresh(Object.class));
}
public void testEnums() {
assertEqualInstance(EmptyEnum.class, null);
assertEqualInstance(OneConstantEnum.class, OneConstantEnum.CONSTANT1);
- assertFreshInstance(TwoConstantEnum.class);
- assertFreshInstance(new TypeToken<Optional<OneConstantEnum>>() {});
+ assertFreshInstance(TwoConstantEnum.class, 2);
+ assertFreshInstance(new TypeToken<Optional<OneConstantEnum>>() {}, 2);
+ assertFreshInstance(new TypeToken<List<OneConstantEnum>>() {}, 1);
+ assertFreshInstance(new TypeToken<List<TwoConstantEnum>>() {}, 2);
}
public void testOptional() {
FreshValueGenerator generator = new FreshValueGenerator();
- assertEquals(Optional.absent(), generator.generate(new TypeToken<Optional<String>>() {}));
- assertEquals(Optional.of("1"), generator.generate(new TypeToken<Optional<String>>() {}));
+ assertEquals(Optional.absent(), generator.generateFresh(new TypeToken<Optional<String>>() {}));
+ assertEquals(Optional.of("2"), generator.generateFresh(new TypeToken<Optional<String>>() {}));
// Test that the first generated instance for different Optional<T> is always absent().
// Having generated Optional<String> instances doesn't prevent absent() from being generated for
// other Optional types.
assertEquals(Optional.absent(),
- generator.generate(new TypeToken<Optional<OneConstantEnum>>() {}));
+ generator.generateFresh(new TypeToken<Optional<OneConstantEnum>>() {}));
assertEquals(Optional.of(OneConstantEnum.CONSTANT1),
- generator.generate(new TypeToken<Optional<OneConstantEnum>>() {}));
+ generator.generateFresh(new TypeToken<Optional<OneConstantEnum>>() {}));
}
public void testAddSampleInstances_twoInstances() {
FreshValueGenerator generator = new FreshValueGenerator();
generator.addSampleInstances(String.class, ImmutableList.of("a", "b"));
- assertEquals("a", generator.generate(String.class));
- assertEquals("b", generator.generate(String.class));
- assertEquals("a", generator.generate(String.class));
+ assertEquals("a", generator.generateFresh(String.class));
+ assertEquals("b", generator.generateFresh(String.class));
+ assertEquals("a", generator.generateFresh(String.class));
}
public void testAddSampleInstances_oneInstance() {
FreshValueGenerator generator = new FreshValueGenerator();
generator.addSampleInstances(String.class, ImmutableList.of("a"));
- assertEquals("a", generator.generate(String.class));
- assertEquals("a", generator.generate(String.class));
+ assertEquals("a", generator.generateFresh(String.class));
+ assertEquals("a", generator.generateFresh(String.class));
}
public void testAddSampleInstances_noInstance() {
FreshValueGenerator generator = new FreshValueGenerator();
generator.addSampleInstances(String.class, ImmutableList.<String>of());
- assertEquals(new FreshValueGenerator().generate(String.class),
- generator.generate(String.class));
+ assertEquals(new FreshValueGenerator().generateFresh(String.class),
+ generator.generateFresh(String.class));
}
public void testFreshCurrency() {
FreshValueGenerator generator = new FreshValueGenerator();
// repeat a few times to make sure we don't stumble upon a bad Locale
- assertNotNull(generator.generate(Currency.class));
- assertNotNull(generator.generate(Currency.class));
- assertNotNull(generator.generate(Currency.class));
+ assertNotNull(generator.generateFresh(Currency.class));
+ assertNotNull(generator.generateFresh(Currency.class));
+ assertNotNull(generator.generateFresh(Currency.class));
}
public void testNulls() throws Exception {
@@ -678,26 +434,31 @@ public class FreshValueGeneratorTest extends TestCase {
private static void assertFreshInstances(Class<?>... types) {
for (Class<?> type : types) {
- assertFreshInstance(type);
+ assertFreshInstance(type, 2);
}
}
private static void assertFreshInstance(TypeToken<?> type) {
- FreshValueGenerator generator = new FreshValueGenerator();
- Object value1 = generator.generate(type);
- Object value2 = generator.generate(type);
- assertNotNull("Null returned for " + type, value1);
- assertFalse("Equal instance " + value1 + " returned for " + type, value1.equals(value2));
+ assertFreshInstance(type, 3);
}
- private static <T> void assertFreshInstance(Class<T> type) {
- assertFreshInstance(TypeToken.of(type));
+ private static void assertFreshInstance(Class<?> type, int instances) {
+ assertFreshInstance(TypeToken.of(type), instances);
+ }
+
+ private static void assertFreshInstance(TypeToken<?> type, int instances) {
+ FreshValueGenerator generator = new FreshValueGenerator();
+ EqualsTester tester = new EqualsTester();
+ for (int i = 0; i < instances; i++) {
+ tester.addEqualityGroup(generator.generateFresh(type));
+ }
+ tester.testEquals();
}
private static <T> void assertEqualInstance(Class<T> type, T value) {
FreshValueGenerator generator = new FreshValueGenerator();
- assertEquals(value, generator.generate(type));
- assertEquals(value, generator.generate(type));
+ assertEquals(value, generator.generateFresh(type));
+ assertEquals(value, generator.generateFresh(type));
}
private enum EmptyEnum {}
@@ -710,24 +471,18 @@ public class FreshValueGeneratorTest extends TestCase {
CONSTANT1, CONSTANT2
}
- private static void assertValueAndTypeEquals(Object expected, Object actual) {
- assertEquals(expected, actual);
- assertEquals(expected.getClass(), actual.getClass());
+ private static void assertCanGenerateOnly(TypeToken<?> type, Object expected) {
+ FreshValueGenerator generator = new FreshValueGenerator();
+ assertValueAndTypeEquals(expected, generator.generateFresh(type));
+ assertNull(generator.generateFresh(type));
}
private static void assertNotInstantiable(TypeToken<?> type) {
- assertNull(new FreshValueGenerator().generate(type));
+ assertNull(new FreshValueGenerator().generateFresh(type));
}
- private static <E> LinkedHashSet<E> newLinkedHashSet(E element) {
- LinkedHashSet<E> set = Sets.newLinkedHashSet();
- set.add(element);
- return set;
- }
-
- private static <E> LinkedList<E> newLinkedList(E element) {
- LinkedList<E> list = Lists.newLinkedList();
- list.add(element);
- return list;
+ private static void assertValueAndTypeEquals(Object expected, Object actual) {
+ assertEquals(expected, actual);
+ assertEquals(expected.getClass(), actual.getClass());
}
}
diff --git a/guava-testlib/test/com/google/common/testing/GcFinalizationTest.java b/guava-testlib/test/com/google/common/testing/GcFinalizationTest.java
index 117186f..bcf501b 100644
--- a/guava-testlib/test/com/google/common/testing/GcFinalizationTest.java
+++ b/guava-testlib/test/com/google/common/testing/GcFinalizationTest.java
@@ -16,6 +16,8 @@
package com.google.common.testing;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.testing.GcFinalization.FinalizationPredicate;
import com.google.common.util.concurrent.SettableFuture;
@@ -118,8 +120,8 @@ public class GcFinalizationTest extends TestCase {
}
void assertWrapsInterruptedException(RuntimeException e) {
- assertTrue(e.getMessage().contains("Unexpected interrupt"));
- assertTrue(e.getCause() instanceof InterruptedException);
+ assertThat(e.getMessage()).contains("Unexpected interrupt");
+ assertThat(e.getCause()).isInstanceOf(InterruptedException.class);
}
public void testAwait_CountDownLatch_Interrupted() {
diff --git a/guava-testlib/test/com/google/common/testing/NullPointerTesterTest.java b/guava-testlib/test/com/google/common/testing/NullPointerTesterTest.java
index 5b44d7e..8bedfd9 100644
--- a/guava-testlib/test/com/google/common/testing/NullPointerTesterTest.java
+++ b/guava-testlib/test/com/google/common/testing/NullPointerTesterTest.java
@@ -44,6 +44,7 @@ import junit.framework.TestCase;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
@@ -290,7 +291,7 @@ public class NullPointerTesterTest extends TestCase {
/** To provide sanity during debugging. */
@Override public String toString() {
- return String.format("Bar(%s, %s)",
+ return rootLocaleFormat("Bar(%s, %s)",
actionWhenFirstParamIsNull, actionWhenSecondParamIsNull);
}
}
@@ -299,7 +300,7 @@ public class NullPointerTesterTest extends TestCase {
try {
new NullPointerTester().testMethod(bar, method);
} catch (AssertionFailedError incorrectError) {
- String errorMessage = String.format(
+ String errorMessage = rootLocaleFormat(
"Should not have flagged method %s for %s", method.getName(), bar);
assertNull(errorMessage, incorrectError);
}
@@ -311,7 +312,7 @@ public class NullPointerTesterTest extends TestCase {
} catch (AssertionFailedError expected) {
return; // good...we wanted a failure
}
- String errorMessage = String.format(
+ String errorMessage = rootLocaleFormat(
"Should have flagged method %s for %s", method.getName(), bar);
fail(errorMessage);
}
@@ -622,7 +623,7 @@ public class NullPointerTesterTest extends TestCase {
}
@SuppressWarnings("unused") // for NullPointerTester
- private static abstract class BaseClassThatFailsToThrow {
+ private abstract static class BaseClassThatFailsToThrow {
public void oneArg(String s) {}
}
@@ -634,7 +635,7 @@ public class NullPointerTesterTest extends TestCase {
}
@SuppressWarnings("unused") // for NullPointerTester
- private static abstract class BaseClassThatFailsToThrowForPackagePrivate {
+ private abstract static class BaseClassThatFailsToThrowForPackagePrivate {
void packagePrivateOneArg(String s) {}
}
@@ -647,7 +648,7 @@ public class NullPointerTesterTest extends TestCase {
}
@SuppressWarnings("unused") // for NullPointerTester
- private static abstract class BaseClassThatFailsToThrowForProtected {
+ private abstract static class BaseClassThatFailsToThrowForProtected {
protected void protectedOneArg(String s) {}
}
@@ -799,7 +800,7 @@ public class NullPointerTesterTest extends TestCase {
new NullPointerTester().testAllPublicInstanceMethods(new StringFoo());
}
- private static abstract class DefaultValueChecker {
+ private abstract static class DefaultValueChecker {
private final Map<Integer, Object> arguments = Maps.newHashMap();
@@ -901,7 +902,7 @@ public class NullPointerTesterTest extends TestCase {
void check() {
runTester();
Object[] defaultArray = (Object[]) getDefaultParameterValue(0);
- assertEquals(0, defaultArray.length);
+ assertThat(defaultArray).isEmpty();
}
}
@@ -920,7 +921,7 @@ public class NullPointerTesterTest extends TestCase {
void check() {
runTester();
String[] defaultArray = (String[]) getDefaultParameterValue(0);
- assertEquals(0, defaultArray.length);
+ assertThat(defaultArray).isEmpty();
}
}
@@ -1022,7 +1023,7 @@ public class NullPointerTesterTest extends TestCase {
runTester();
TypeToken<?> defaultType = (TypeToken<?>) getDefaultParameterValue(0);
assertTrue(new TypeToken<List<? super Number>>() {}
- .isAssignableFrom(defaultType));
+ .isSupertypeOf(defaultType));
}
}
@@ -1141,7 +1142,7 @@ public class NullPointerTesterTest extends TestCase {
new GenericInterface2DefaultValueChecker().check();
}
- private static abstract class AbstractGenericDefaultValueChecker<T>
+ private abstract static class AbstractGenericDefaultValueChecker<T>
extends DefaultValueChecker {
@SuppressWarnings("unused") // called by NullPointerTester
@@ -1162,7 +1163,7 @@ public class NullPointerTesterTest extends TestCase {
new GenericDefaultValueResolvedToStringChecker().check();
}
- private static abstract
+ private abstract static
class AbstractGenericDefaultValueForPackagePrivateMethodChecker<T>
extends DefaultValueChecker {
@@ -1272,4 +1273,8 @@ public class NullPointerTesterTest extends TestCase {
assertThat(expected.getMessage()).contains("inner class");
}
}
+
+ private static String rootLocaleFormat(String format, Object... args) {
+ return String.format(Locale.ROOT, format, args);
+ }
}
diff --git a/guava-testlib/test/com/google/common/testing/TearDownStackTest.java b/guava-testlib/test/com/google/common/testing/TearDownStackTest.java
index 7c3aa6e..30c0db8 100644
--- a/guava-testlib/test/com/google/common/testing/TearDownStackTest.java
+++ b/guava-testlib/test/com/google/common/testing/TearDownStackTest.java
@@ -16,6 +16,8 @@
package com.google.common.testing;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.annotations.GwtCompatible;
import junit.framework.TestCase;
@@ -83,7 +85,7 @@ public class TearDownStackTest extends TestCase {
stack.runTearDown();
fail("runTearDown should have thrown an exception");
} catch (ClusterException expected) {
- assertEquals("two", expected.getCause().getMessage());
+ assertThat(expected.getCause()).hasMessage("two");
} catch (RuntimeException e) {
throw new RuntimeException(
"A ClusterException should have been thrown, rather than a " + e.getClass().getName(), e);
diff --git a/guava-tests/benchmark/com/google/common/base/EnumsBenchmark.java b/guava-tests/benchmark/com/google/common/base/EnumsBenchmark.java
index 76e47c7..ec951e7 100644
--- a/guava-tests/benchmark/com/google/common/base/EnumsBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/base/EnumsBenchmark.java
@@ -65,10 +65,12 @@ public class EnumsBenchmark {
}
@Benchmark
- void getIfPresent(int repetitions) {
+ boolean getIfPresent(int repetitions) {
+ boolean retVal = false;
for (int i = 0; i < repetitions; ++i) {
- Enums.getIfPresent(enumType, sampleData[i & 255]);
+ retVal &= Enums.getIfPresent(enumType, sampleData[i & 255]).isPresent();
}
+ return retVal;
}
private enum SmallEnum {
diff --git a/guava-tests/benchmark/com/google/common/base/LazyStackTraceBenchmark.java b/guava-tests/benchmark/com/google/common/base/LazyStackTraceBenchmark.java
new file mode 100644
index 0000000..9b17b58
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/base/LazyStackTraceBenchmark.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.base;
+
+import static com.google.common.base.Throwables.lazyStackTrace;
+import static java.util.Arrays.asList;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+import com.google.caliper.api.SkipThisScenarioException;
+
+import java.util.List;
+
+/**
+ * Quick and dirty benchmark of {@link Throwables#lazyStackTrace(Throwable)}. We benchmark a "caller
+ * finder" implementation that might be used in a logging framework.
+ */
+public class LazyStackTraceBenchmark {
+ @Param({"20", "200", "2000"}) int stackDepth;
+ @Param({"-1", "3", "15"}) int breakAt;
+
+ int recursionCount;
+
+ private static final Object duh = new Object();
+
+ @Param Mode mode;
+
+ enum Mode {
+ LAZY_STACK_TRACE {
+ @Override
+ List<StackTraceElement> getStackTrace(Throwable t) {
+ return lazyStackTrace(t);
+ }
+ },
+ GET_STACK_TRACE {
+ @Override
+ List<StackTraceElement> getStackTrace(Throwable t) {
+ return asList(t.getStackTrace());
+ }
+ };
+
+ boolean timeIt(int reps, int breakAt) {
+ boolean dummy = false;
+ for (int i = 0; i < reps; i++) {
+ int f = 0;
+ Throwable t = new Throwable();
+ for (StackTraceElement ste : getStackTrace(t)) {
+ dummy |= ste == duh;
+ if (f++ == breakAt) {
+ break;
+ }
+ }
+ }
+ return dummy;
+ }
+
+ abstract List<StackTraceElement> getStackTrace(Throwable t);
+ }
+
+ @BeforeExperiment
+ public void doBefore() {
+ recursionCount = stackDepth - new Throwable().getStackTrace().length - 1;
+ if (recursionCount < 0) {
+ throw new SkipThisScenarioException();
+ }
+ }
+
+ @Benchmark
+ public boolean timeFindCaller(int reps) {
+ return timeFindCaller(reps, recursionCount);
+ }
+
+ private boolean timeFindCaller(int reps, int recurse) {
+ return recurse > 0
+ ? timeFindCaller(reps, recurse - 1)
+ : mode.timeIt(reps, breakAt);
+ }
+}
diff --git a/guava-tests/benchmark/com/google/common/base/Utf8Benchmark.java b/guava-tests/benchmark/com/google/common/base/Utf8Benchmark.java
deleted file mode 100644
index d30f6b4..0000000
--- a/guava-tests/benchmark/com/google/common/base/Utf8Benchmark.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2011 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.base;
-
-import com.google.caliper.BeforeExperiment;
-import com.google.caliper.Benchmark;
-import com.google.caliper.Param;
-
-import java.util.Random;
-
-/**
- * Benchmark for the {@link Utf8} class.
- *
- *
- * @author Martin Buchholz
- */
-public class Utf8Benchmark {
-
- static class MaxCodePoint {
- final int value;
-
- /**
- * Convert the input string to a code point. Accepts regular
- * decimal numerals, hex strings, and some symbolic names
- * meaningful to humans.
- */
- private static int decode(String userFriendly) {
- try {
- return Integer.decode(userFriendly);
- } catch (NumberFormatException ignored) {
- if (userFriendly.matches("(?i)(?:American|English|ASCII)")) {
- // 1-byte UTF-8 sequences - "American" ASCII text
- return 0x80;
- } else if (userFriendly.matches("(?i)(?:French|Latin|Western.*European)")) {
- // Mostly 1-byte UTF-8 sequences, mixed with occasional 2-byte
- // sequences - "Western European" text
- return 0x90;
- } else if (userFriendly.matches("(?i)(?:Branch.*Prediction.*Hostile)")) {
- // Defeat branch predictor for: c < 0x80 ; branch taken 50% of the time.
- return 0x100;
- } else if (userFriendly.matches("(?i)(?:Greek|Cyrillic|European|ISO.?8859)")) {
- // Mostly 2-byte UTF-8 sequences - "European" text
- return 0x800;
- } else if (userFriendly.matches("(?i)(?:Chinese|Han|Asian|BMP)")) {
- // Mostly 3-byte UTF-8 sequences - "Asian" text
- return Character.MIN_SUPPLEMENTARY_CODE_POINT;
- } else if (userFriendly.matches("(?i)(?:Cuneiform|rare|exotic|supplementary.*)")) {
- // Mostly 4-byte UTF-8 sequences - "rare exotic" text
- return Character.MAX_CODE_POINT;
- } else {
- throw new IllegalArgumentException("Can't decode codepoint " + userFriendly);
- }
- }
- }
-
- public static MaxCodePoint valueOf(String userFriendly) {
- return new MaxCodePoint(userFriendly);
- }
-
- public MaxCodePoint(String userFriendly) {
- value = decode(userFriendly);
- }
- }
-
- /**
- * The default values of maxCodePoint below provide pretty good
- * performance models of different kinds of common human text.
- * @see MaxCodePoint#decode
- */
- @Param({"0x80", "0x90", "0x100", "0x800", "0x10000", "0x10ffff"}) MaxCodePoint maxCodePoint;
-
- @Param({"100"}) int stringCount;
- @Param({"16384"}) int charCount;
- private CharSequence[] seqs; // actually, all StringBuilders
- private String[] strings;
- private byte[][] byteArrays;
-
- /**
- * Compute arrays of valid unicode text, and store it in 3 forms:
- * byte arrays, Strings, and StringBuilders (in a CharSequence[] to
- * make it a little harder for the JVM).
- */
- @BeforeExperiment void setUp() {
- final long seed = 99;
- final Random rnd = new Random(seed);
- seqs = new CharSequence[stringCount];
- strings = new String[stringCount];
- byteArrays = new byte[stringCount][];
- for (int i = 0; i < stringCount; i++) {
- StringBuilder sb = new StringBuilder();
- for (int j = 0; j < charCount; j++) {
- int codePoint;
- // discard illegal surrogate "codepoints"
- do {
- codePoint = rnd.nextInt(maxCodePoint.value);
- } while (isSurrogate(codePoint));
- sb.appendCodePoint(codePoint);
- }
- seqs[i] = sb;
- strings[i] = sb.toString();
- byteArrays[i] = strings[i].getBytes(Charsets.UTF_8);
- }
- }
-
- /**
- * Benchmarks {@link Utf8#isWellFormed} on valid byte arrays
- * containing pseudo-randomly-generated codePoints less than {@code
- * maxCodePoint}. A constant seed is used, so separate runs perform
- * identical computations.
- */
- @Benchmark void isWellFormed(int reps) {
- for (int i = 0; i < reps; i++) {
- for (byte[] byteArray : byteArrays) {
- if (!Utf8.isWellFormed(byteArray)) {
- throw new Error("unexpected invalid UTF-8");
- }
- }
- }
- }
-
- /**
- * Benchmarks {@link Utf8#length} on valid strings containing
- * pseudo-randomly-generated codePoints less than {@code
- * maxCodePoint}. A constant seed is used, so separate runs perform
- * identical computations.
- */
- @Benchmark void lengthOfString(int reps) {
- for (int i = 0; i < reps; i++) {
- for (String string : strings) {
- if (Utf8.encodedLength(string) == 1237482374) {
- throw new Error("Unlikely! We're just defeating the optimizer!");
- }
- }
- }
- }
-
- /**
- * Benchmarks {@link Utf8#length} on valid StringBuilders containing
- * pseudo-randomly-generated codePoints less than {@code
- * maxCodePoint}. A constant seed is used, so separate runs perform
- * identical computations.
- */
- @Benchmark void lengthOfStringBuilder(int reps) {
- for (int i = 0; i < reps; i++) {
- for (CharSequence seq : seqs) {
- if (Utf8.encodedLength(seq) == 1237482374) {
- throw new Error("Unlikely! We're just defeating the optimizer!");
- }
- }
- }
- }
-
- /** Character.isSurrogate was added in Java SE 7. */
- private boolean isSurrogate(int c) {
- return (Character.MIN_HIGH_SURROGATE <= c &&
- c <= Character.MAX_LOW_SURROGATE);
- }
-}
diff --git a/guava-tests/benchmark/com/google/common/base/WhitespaceMatcherBenchmark.java b/guava-tests/benchmark/com/google/common/base/WhitespaceMatcherBenchmark.java
index 8a9ed60..f26902c 100644
--- a/guava-tests/benchmark/com/google/common/base/WhitespaceMatcherBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/base/WhitespaceMatcherBenchmark.java
@@ -20,7 +20,6 @@ import com.google.caliper.BeforeExperiment;
import com.google.caliper.Benchmark;
import com.google.caliper.Param;
import com.google.caliper.runner.CaliperMain;
-import com.google.common.base.CharMatcher.FastMatcher;
import java.util.BitSet;
import java.util.Random;
@@ -39,7 +38,7 @@ public class WhitespaceMatcherBenchmark {
+ "\u0000\u0000\u0085\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a"
+ "\u0000\u0000\u0000\u0000\u0000\u205f\u1680\u0000\u0000\u180e\u0000\u0000\u0000";
- public static final CharMatcher OLD_WHITESPACE = new FastMatcher("CharMatcher.WHITESPACE") {
+ public static final CharMatcher OLD_WHITESPACE = new CharMatcher() {
@Override public boolean matches(char c) {
return OLD_WHITESPACE_TABLE.charAt(c % 79) == c;
}
diff --git a/guava-tests/benchmark/com/google/common/cache/MapMakerComparisonBenchmark.java b/guava-tests/benchmark/com/google/common/cache/MapMakerComparisonBenchmark.java
index 966e3e6..d5a9bbf 100644
--- a/guava-tests/benchmark/com/google/common/cache/MapMakerComparisonBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/cache/MapMakerComparisonBenchmark.java
@@ -18,8 +18,6 @@ package com.google.common.cache;
import com.google.caliper.BeforeExperiment;
import com.google.caliper.Benchmark;
-import com.google.common.base.Function;
-import com.google.common.base.Functions;
import com.google.common.collect.MapMaker;
import java.util.Map;
@@ -33,15 +31,6 @@ public class MapMakerComparisonBenchmark {
private static final String TEST_KEY = "test key";
private static final String TEST_VALUE = "test value";
- private static final Function<Object, Object> IDENTITY = Functions.identity();
-
- // Loading/computing versions:
- private final Map<Object, Object> computingMap = new MapMaker().makeComputingMap(IDENTITY);
- private final LoadingCache<Object, Object> loadingCache =
- CacheBuilder.newBuilder().recordStats().build(CacheLoader.from(IDENTITY));
- private final LoadingCache<Object, Object> loadingCacheNoStats =
- CacheBuilder.newBuilder().build(CacheLoader.from(IDENTITY));
-
// Non-loading versions:
private final Map<Object, Object> map = new MapMaker().makeMap(); // Returns ConcurrentHashMap
private final Cache<Object, Object> cache = CacheBuilder.newBuilder().recordStats().build();
@@ -54,24 +43,6 @@ public class MapMakerComparisonBenchmark {
cacheNoStats.put(TEST_KEY, TEST_VALUE);
}
- @Benchmark void computingMapMaker(int rep) {
- for (int i = 0; i < rep; i++) {
- computingMap.get(TEST_KEY);
- }
- }
-
- @Benchmark void loadingCacheBuilder_stats(int rep) {
- for (int i = 0; i < rep; i++) {
- loadingCache.getUnchecked(TEST_KEY);
- }
- }
-
- @Benchmark void loadingCacheBuilder(int rep) {
- for (int i = 0; i < rep; i++) {
- loadingCacheNoStats.getUnchecked(TEST_KEY);
- }
- }
-
@Benchmark void concurrentHashMap(int rep) {
for (int i = 0; i < rep; i++) {
map.get(TEST_KEY);
diff --git a/guava-tests/benchmark/com/google/common/collect/MultipleSetContainsBenchmark.java b/guava-tests/benchmark/com/google/common/collect/MultipleSetContainsBenchmark.java
new file mode 100644
index 0000000..c0063ad
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/collect/MultipleSetContainsBenchmark.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.collect;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+import com.google.caliper.api.SkipThisScenarioException;
+
+import java.util.Random;
+
+/**
+ * A benchmark that tries invoking {@code Set.contains} on many different sets.
+ */
+public class MultipleSetContainsBenchmark {
+
+ @Param({"0.0", "0.1", "0.7", "1.0"})
+ double emptySetProportion;
+
+ @Param({"0.0", "0.1", "0.7", "1.0"})
+ double singletonSetProportion;
+
+ @Param({"0.2", "0.8"})
+ double hitRate;
+
+ static final Object PRESENT = new Object();
+ static final Object ABSENT = new Object();
+
+ @SuppressWarnings("unchecked")
+ private final ImmutableSet<Object>[] sets = new ImmutableSet[0x1000];
+
+ private final Object[] queries = new Object[0x1000];
+
+ @BeforeExperiment void setUp() {
+ if (emptySetProportion + singletonSetProportion > 1.01) {
+ throw new SkipThisScenarioException();
+ }
+
+ Random rng = new Random();
+ for (int i = 0; i < 0x1000; i++) {
+ double setSize = rng.nextDouble();
+ if (setSize < emptySetProportion) {
+ sets[i] = ImmutableSet.of();
+ } else if (setSize < emptySetProportion + singletonSetProportion) {
+ sets[i] = ImmutableSet.of(PRESENT);
+ } else {
+ sets[i] = ImmutableSet.of(PRESENT, new Object());
+ }
+
+ if (rng.nextDouble() < hitRate) {
+ queries[i] = PRESENT;
+ } else {
+ queries[i] = ABSENT;
+ }
+ }
+ }
+
+ @Benchmark public boolean contains(int reps) {
+ ImmutableSet<Object>[] sets = this.sets;
+ Object[] queries = this.queries;
+ boolean result = false;
+ for (int i = 0; i < reps; i++) {
+ int j = i & 0xFFF;
+ result ^= sets[j].contains(queries[j]);
+ }
+ return result;
+ }
+
+}
diff --git a/guava-tests/benchmark/com/google/common/hash/ChecksumBenchmark.java b/guava-tests/benchmark/com/google/common/hash/ChecksumBenchmark.java
index b8e5d73..28d75fa 100644
--- a/guava-tests/benchmark/com/google/common/hash/ChecksumBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/hash/ChecksumBenchmark.java
@@ -59,7 +59,7 @@ public class ChecksumBenchmark {
for (int i = 0; i < reps; i++) {
CRC32 checksum = new CRC32();
checksum.update(testBytes);
- result ^= checksum.getValue();
+ result = (byte) (result ^ checksum.getValue());
}
return result;
}
@@ -75,7 +75,7 @@ public class ChecksumBenchmark {
for (int i = 0; i < reps; i++) {
Adler32 checksum = new Adler32();
checksum.update(testBytes);
- result ^= checksum.getValue();
+ result = (byte) (result ^ checksum.getValue());
}
return result;
}
diff --git a/guava-tests/benchmark/com/google/common/hash/HashCodeBenchmark.java b/guava-tests/benchmark/com/google/common/hash/HashCodeBenchmark.java
new file mode 100644
index 0000000..78fd17c
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/hash/HashCodeBenchmark.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.hash;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Benchmarks for comparing the various {@link HashCode#equals} methods.
+ *
+ * <p>Parameters for the benchmark are:
+ * <ul>
+ * <li>size: the length of the byte array to hash
+ * <li>whereToDiffer: where in the array the bytes should differ
+ * <li>equalsImpl: which implementation of array equality to use
+ * </ul>
+ *
+ * <p><b>Important note:</b> the primary goal of this benchmark is to ensure that varying {@code
+ * whereToDiffer} produces no observable change in performance. We want to make sure that the
+ * array equals implementation is *not* short-circuiting to prevent timing-based attacks. Being
+ * fast is only a secondary goal.
+ *
+ * @author Kurt Alfred Kluever
+ */
+public class HashCodeBenchmark {
+
+ // Use a statically configured random instance for all of the benchmarks
+ private static final Random random = new Random(42);
+
+ @Param({"1000", "100000"})
+ private int size;
+
+ @Param WhereToDiffer whereToDiffer;
+
+ @Param EqualsImplementation equalsImpl;
+
+ private enum WhereToDiffer {
+ ONE_PERCENT_IN,
+ LAST_BYTE,
+ NOT_AT_ALL;
+ }
+
+ private enum EqualsImplementation {
+ ANDING_BOOLEANS {
+ @Override boolean doEquals(byte[] a, byte[] b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ boolean areEqual = true;
+ for (int i = 0; i < a.length; i++) {
+ areEqual &= (a[i] == b[i]);
+ }
+ return areEqual;
+ }
+ },
+ XORING_TO_BYTE {
+ @Override boolean doEquals(byte[] a, byte[] b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ byte result = 0;
+ for (int i = 0; i < a.length; i++) {
+ result = (byte) (result | a[i] ^ b[i]);
+ }
+ return (result == 0);
+ }
+ },
+ XORING_TO_INT {
+ @Override boolean doEquals(byte[] a, byte[] b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ int result = 0;
+ for (int i = 0; i < a.length; i++) {
+ result |= a[i] ^ b[i];
+ }
+ return (result == 0);
+ }
+ },
+ MESSAGE_DIGEST_IS_EQUAL {
+ @Override boolean doEquals(byte[] a, byte[] b) {
+ return MessageDigest.isEqual(a, b);
+ }
+ },
+ ARRAYS_EQUALS {
+ @Override boolean doEquals(byte[] a, byte[] b) {
+ return Arrays.equals(a, b);
+ }
+ };
+
+ abstract boolean doEquals(byte[] a, byte[] b);
+ }
+
+ private byte[] testBytesA;
+ private byte[] testBytesB;
+
+ @BeforeExperiment void setUp() {
+ testBytesA = new byte[size];
+ random.nextBytes(testBytesA);
+ testBytesB = Arrays.copyOf(testBytesA, size);
+ int indexToDifferAt = -1;
+ switch (whereToDiffer) {
+ case ONE_PERCENT_IN:
+ indexToDifferAt = (int) (size * 0.01);
+ break;
+ case LAST_BYTE:
+ indexToDifferAt = size - 1;
+ break;
+ case NOT_AT_ALL:
+ }
+ if (indexToDifferAt != -1) {
+ testBytesA[indexToDifferAt] = (byte) (testBytesB[indexToDifferAt] - 1);
+ }
+ }
+
+ @Benchmark boolean hashFunction(int reps) {
+ boolean result = true;
+ for (int i = 0; i < reps; i++) {
+ result ^= equalsImpl.doEquals(testBytesA, testBytesB);
+ }
+ return result;
+ }
+}
diff --git a/guava-tests/benchmark/com/google/common/hash/HashFunctionBenchmark.java b/guava-tests/benchmark/com/google/common/hash/HashFunctionBenchmark.java
index faeaee6..dbabd33 100644
--- a/guava-tests/benchmark/com/google/common/hash/HashFunctionBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/hash/HashFunctionBenchmark.java
@@ -19,7 +19,6 @@ package com.google.common.hash;
import com.google.caliper.BeforeExperiment;
import com.google.caliper.Benchmark;
import com.google.caliper.Param;
-import com.google.common.hash.HashFunction;
import java.util.Random;
@@ -59,4 +58,13 @@ public class HashFunctionBenchmark {
}
return result;
}
+
+ @Benchmark int hashFunctionWithOffset(int reps) {
+ HashFunction hashFunction = hashFunctionEnum.getHashFunction();
+ int result = 37;
+ for (int i = 0; i < reps; i++) {
+ result ^= hashFunction.hashBytes(testBytes, 1, testBytes.length - 1).asBytes()[0];
+ }
+ return result;
+ }
}
diff --git a/guava-tests/benchmark/com/google/common/hash/MessageDigestAlgorithmBenchmark.java b/guava-tests/benchmark/com/google/common/hash/MessageDigestAlgorithmBenchmark.java
index e45d582..ff80e96 100644
--- a/guava-tests/benchmark/com/google/common/hash/MessageDigestAlgorithmBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/hash/MessageDigestAlgorithmBenchmark.java
@@ -64,6 +64,7 @@ public class MessageDigestAlgorithmBenchmark {
MD5("MD5", Hashing.md5()),
SHA_1("SHA-1", Hashing.sha1()),
SHA_256("SHA-256", Hashing.sha256()),
+ SHA_384("SHA-384", Hashing.sha384()),
SHA_512("SHA-512", Hashing.sha512());
private final String algorithmName;
diff --git a/guava-tests/benchmark/com/google/common/hash/MessageDigestCreationBenchmark.java b/guava-tests/benchmark/com/google/common/hash/MessageDigestCreationBenchmark.java
index a35b424..22d6d85 100644
--- a/guava-tests/benchmark/com/google/common/hash/MessageDigestCreationBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/hash/MessageDigestCreationBenchmark.java
@@ -29,7 +29,7 @@ import java.security.MessageDigest;
*/
public class MessageDigestCreationBenchmark {
- @Param({"MD5", "SHA-1", "SHA-256", "SHA-512"})
+ @Param({"MD5", "SHA-1", "SHA-256", "SHA-384", "SHA-512"})
private String algorithm;
private MessageDigest md;
diff --git a/guava-tests/benchmark/com/google/common/io/BaseEncodingBenchmark.java b/guava-tests/benchmark/com/google/common/io/BaseEncodingBenchmark.java
new file mode 100644
index 0000000..5131676
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/io/BaseEncodingBenchmark.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.common.io;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Random;
+
+/**
+ * Benchmark for {@code BaseEncoding} performance.
+ */
+public class BaseEncodingBenchmark {
+ private static final int INPUTS_COUNT = 0x1000;
+ private static final int INPUTS_MASK = 0xFFF;
+
+ enum EncodingOption {
+ BASE64(BaseEncoding.base64()),
+ BASE64_URL(BaseEncoding.base64Url()),
+ BASE32(BaseEncoding.base32()),
+ BASE32_HEX(BaseEncoding.base32Hex()),
+ BASE16(BaseEncoding.base16());
+
+ final BaseEncoding encoding;
+
+ EncodingOption(BaseEncoding encoding) {
+ this.encoding = encoding;
+ }
+ }
+
+ @Param
+ EncodingOption encoding;
+
+ @Param({"10", "100", "10000"})
+ int n;
+
+ private final byte[][] encodingInputs = new byte[INPUTS_COUNT][];
+ private final String[] decodingInputs = new String[INPUTS_COUNT];
+
+ @BeforeExperiment
+ public void setUp() {
+ Random rng = new Random();
+ for (int i = 0; i < encodingInputs.length; i++) {
+ encodingInputs[i] = new byte[n];
+ rng.nextBytes(encodingInputs[i]);
+ decodingInputs[i] = encoding.encoding.encode(encodingInputs[i]);
+ }
+ }
+
+ @Benchmark public int encode(int reps) {
+ int tmp = 0;
+ for (int i = 0; i < reps; i++) {
+ tmp += System.identityHashCode(encoding.encoding.encode(encodingInputs[i & INPUTS_MASK]));
+ }
+ return tmp;
+ }
+
+ @Benchmark public int decode(int reps) {
+ int tmp = 0;
+ for (int i = 0; i < reps; i++) {
+ tmp += System.identityHashCode(encoding.encoding.decode(decodingInputs[i & INPUTS_MASK]));
+ }
+ return tmp;
+ }
+
+ @Benchmark public int encodingStream(int reps) throws IOException {
+ int tmp = 0;
+ for (int i = 0; i < reps; i++) {
+ StringWriter target = new StringWriter(2 * n);
+ OutputStream encodingStream = encoding.encoding.encodingStream(target);
+ encodingStream.write(encodingInputs[i & INPUTS_MASK]);
+ encodingStream.close();
+ tmp += target.getBuffer().length();
+ }
+ return tmp;
+ }
+
+ @Benchmark public int decodingStream(int reps) throws IOException {
+ int tmp = 0;
+ byte[] target = new byte[n];
+ for (int i = 0; i < reps; i++) {
+ StringReader source = new StringReader(decodingInputs[i & INPUTS_MASK]);
+ InputStream decodingStream = encoding.encoding.decodingStream(source);
+ decodingStream.read(target);
+ decodingStream.close();
+ tmp += target[0];
+ }
+ return tmp;
+ }
+}
diff --git a/guava-tests/benchmark/com/google/common/util/concurrent/AbstractFutureFootprintBenchmark.java b/guava-tests/benchmark/com/google/common/util/concurrent/AbstractFutureFootprintBenchmark.java
new file mode 100644
index 0000000..3c9fac5
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/util/concurrent/AbstractFutureFootprintBenchmark.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Param;
+import com.google.caliper.api.Footprint;
+import com.google.caliper.api.SkipThisScenarioException;
+import com.google.common.util.concurrent.AbstractFutureBenchmarks.Facade;
+import com.google.common.util.concurrent.AbstractFutureBenchmarks.Impl;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+/**
+ * Measures the size of AbstractFuture implementations.
+ */
+public class AbstractFutureFootprintBenchmark {
+
+ enum State { NOT_DONE, FINISHED, CANCELLED, FAILED}
+
+ @Param State state;
+ @Param Impl impl;
+ @Param({"0", "1", "5", "10"}) int numListeners;
+ @Param({"0", "1", "5", "10"}) int numThreads;
+
+ private final Set<Thread> blockedThreads = new HashSet<Thread>();
+
+ @BeforeExperiment void setUp() throws Exception {
+ if (state != State.NOT_DONE && (numListeners != 0 || numThreads != 0)) {
+ throw new SkipThisScenarioException();
+ }
+ }
+
+ // This exclusion doesn't exclude the TOMBSTONE objects we set. So 'done' NEW futures will look
+ // larger than they are.
+ @Footprint(exclude = {Runnable.class, Executor.class, Thread.class, Exception.class})
+ public Object measureSize() {
+ for (Thread thread : blockedThreads) {
+ thread.interrupt();
+ }
+ blockedThreads.clear();
+ final Facade<Object> f = impl.newFacade();
+ for (int i = 0; i < numThreads; i++) {
+ Thread thread = new Thread() {
+ @Override public void run() {
+ try {
+ f.get();
+ } catch (Throwable expected) {}
+ }
+ };
+ thread.start();
+ blockedThreads.add(thread);
+ }
+ for (int i = 0; i < numListeners; i++) {
+ f.addListener(Runnables.doNothing(), directExecutor());
+ }
+ for (Thread thread : blockedThreads) {
+ AbstractFutureBenchmarks.awaitWaiting(thread);
+ }
+ switch (state) {
+ case NOT_DONE:
+ break;
+ case FINISHED:
+ f.set(null);
+ break;
+ case CANCELLED:
+ f.cancel(false);
+ break;
+ case FAILED:
+ f.setException(new Exception());
+ break;
+ default:
+ throw new AssertionError();
+ }
+ return f;
+ }
+}
diff --git a/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java b/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java
index 4e86043..9cfc814 100644
--- a/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java
+++ b/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java
@@ -26,12 +26,12 @@ import com.google.caliper.api.Footprint;
import com.google.caliper.api.VmOptions;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.AbstractFutureBenchmarks.OldAbstractFuture;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -44,7 +44,7 @@ import javax.annotation.concurrent.GuardedBy;
/**
* Benchmarks for {@link ExecutionList}.
*/
- at VmOptions({"-Xms3g", "-Xmx3g"})
+ at VmOptions({"-Xms8g", "-Xmx8g"})
public class ExecutionListBenchmark {
private static final int NUM_THREADS = 10; // make a param?
@@ -55,7 +55,7 @@ public class ExecutionListBenchmark {
/** Returns the underlying implementation, useful for the Footprint benchmark. */
Object getImpl();
}
-
+
enum Impl {
NEW {
@Override ExecutionListWrapper newExecutionList() {
@@ -68,7 +68,7 @@ public class ExecutionListBenchmark {
@Override public void execute() {
list.execute();
}
-
+
@Override public Object getImpl() {
return list;
}
@@ -86,7 +86,7 @@ public class ExecutionListBenchmark {
@Override public void execute() {
list.execute();
}
-
+
@Override public Object getImpl() {
return list;
}
@@ -104,7 +104,7 @@ public class ExecutionListBenchmark {
@Override public void execute() {
list.execute();
}
-
+
@Override public Object getImpl() {
return list;
}
@@ -122,7 +122,7 @@ public class ExecutionListBenchmark {
@Override public void execute() {
list.execute();
}
-
+
@Override public Object getImpl() {
return list;
}
@@ -140,49 +140,87 @@ public class ExecutionListBenchmark {
@Override public void execute() {
list.execute();
}
-
+
@Override public Object getImpl() {
return list;
}
};
}
+ },
+ ABSTRACT_FUTURE {
+ @Override ExecutionListWrapper newExecutionList() {
+ return new ExecutionListWrapper() {
+ final AbstractFuture<?> future = new AbstractFuture<Object>() {};
+ @Override public void add(Runnable runnable, Executor executor) {
+ future.addListener(runnable, executor);
+ }
+
+ @Override public void execute() {
+ future.set(null);
+ }
+
+ @Override public Object getImpl() {
+ return future;
+ }
+ };
+ }
+ },
+ OLD_ABSTRACT_FUTURE {
+ @Override ExecutionListWrapper newExecutionList() {
+ return new ExecutionListWrapper() {
+ final OldAbstractFuture<Object> future = new OldAbstractFuture<Object>() {};
+ @Override public void add(Runnable runnable, Executor executor) {
+ future.addListener(runnable, executor);
+ }
+
+ @Override public void execute() {
+ future.set(null);
+ }
+
+ @Override public Object getImpl() {
+ return future;
+ }
+ };
+ }
};
abstract ExecutionListWrapper newExecutionList();
}
-
- private ExecutorService executorService;
+
+ private ThreadPoolExecutor executorService;
private CountDownLatch listenerLatch;
private ExecutionListWrapper list;
-
+
@Param Impl impl;
@Param({"1", "5", "10"}) int numListeners;
-
+
private final Runnable listener = new Runnable() {
@Override public void run() {
listenerLatch.countDown();
}
};
-
+
@BeforeExperiment void setUp() throws Exception {
- executorService = new ThreadPoolExecutor(NUM_THREADS,
- NUM_THREADS,
- Long.MAX_VALUE,
- TimeUnit.SECONDS,
+ executorService = new ThreadPoolExecutor(NUM_THREADS,
+ NUM_THREADS,
+ Long.MAX_VALUE,
+ TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(1000));
+ executorService.prestartAllCoreThreads();
final AtomicInteger integer = new AtomicInteger();
- // Execute a bunch of tasks to ensure that our threads are allocated and hot
+ // Execute a bunch of tasks to ensure that our threads are allocated and hot
for (int i = 0; i < NUM_THREADS * 10; i++) {
executorService.submit(new Runnable() {
@Override public void run() {
integer.getAndIncrement();
- }});
+ }
+ });
}
}
-
+
@AfterExperiment void tearDown() throws Exception {
executorService.shutdown();
}
-
+
@Footprint(exclude = {Runnable.class, Executor.class})
public Object measureSize() {
list = impl.newExecutionList();
@@ -191,7 +229,7 @@ public class ExecutionListBenchmark {
}
return list.getImpl();
}
-
+
@Benchmark int addThenExecute_singleThreaded(int reps) {
int returnValue = 0;
for (int i = 0; i < reps; i++) {
@@ -206,7 +244,7 @@ public class ExecutionListBenchmark {
}
return returnValue;
}
-
+
@Benchmark int executeThenAdd_singleThreaded(int reps) {
int returnValue = 0;
for (int i = 0; i < reps; i++) {
@@ -221,13 +259,13 @@ public class ExecutionListBenchmark {
}
return returnValue;
}
-
+
private final Runnable executeTask = new Runnable() {
@Override public void run() {
list.execute();
}
};
-
+
@Benchmark int addThenExecute_multiThreaded(final int reps) throws InterruptedException {
Runnable addTask = new Runnable() {
@Override public void run() {
@@ -244,12 +282,12 @@ public class ExecutionListBenchmark {
executorService.submit(addTask);
}
executorService.submit(executeTask);
- returnValue = (int) listenerLatch.getCount();
+ returnValue += (int) listenerLatch.getCount();
listenerLatch.await();
}
return returnValue;
}
-
+
@Benchmark int executeThenAdd_multiThreaded(final int reps) throws InterruptedException {
Runnable addTask = new Runnable() {
@Override public void run() {
@@ -266,12 +304,12 @@ public class ExecutionListBenchmark {
for (int j = 0; j < NUM_THREADS; j++) {
executorService.submit(addTask);
}
- returnValue = (int) listenerLatch.getCount();
+ returnValue += (int) listenerLatch.getCount();
listenerLatch.await();
}
return returnValue;
}
-
+
// This is the old implementation of ExecutionList using a LinkedList.
private static final class OldExecutionList {
static final Logger log = Logger.getLogger(OldExecutionList.class.getName());
@@ -389,7 +427,7 @@ public class ExecutionListBenchmark {
}
}
}
-
+
// A version of the ExecutionList that uses an explicit tail pointer to keep the nodes in order
// rather than flipping the stack in execute().
private static final class NewExecutionListQueue {
@@ -459,14 +497,14 @@ public class ExecutionListBenchmark {
}
}
}
-
+
// A version of the list that uses compare and swap to manage the stack without locks.
private static final class ExecutionListCAS {
static final Logger log = Logger.getLogger(ExecutionListCAS.class.getName());
private static final sun.misc.Unsafe UNSAFE;
private static final long HEAD_OFFSET;
-
+
/**
* A special instance of {@link RunnableExecutorPair} that is used as a sentinel value for the
* bottom of the stack.
@@ -477,13 +515,13 @@ public class ExecutionListBenchmark {
try {
UNSAFE = getUnsafe();
HEAD_OFFSET = UNSAFE.objectFieldOffset(ExecutionListCAS.class.getDeclaredField("head"));
- } catch (Exception ex) {
- throw new Error(ex);
+ } catch (Exception ex) {
+ throw new Error(ex);
}
}
-
+
/**
- * TODO(user): This was copied verbatim from Striped64.java... standardize this?
+ * TODO(lukes): This was copied verbatim from Striped64.java... standardize this?
*/
private static sun.misc.Unsafe getUnsafe() {
try {
@@ -512,13 +550,13 @@ public class ExecutionListBenchmark {
public void add(Runnable runnable, Executor executor) {
Preconditions.checkNotNull(runnable, "Runnable was null.");
Preconditions.checkNotNull(executor, "Executor was null.");
-
+
RunnableExecutorPair newHead = new RunnableExecutorPair(runnable, executor);
RunnableExecutorPair oldHead;
do {
oldHead = head;
if (oldHead == null) {
- // If runnables == null then execute() has been called so we should just execute our
+ // If runnables == null then execute() has been called so we should just execute our
// listener immediately.
newHead.execute();
return;
@@ -538,7 +576,7 @@ public class ExecutionListBenchmark {
}
// try to swap null into head.
} while (!UNSAFE.compareAndSwapObject(this, HEAD_OFFSET, stack, null));
-
+
RunnableExecutorPair reversedStack = null;
while (stack != NULL_PAIR) {
RunnableExecutorPair head = stack;
diff --git a/guava-tests/benchmark/com/google/common/util/concurrent/FuturesCombineBenchmark.java b/guava-tests/benchmark/com/google/common/util/concurrent/FuturesCombineBenchmark.java
deleted file mode 100644
index 60b5e5c..0000000
--- a/guava-tests/benchmark/com/google/common/util/concurrent/FuturesCombineBenchmark.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2014 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.util.concurrent;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.caliper.Benchmark;
-import com.google.caliper.Param;
-import com.google.caliper.api.VmOptions;
-import com.google.common.collect.ImmutableList;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
-
-/**
- * A benchmark for {@link Futures#combine}
- */
- at VmOptions({"-Xms12g", "-Xmx12g", "-d64"})
-public class FuturesCombineBenchmark {
-
- enum Impl {
- OLD {
- @Override <V> ListenableFuture<V> combine(final Callable<V> combiner, Executor executor,
- Iterable<? extends ListenableFuture<?>> futures) {
- ListenableFuture<?> trigger = Futures.successfulAsList(futures);
- checkNotNull(combiner);
- checkNotNull(trigger);
- return Futures.transform(trigger, new AsyncFunction<Object, V>() {
- @Override public ListenableFuture<V> apply(Object arg) throws Exception {
- try {
- return Futures.immediateFuture(combiner.call());
- } catch (CancellationException e) {
- return Futures.immediateCancelledFuture();
- } catch (ExecutionException e) {
- return Futures.immediateFailedFuture(e.getCause()); // OK to rethrow on Error
- }
- }
- }, executor);
- }
- },
- NEW {
- @Override
- <V> ListenableFuture<V> combine(Callable<V> combiner, final Executor executor,
- Iterable<? extends ListenableFuture<?>> futures) {
- return Futures.combine(combiner, executor, futures);
- }
- };
-
- abstract <V> ListenableFuture<V> combine(
- Callable<V> combiner, Executor executor,
- Iterable<? extends ListenableFuture<?>> futures);
- }
-
- private static final Executor INLINE_EXECUTOR = new Executor() {
- @Override public void execute(Runnable command) {
- command.run();
- }
- };
-
- @Param Impl impl;
- @Param({"1", "5", "10"}) int numInputs;
-
- @Benchmark int timeDoneSuccesfulFutures(int reps) throws Exception {
- ImmutableList.Builder<ListenableFuture<?>> futuresBuilder = ImmutableList.builder();
- for (int i = 0; i < numInputs; i++) {
- futuresBuilder.add(Futures.immediateFuture(i));
- }
- ImmutableList<ListenableFuture<?>> futures = futuresBuilder.build();
- Impl impl = this.impl;
- Callable<Integer> callable = Callables.returning(12);
- int sum = 0;
- for (int i = 0; i < reps; i++) {
- sum += impl.combine(callable, INLINE_EXECUTOR, futures).get();
- }
- return sum;
- }
-
- @Benchmark int timeDoneFailedFutures(int reps) throws Exception {
- ImmutableList.Builder<ListenableFuture<?>> futuresBuilder = ImmutableList.builder();
- for (int i = 0; i < numInputs; i++) {
- futuresBuilder.add(Futures.immediateFailedFuture(new Exception("boom")));
- }
- ImmutableList<ListenableFuture<?>> futures = futuresBuilder.build();
- Impl impl = this.impl;
- Callable<Integer> callable = Callables.returning(12);
- int sum = 0;
- for (int i = 0; i < reps; i++) {
- sum += impl.combine(callable, INLINE_EXECUTOR, futures).get();
- }
- return sum;
- }
-
- @Benchmark int timeSuccesfulFutures(int reps) throws Exception {
- Impl impl = this.impl;
- Callable<Integer> callable = Callables.returning(12);
- int sum = 0;
- for (int i = 0; i < reps; i++) {
- ImmutableList<SettableFuture<Integer>> futures = getSettableFutureList();
- ListenableFuture<Integer> combined = impl.combine(callable, INLINE_EXECUTOR, futures);
- for (SettableFuture<Integer> future : futures) {
- future.set(i);
- }
- sum += combined.get();
- }
- return sum;
- }
-
- @Benchmark int timeFailedFutures(int reps) throws Exception {
- Impl impl = this.impl;
- Callable<Integer> callable = Callables.returning(12);
- int sum = 0;
- Exception throwable = new Exception("boom");
- for (int i = 0; i < reps; i++) {
- ImmutableList<SettableFuture<Integer>> futures = getSettableFutureList();
- ListenableFuture<Integer> combined = impl.combine(callable, INLINE_EXECUTOR, futures);
- for (SettableFuture<Integer> future : futures) {
- future.setException(throwable);
- }
- sum += combined.get();
- }
- return sum;
- }
-
- private ImmutableList<SettableFuture<Integer>> getSettableFutureList() {
- ImmutableList.Builder<SettableFuture<Integer>> futuresBuilder = ImmutableList.builder();
- for (int i = 0; i < numInputs; i++) {
- futuresBuilder.add(SettableFuture.<Integer>create());
- }
- return futuresBuilder.build();
- }
-}
diff --git a/guava-tests/benchmark/com/google/common/util/concurrent/FuturesGetCheckedBenchmark.java b/guava-tests/benchmark/com/google/common/util/concurrent/FuturesGetCheckedBenchmark.java
new file mode 100644
index 0000000..7a7bd21
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/util/concurrent/FuturesGetCheckedBenchmark.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static com.google.common.util.concurrent.FuturesGetChecked.checkExceptionClassValidity;
+import static com.google.common.util.concurrent.FuturesGetChecked.classValueValidator;
+import static com.google.common.util.concurrent.FuturesGetChecked.getChecked;
+import static com.google.common.util.concurrent.FuturesGetChecked.isCheckedException;
+import static com.google.common.util.concurrent.FuturesGetChecked.weakSetValidator;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.FuturesGetChecked.GetCheckedTypeValidator;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.security.GeneralSecurityException;
+import java.security.acl.NotOwnerException;
+import java.util.List;
+import java.util.TooManyListenersException;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeoutException;
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.InvalidPreferencesFormatException;
+import java.util.zip.DataFormatException;
+
+import javax.security.auth.RefreshFailedException;
+
+/**
+ * Microbenchmark for {@link Futures#getChecked}.
+ */
+public class FuturesGetCheckedBenchmark {
+ private enum Validator {
+ NON_CACHING_WITH_CONSTRUCTOR_CHECK(nonCachingWithConstructorCheckValidator()),
+ NON_CACHING_WITHOUT_CONSTRUCTOR_CHECK(nonCachingWithoutConstructorCheckValidator()),
+ WEAK_SET(weakSetValidator()),
+ CLASS_VALUE(classValueValidator());
+
+ final GetCheckedTypeValidator validator;
+
+ private Validator(GetCheckedTypeValidator validator) {
+ this.validator = validator;
+ }
+ }
+
+ private enum Result {
+ SUCCESS(immediateFuture(new Object())),
+ FAILURE(immediateFailedFuture(new Exception()));
+
+ final Future<Object> future;
+
+ private Result(Future<Object> result) {
+ this.future = result;
+ }
+ }
+
+ private enum ExceptionType {
+ CHECKED(IOException.class),
+ UNCHECKED(RuntimeException.class);
+
+ final Class<? extends Exception> exceptionType;
+
+ private ExceptionType(Class<? extends Exception> exceptionType) {
+ this.exceptionType = exceptionType;
+ }
+ }
+
+ private static final ImmutableSet<Class<? extends Exception>> OTHER_EXCEPTION_TYPES =
+ ImmutableSet.of(
+ BackingStoreException.class,
+ BrokenBarrierException.class,
+ CloneNotSupportedException.class,
+ DataFormatException.class,
+ ExecutionException.class,
+ GeneralSecurityException.class,
+ InvalidPreferencesFormatException.class,
+ NotOwnerException.class,
+ RefreshFailedException.class,
+ TimeoutException.class,
+ TooManyListenersException.class,
+ URISyntaxException.class);
+
+ @Param
+ Validator validator;
+ @Param
+ Result result;
+ @Param
+ ExceptionType exceptionType;
+ /**
+ * The number of other exception types in the cache of known-good exceptions and the number of
+ * other {@code ClassValue} entries for the exception type to be tested. This lets us evaluate
+ * whether our solution scales to use with multiple exception types and to whether it is affected
+ * by other {@code ClassValue} users. Some of the benchmarked implementations don't use one or
+ * both of these mechanisms, so they will be unaffected.
+ */
+ @Param({"0", "1", "12"})
+ int otherEntriesInDataStructure;
+
+ final List<ClassValue<?>> retainedReferencesToOtherClassValues = newArrayList();
+
+ @BeforeExperiment
+ void addOtherEntries() throws Exception {
+ GetCheckedTypeValidator validator = this.validator.validator;
+ Class<? extends Exception> exceptionType = this.exceptionType.exceptionType;
+
+ for (Class<? extends Exception> exceptionClass :
+ OTHER_EXCEPTION_TYPES.asList().subList(0, otherEntriesInDataStructure)) {
+ getChecked(validator, immediateFuture(""), exceptionClass);
+ }
+
+ for (int i = 0; i < otherEntriesInDataStructure; i++) {
+ ClassValue<Boolean> classValue =
+ new ClassValue<Boolean>() {
+ @Override
+ protected Boolean computeValue(Class<?> type) {
+ return true;
+ }
+ };
+ classValue.get(exceptionType);
+ retainedReferencesToOtherClassValues.add(classValue);
+ }
+ }
+
+ @Benchmark
+ int benchmarkGetChecked(int reps) {
+ int tmp = 0;
+ GetCheckedTypeValidator validator = this.validator.validator;
+ Future<Object> future = this.result.future;
+ Class<? extends Exception> exceptionType = this.exceptionType.exceptionType;
+ for (int i = 0; i < reps; ++i) {
+ try {
+ tmp += getChecked(validator, future, exceptionType).hashCode();
+ } catch (Exception e) {
+ tmp += e.hashCode();
+ }
+ }
+ return tmp;
+ }
+
+ private static GetCheckedTypeValidator nonCachingWithoutConstructorCheckValidator() {
+ return NonCachingWithoutConstructorCheckValidator.INSTANCE;
+ }
+
+ private enum NonCachingWithoutConstructorCheckValidator implements GetCheckedTypeValidator {
+ INSTANCE;
+
+ @Override
+ public void validateClass(Class<? extends Exception> exceptionClass) {
+ checkArgument(isCheckedException(exceptionClass),
+ "Futures.getChecked exception type (%s) must not be a RuntimeException", exceptionClass);
+ }
+ }
+
+ private static GetCheckedTypeValidator nonCachingWithConstructorCheckValidator() {
+ return NonCachingWithConstructorCheckValidator.INSTANCE;
+ }
+
+ private enum NonCachingWithConstructorCheckValidator implements GetCheckedTypeValidator {
+ INSTANCE;
+
+ @Override
+ public void validateClass(Class<? extends Exception> exceptionClass) {
+ checkExceptionClassValidity(exceptionClass);
+ }
+ }
+}
diff --git a/guava-tests/benchmark/com/google/common/util/concurrent/SingleThreadAbstractFutureBenchmark.java b/guava-tests/benchmark/com/google/common/util/concurrent/SingleThreadAbstractFutureBenchmark.java
new file mode 100644
index 0000000..2357b9d
--- /dev/null
+++ b/guava-tests/benchmark/com/google/common/util/concurrent/SingleThreadAbstractFutureBenchmark.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+import com.google.caliper.api.VmOptions;
+import com.google.common.util.concurrent.AbstractFutureBenchmarks.Facade;
+import com.google.common.util.concurrent.AbstractFutureBenchmarks.Impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A benchmark that times how long it takes to add a given number of
+ */
+ at VmOptions({"-Xms8g", "-Xmx8g"})
+public class SingleThreadAbstractFutureBenchmark {
+ @Param Impl impl;
+
+ private final Exception exception = new Exception();
+ private Facade<?> notDoneFuture;
+
+ @BeforeExperiment void setUp() throws Exception {
+ notDoneFuture = impl.newFacade();
+ }
+
+ @Benchmark public long timeComplete_Normal(int reps) throws Exception {
+ long r = 0;
+ List<Facade<Integer>> list = new ArrayList<Facade<Integer>>(reps);
+ for (int i = 0; i < reps; i++) {
+ final Facade<Integer> localFuture = impl.newFacade();
+ list.add(localFuture);
+ localFuture.set(i);
+ }
+ for (int i = 0; i < reps; i++) {
+ r += list.get(i).get();
+ }
+ return r;
+ }
+
+ @Benchmark public long timeComplete_Failure(int reps) throws Exception {
+ long r = 0;
+ List<Facade<Integer>> list = new ArrayList<Facade<Integer>>(reps);
+ for (int i = 0; i < reps; i++) {
+ final Facade<Integer> localFuture = impl.newFacade();
+ list.add(localFuture);
+ localFuture.setException(exception);
+ }
+ for (int i = 0; i < reps; i++) {
+ Facade<Integer> facade = list.get(i);
+ try {
+ facade.get();
+ r++;
+ } catch (ExecutionException e) {
+ r += 2;
+ }
+ }
+ return r;
+ }
+
+ @Benchmark public long timeComplete_Cancel(int reps) throws Exception {
+ long r = 0;
+ List<Facade<Integer>> list = new ArrayList<Facade<Integer>>(reps);
+ for (int i = 0; i < reps; i++) {
+ final Facade<Integer> localFuture = impl.newFacade();
+ list.add(localFuture);
+ localFuture.cancel(false);
+ }
+ for (int i = 0; i < reps; i++) {
+ Facade<Integer> facade = list.get(i);
+ try {
+ facade.get();
+ r++;
+ } catch (CancellationException e) {
+ r += 2;
+ }
+ }
+ return r;
+ }
+
+ @Benchmark public long timeGetWith0Timeout(long reps) throws Exception {
+ Facade<?> f = notDoneFuture;
+ long r = 0;
+ for (int i = 0; i < reps; i++) {
+ try {
+ f.get(0, TimeUnit.SECONDS);
+ r += 1;
+ } catch (TimeoutException e) {
+ r += 2;
+ }
+ }
+ return r;
+ }
+ @Benchmark public long timeGetWithSmallTimeout(long reps) throws Exception {
+ Facade<?> f = notDoneFuture;
+ long r = 0;
+ for (int i = 0; i < reps; i++) {
+ try {
+ f.get(500, TimeUnit.NANOSECONDS);
+ r += 1;
+ } catch (TimeoutException e) {
+ r += 2;
+ }
+ }
+ return r;
+ }
+}
diff --git a/guava-tests/pom.xml b/guava-tests/pom.xml
index ea1e303..dcb6351 100644
--- a/guava-tests/pom.xml
+++ b/guava-tests/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>com.google.guava</groupId>
<artifactId>guava-parent</artifactId>
- <version>18.0</version>
+ <version>19.0</version>
</parent>
<artifactId>guava-tests</artifactId>
<name>Guava Unit Tests</name>
@@ -26,6 +26,10 @@
<artifactId>jsr305</artifactId>
</dependency>
<dependency>
+ <groupId>com.google.errorprone</groupId>
+ <artifactId>error_prone_annotations</artifactId>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
@@ -63,12 +67,18 @@
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <redirectTestOutputToFile>true</redirectTestOutputToFile>
+ <!-- Set max heap for tests. -->
+ <!-- Catch dependencies on the default locale by setting it to hi-IN. -->
+ <argLine>-Xmx1536M -Duser.language=hi -Duser.country=IN</argLine>
+ </configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
- <version>2.3.1</version>
<executions>
<execution>
+ <id>create-test-jar</id>
<goals><goal>test-jar</goal></goals>
</execution>
</executions>
@@ -77,7 +87,6 @@
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
</plugin>
- <!-- TODO(cpovirk): reenable after a matching Caliper snapshot is pushed to Maven Central
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
@@ -95,7 +104,6 @@
</execution>
</executions>
</plugin>
- -->
</plugins>
</build>
</project>
diff --git a/guava-tests/test/com/google/common/base/CharMatcherTest.java b/guava-tests/test/com/google/common/base/CharMatcherTest.java
index 19dad23..228d91e 100644
--- a/guava-tests/test/com/google/common/base/CharMatcherTest.java
+++ b/guava-tests/test/com/google/common/base/CharMatcherTest.java
@@ -16,14 +16,14 @@
package com.google.common.base;
-import static com.google.common.base.CharMatcher.BREAKING_WHITESPACE;
-import static com.google.common.base.CharMatcher.WHITESPACE;
import static com.google.common.base.CharMatcher.anyOf;
+import static com.google.common.base.CharMatcher.breakingWhitespace;
import static com.google.common.base.CharMatcher.forPredicate;
import static com.google.common.base.CharMatcher.inRange;
import static com.google.common.base.CharMatcher.is;
import static com.google.common.base.CharMatcher.isNot;
import static com.google.common.base.CharMatcher.noneOf;
+import static com.google.common.base.CharMatcher.whitespace;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
@@ -51,7 +51,7 @@ public class CharMatcherTest extends TestCase {
public void testStaticNullPointers() throws Exception {
NullPointerTester tester = new NullPointerTester();
tester.testAllPublicStaticMethods(CharMatcher.class);
- tester.testAllPublicInstanceMethods(CharMatcher.ANY);
+ tester.testAllPublicInstanceMethods(CharMatcher.any());
tester.testAllPublicInstanceMethods(CharMatcher.anyOf("abc"));
}
@@ -67,14 +67,14 @@ public class CharMatcherTest extends TestCase {
// we're lucky enough that these do pass, it saves us from having to write
// more excruciating tests! Hooray!
- assertSame(CharMatcher.ANY, CharMatcher.NONE.negate());
- assertSame(CharMatcher.NONE, CharMatcher.ANY.negate());
+ assertSame(CharMatcher.any(), CharMatcher.none().negate());
+ assertSame(CharMatcher.none(), CharMatcher.any().negate());
- assertSame(WHATEVER, CharMatcher.ANY.and(WHATEVER));
- assertSame(CharMatcher.ANY, CharMatcher.ANY.or(WHATEVER));
+ assertSame(WHATEVER, CharMatcher.any().and(WHATEVER));
+ assertSame(CharMatcher.any(), CharMatcher.any().or(WHATEVER));
- assertSame(CharMatcher.NONE, CharMatcher.NONE.and(WHATEVER));
- assertSame(WHATEVER, CharMatcher.NONE.or(WHATEVER));
+ assertSame(CharMatcher.none(), CharMatcher.none().and(WHATEVER));
+ assertSame(WHATEVER, CharMatcher.none().or(WHATEVER));
}
// The rest of the behavior of ANY and DEFAULT will be covered in the tests for
@@ -82,8 +82,8 @@ public class CharMatcherTest extends TestCase {
public void testWhitespaceBreakingWhitespaceSubset() throws Exception {
for (int c = 0; c <= Character.MAX_VALUE; c++) {
- if (BREAKING_WHITESPACE.apply((char) c)) {
- assertTrue(Integer.toHexString(c), WHITESPACE.apply((char) c));
+ if (breakingWhitespace().matches((char) c)) {
+ assertTrue(Integer.toHexString(c), whitespace().matches((char) c));
}
}
}
@@ -95,7 +95,7 @@ public class CharMatcherTest extends TestCase {
public void testJavaIsoControl() {
for (int c = 0; c <= Character.MAX_VALUE; c++) {
assertEquals("" + c, Character.isISOControl(c),
- CharMatcher.JAVA_ISO_CONTROL.matches((char) c));
+ CharMatcher.javaIsoControl().matches((char) c));
}
}
@@ -111,8 +111,8 @@ public class CharMatcherTest extends TestCase {
@GwtIncompatible("java.util.BitSet")
public void testSetBits() {
- doTestSetBits(CharMatcher.ANY);
- doTestSetBits(CharMatcher.NONE);
+ doTestSetBits(CharMatcher.any());
+ doTestSetBits(CharMatcher.none());
doTestSetBits(is('a'));
doTestSetBits(isNot('a'));
doTestSetBits(anyOf(""));
@@ -122,10 +122,10 @@ public class CharMatcherTest extends TestCase {
doTestSetBits(noneOf("CharMatcher"));
doTestSetBits(inRange('n', 'q'));
doTestSetBits(forPredicate(Predicates.equalTo('c')));
- doTestSetBits(CharMatcher.ASCII);
- doTestSetBits(CharMatcher.DIGIT);
- doTestSetBits(CharMatcher.INVISIBLE);
- doTestSetBits(CharMatcher.WHITESPACE);
+ doTestSetBits(CharMatcher.ascii());
+ doTestSetBits(CharMatcher.digit());
+ doTestSetBits(CharMatcher.invisible());
+ doTestSetBits(CharMatcher.whitespace());
doTestSetBits(inRange('A', 'Z').and(inRange('F', 'K').negate()));
}
@@ -139,8 +139,8 @@ public class CharMatcherTest extends TestCase {
}
public void testEmpty() throws Exception {
- doTestEmpty(CharMatcher.ANY);
- doTestEmpty(CharMatcher.NONE);
+ doTestEmpty(CharMatcher.any());
+ doTestEmpty(CharMatcher.none());
doTestEmpty(is('a'));
doTestEmpty(isNot('a'));
doTestEmpty(anyOf(""));
@@ -154,8 +154,8 @@ public class CharMatcherTest extends TestCase {
@GwtIncompatible("NullPointerTester")
public void testNull() throws Exception {
- doTestNull(CharMatcher.ANY);
- doTestNull(CharMatcher.NONE);
+ doTestNull(CharMatcher.any());
+ doTestNull(CharMatcher.none());
doTestNull(is('a'));
doTestNull(isNot('a'));
doTestNull(anyOf(""));
@@ -204,7 +204,7 @@ public class CharMatcherTest extends TestCase {
}
public void testNoMatches() {
- doTestNoMatches(CharMatcher.NONE, "blah");
+ doTestNoMatches(CharMatcher.none(), "blah");
doTestNoMatches(is('a'), "bcde");
doTestNoMatches(isNot('a'), "aaaa");
doTestNoMatches(anyOf(""), "abcd");
@@ -215,10 +215,10 @@ public class CharMatcherTest extends TestCase {
doTestNoMatches(inRange('p', 'x'), "mom");
doTestNoMatches(forPredicate(Predicates.equalTo('c')), "abe");
doTestNoMatches(inRange('A', 'Z').and(inRange('F', 'K').negate()), "F1a");
- doTestNoMatches(CharMatcher.DIGIT, "\tAz()");
- doTestNoMatches(CharMatcher.JAVA_DIGIT, "\tAz()");
- doTestNoMatches(CharMatcher.DIGIT.and(CharMatcher.ASCII), "\tAz()");
- doTestNoMatches(CharMatcher.SINGLE_WIDTH, "\u05bf\u3000");
+ doTestNoMatches(CharMatcher.digit(), "\tAz()");
+ doTestNoMatches(CharMatcher.javaDigit(), "\tAz()");
+ doTestNoMatches(CharMatcher.digit().and(CharMatcher.ascii()), "\tAz()");
+ doTestNoMatches(CharMatcher.singleWidth(), "\u05bf\u3000");
}
private void doTestNoMatches(CharMatcher matcher, String s) {
@@ -233,7 +233,7 @@ public class CharMatcherTest extends TestCase {
}
public void testAllMatches() {
- doTestAllMatches(CharMatcher.ANY, "blah");
+ doTestAllMatches(CharMatcher.any(), "blah");
doTestAllMatches(isNot('a'), "bcde");
doTestAllMatches(is('a'), "aaaa");
doTestAllMatches(noneOf("CharMatcher"), "zxqy");
@@ -242,10 +242,10 @@ public class CharMatcherTest extends TestCase {
doTestAllMatches(anyOf("CharMatcher"), "ChMa");
doTestAllMatches(inRange('m', 'p'), "mom");
doTestAllMatches(forPredicate(Predicates.equalTo('c')), "ccc");
- doTestAllMatches(CharMatcher.DIGIT, "0123456789\u0ED0\u1B59");
- doTestAllMatches(CharMatcher.JAVA_DIGIT, "0123456789");
- doTestAllMatches(CharMatcher.DIGIT.and(CharMatcher.ASCII), "0123456789");
- doTestAllMatches(CharMatcher.SINGLE_WIDTH, "\t0123ABCdef~\u00A0\u2111");
+ doTestAllMatches(CharMatcher.digit(), "0123456789\u0ED0\u1B59");
+ doTestAllMatches(CharMatcher.javaDigit(), "0123456789");
+ doTestAllMatches(CharMatcher.digit().and(CharMatcher.ascii()), "0123456789");
+ doTestAllMatches(CharMatcher.singleWidth(), "\t0123ABCdef~\u00A0\u2111");
}
private void doTestAllMatches(CharMatcher matcher, String s) {
@@ -355,6 +355,7 @@ public class CharMatcherTest extends TestCase {
reallyTestMatchThenNoMatch(matcher.precomputed().negate(), s);
}
+ @SuppressWarnings("deprecation") // intentionally testing apply() method
private void reallyTestOneCharMatch(CharMatcher matcher, String s) {
assertTrue(matcher.matches(s.charAt(0)));
assertTrue(matcher.apply(s.charAt(0)));
@@ -372,6 +373,7 @@ public class CharMatcherTest extends TestCase {
assertEquals(1, matcher.countIn(s));
}
+ @SuppressWarnings("deprecation") // intentionally testing apply() method
private void reallyTestOneCharNoMatch(CharMatcher matcher, String s) {
assertFalse(matcher.matches(s.charAt(0)));
assertFalse(matcher.apply(s.charAt(0)));
@@ -487,14 +489,14 @@ public class CharMatcherTest extends TestCase {
assertSame(inout, anyOf("-").collapseFrom(inout, '_'));
assertSame(inout, anyOf("-#").collapseFrom(inout, '_'));
assertSame(inout, anyOf("-#123").collapseFrom(inout, '_'));
- assertSame(inout, CharMatcher.NONE.collapseFrom(inout, '_'));
+ assertSame(inout, CharMatcher.none().collapseFrom(inout, '_'));
}
public void testCollapse_any() {
- assertEquals("", CharMatcher.ANY.collapseFrom("", '_'));
- assertEquals("_", CharMatcher.ANY.collapseFrom("a", '_'));
- assertEquals("_", CharMatcher.ANY.collapseFrom("ab", '_'));
- assertEquals("_", CharMatcher.ANY.collapseFrom("abcd", '_'));
+ assertEquals("", CharMatcher.any().collapseFrom("", '_'));
+ assertEquals("_", CharMatcher.any().collapseFrom("a", '_'));
+ assertEquals("_", CharMatcher.any().collapseFrom("ab", '_'));
+ assertEquals("_", CharMatcher.any().collapseFrom("abcd", '_'));
}
public void testTrimFrom() {
@@ -652,18 +654,18 @@ public class CharMatcherTest extends TestCase {
// build a precomputed version.
CharMatcher m1 = is('x');
assertSame(m1, m1.precomputed());
- assertSame(m1.toString(), m1.precomputed().toString());
+ assertEquals(m1.toString(), m1.precomputed().toString());
CharMatcher m2 = anyOf("Az");
assertSame(m2, m2.precomputed());
- assertSame(m2.toString(), m2.precomputed().toString());
+ assertEquals(m2.toString(), m2.precomputed().toString());
CharMatcher m3 = inRange('A', 'Z');
assertSame(m3, m3.precomputed());
- assertSame(m3.toString(), m3.precomputed().toString());
+ assertEquals(m3.toString(), m3.precomputed().toString());
- assertSame(CharMatcher.NONE, CharMatcher.NONE.precomputed());
- assertSame(CharMatcher.ANY, CharMatcher.ANY.precomputed());
+ assertSame(CharMatcher.none(), CharMatcher.none().precomputed());
+ assertSame(CharMatcher.any(), CharMatcher.any().precomputed());
}
@GwtIncompatible("java.util.BitSet")
@@ -674,8 +676,8 @@ public class CharMatcherTest extends TestCase {
@GwtIncompatible("java.util.BitSet")
private static BitSet bitSet(char[] chars) {
BitSet tmp = new BitSet();
- for (int i = 0; i < chars.length; i++) {
- tmp.set(chars[i]);
+ for (char c : chars) {
+ tmp.set(c);
}
return tmp;
}
@@ -717,8 +719,8 @@ public class CharMatcherTest extends TestCase {
static void checkExactMatches(CharMatcher m, char[] chars) {
Set<Character> positive = Sets.newHashSetWithExpectedSize(chars.length);
- for (int i = 0; i < chars.length; i++) {
- positive.add(chars[i]);
+ for (char c : chars) {
+ positive.add(c);
}
for (int c = 0; c <= Character.MAX_VALUE; c++) {
assertFalse(positive.contains(new Character((char) c)) ^ m.matches((char) c));
@@ -747,7 +749,7 @@ public class CharMatcherTest extends TestCase {
}
public void testToString() {
- assertToStringWorks("CharMatcher.NONE", CharMatcher.anyOf(""));
+ assertToStringWorks("CharMatcher.none()", CharMatcher.anyOf(""));
assertToStringWorks("CharMatcher.is('\\u0031')", CharMatcher.anyOf("1"));
assertToStringWorks("CharMatcher.isNot('\\u0031')", CharMatcher.isNot('1'));
assertToStringWorks("CharMatcher.anyOf(\"\\u0031\\u0032\")", CharMatcher.anyOf("12"));
diff --git a/guava-tests/test/com/google/common/base/EnumsTest.java b/guava-tests/test/com/google/common/base/EnumsTest.java
index a5faed2..69c65fc 100644
--- a/guava-tests/test/com/google/common/base/EnumsTest.java
+++ b/guava-tests/test/com/google/common/base/EnumsTest.java
@@ -16,6 +16,8 @@
package com.google.common.base;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.ImmutableSet;
@@ -50,27 +52,27 @@ public class EnumsTest extends TestCase {
private enum OtherEnum {}
public void testGetIfPresent() {
- assertEquals(Optional.of(TestEnum.CHEETO), Enums.getIfPresent(TestEnum.class, "CHEETO"));
- assertEquals(Optional.of(TestEnum.HONDA), Enums.getIfPresent(TestEnum.class, "HONDA"));
- assertEquals(Optional.of(TestEnum.POODLE), Enums.getIfPresent(TestEnum.class, "POODLE"));
+ assertThat(Enums.getIfPresent(TestEnum.class, "CHEETO")).hasValue(TestEnum.CHEETO);
+ assertThat(Enums.getIfPresent(TestEnum.class, "HONDA")).hasValue(TestEnum.HONDA);
+ assertThat(Enums.getIfPresent(TestEnum.class, "POODLE")).hasValue(TestEnum.POODLE);
- assertTrue(Enums.getIfPresent(TestEnum.class, "CHEETO").isPresent());
- assertTrue(Enums.getIfPresent(TestEnum.class, "HONDA").isPresent());
- assertTrue(Enums.getIfPresent(TestEnum.class, "POODLE").isPresent());
+ assertThat(Enums.getIfPresent(TestEnum.class, "CHEETO")).isPresent();
+ assertThat(Enums.getIfPresent(TestEnum.class, "HONDA")).isPresent();
+ assertThat(Enums.getIfPresent(TestEnum.class, "POODLE")).isPresent();
- assertEquals(TestEnum.CHEETO, Enums.getIfPresent(TestEnum.class, "CHEETO").get());
- assertEquals(TestEnum.HONDA, Enums.getIfPresent(TestEnum.class, "HONDA").get());
- assertEquals(TestEnum.POODLE, Enums.getIfPresent(TestEnum.class, "POODLE").get());
+ assertThat(Enums.getIfPresent(TestEnum.class, "CHEETO")).hasValue(TestEnum.CHEETO);
+ assertThat(Enums.getIfPresent(TestEnum.class, "HONDA")).hasValue(TestEnum.HONDA);
+ assertThat(Enums.getIfPresent(TestEnum.class, "POODLE")).hasValue(TestEnum.POODLE);
}
public void testGetIfPresent_caseSensitive() {
- assertFalse(Enums.getIfPresent(TestEnum.class, "cHEETO").isPresent());
- assertFalse(Enums.getIfPresent(TestEnum.class, "Honda").isPresent());
- assertFalse(Enums.getIfPresent(TestEnum.class, "poodlE").isPresent());
+ assertThat(Enums.getIfPresent(TestEnum.class, "cHEETO")).isAbsent();
+ assertThat(Enums.getIfPresent(TestEnum.class, "Honda")).isAbsent();
+ assertThat(Enums.getIfPresent(TestEnum.class, "poodlE")).isAbsent();
}
public void testGetIfPresent_whenNoMatchingConstant() {
- assertEquals(Optional.absent(), Enums.getIfPresent(TestEnum.class, "WOMBAT"));
+ assertThat(Enums.getIfPresent(TestEnum.class, "WOMBAT")).isAbsent();
}
@GwtIncompatible("weak references")
@@ -95,12 +97,12 @@ public class EnumsTest extends TestCase {
Set<TestEnum> shadowConstants = new HashSet<TestEnum>();
for (TestEnum constant : TestEnum.values()) {
Optional<TestEnum> result = Enums.getIfPresent(shadowTestEnum, constant.name());
- assertTrue(result.isPresent());
+ assertThat(result).isPresent();
shadowConstants.add(result.get());
}
assertEquals(ImmutableSet.copyOf(shadowTestEnum.getEnumConstants()), shadowConstants);
Optional<TestEnum> result = Enums.getIfPresent(shadowTestEnum, "blibby");
- assertFalse(result.isPresent());
+ assertThat(result).isAbsent();
return new WeakReference<ClassLoader>(shadowLoader);
}
diff --git a/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java b/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java
index de52bbe..60b481a 100644
--- a/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java
+++ b/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java
@@ -107,6 +107,7 @@ public class FinalizableReferenceQueueTest extends TestCase {
};
}
+ @SuppressUnderAndroid // no concept of separate ClassLoaders
public void testDecoupledLoader() {
FinalizableReferenceQueue.DecoupledLoader decoupledLoader =
new FinalizableReferenceQueue.DecoupledLoader() {
@@ -146,6 +147,7 @@ public class FinalizableReferenceQueueTest extends TestCase {
}
}
+ @SuppressUnderAndroid // TODO(cpovirk): How significant is this failure?
public void testGetFinalizerUrl() {
assertNotNull(getClass().getResource("internal/Finalizer.class"));
}
diff --git a/guava-tests/test/com/google/common/base/FunctionsTest.java b/guava-tests/test/com/google/common/base/FunctionsTest.java
index cc7b4f2..90304c5 100644
--- a/guava-tests/test/com/google/common/base/FunctionsTest.java
+++ b/guava-tests/test/com/google/common/base/FunctionsTest.java
@@ -434,6 +434,8 @@ public class FunctionsTest extends TestCase {
}
@GwtIncompatible("reflection")
+ @SuppressUnderAndroid // TODO(cpovirk): ClassNotFoundException: com.google.common.base.Function
+ // (I suspect that this and the other similar failures happen with ArbitraryInstances proxies.)
public void testEqualsAndSerializable() throws Exception {
new ClassSanityTester().forAllPublicStaticMethods(Functions.class).testEqualsAndSerializable();
}
diff --git a/guava-tests/test/com/google/common/base/JoinerTest.java b/guava-tests/test/com/google/common/base/JoinerTest.java
index 32f22e2..c0322f6 100644
--- a/guava-tests/test/com/google/common/base/JoinerTest.java
+++ b/guava-tests/test/com/google/common/base/JoinerTest.java
@@ -58,6 +58,7 @@ public class JoinerTest extends TestCase {
private static final Iterable<Integer> ITERABLE_FOUR_NULLS
= Arrays.asList((Integer) null, null, null, null);
+ @SuppressWarnings("CheckReturnValue")
public void testNoSpecialNullBehavior() {
checkNoOutput(J, ITERABLE_);
checkResult(J, ITERABLE_1, "1");
@@ -237,6 +238,7 @@ public class JoinerTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testMap() {
MapJoiner j = Joiner.on(";").withKeyValueSeparator(":");
assertEquals("", j.join(ImmutableMap.of()));
@@ -259,6 +261,7 @@ public class JoinerTest extends TestCase {
assertEquals("1:2;3:4;5:6", sb.toString());
}
+ @SuppressWarnings("CheckReturnValue")
public void testEntries() {
MapJoiner j = Joiner.on(";").withKeyValueSeparator(":");
assertEquals("", j.join(ImmutableMultimap.of().entries()));
diff --git a/guava-tests/test/com/google/common/base/ObjectsTest.java b/guava-tests/test/com/google/common/base/ObjectsTest.java
index c8de82b..6eb4952 100644
--- a/guava-tests/test/com/google/common/base/ObjectsTest.java
+++ b/guava-tests/test/com/google/common/base/ObjectsTest.java
@@ -70,6 +70,7 @@ public class ObjectsTest extends TestCase {
assertSame(n1, n2);
}
+ @SuppressWarnings("CheckReturnValue")
public void testFirstNonNull_throwsNullPointerException() throws Exception {
try {
Objects.firstNonNull(null, null);
diff --git a/guava-tests/test/com/google/common/base/OptionalTest.java b/guava-tests/test/com/google/common/base/OptionalTest.java
index daa8920..7ad2c19 100644
--- a/guava-tests/test/com/google/common/base/OptionalTest.java
+++ b/guava-tests/test/com/google/common/base/OptionalTest.java
@@ -47,6 +47,7 @@ public final class OptionalTest extends TestCase {
assertEquals("training", Optional.of("training").get());
}
+ @SuppressWarnings("CheckReturnValue")
public void testOf_null() {
try {
Optional.of(null);
@@ -73,6 +74,7 @@ public final class OptionalTest extends TestCase {
assertTrue(Optional.of("training").isPresent());
}
+ @SuppressWarnings("CheckReturnValue")
public void testGet_absent() {
Optional<String> optional = Optional.absent();
try {
@@ -102,6 +104,7 @@ public final class OptionalTest extends TestCase {
assertEquals("fallback", Optional.absent().or(Suppliers.ofInstance("fallback")));
}
+ @SuppressWarnings("CheckReturnValue")
public void testOr_nullSupplier_absent() {
Supplier<Object> nullSupplier = Suppliers.ofInstance(null);
Optional<Object> absentOptional = Optional.absent();
@@ -173,6 +176,7 @@ public final class OptionalTest extends TestCase {
assertEquals(Optional.of("42"), Optional.of(42).transform(Functions.toStringFunction()));
}
+ @SuppressWarnings("CheckReturnValue")
public void testTransform_present_functionReturnsNull() {
try {
Optional.of("a").transform(
@@ -201,6 +205,8 @@ public final class OptionalTest extends TestCase {
public void testEqualsAndHashCode_absent() {
assertEquals(Optional.<String>absent(), Optional.<Integer>absent());
assertEquals(Optional.absent().hashCode(), Optional.absent().hashCode());
+ assertThat(Optional.absent().hashCode())
+ .isNotEqualTo(Optional.of(0).hashCode());
}
public void testEqualsAndHashCode_present() {
@@ -221,7 +227,7 @@ public final class OptionalTest extends TestCase {
public void testPresentInstances_allPresent() {
List<Optional<String>> optionals =
ImmutableList.of(Optional.of("a"), Optional.of("b"), Optional.of("c"));
- assertThat(Optional.presentInstances(optionals)).iteratesAs("a", "b", "c");
+ assertThat(Optional.presentInstances(optionals)).containsExactly("a", "b", "c").inOrder();
}
public void testPresentInstances_allAbsent() {
@@ -233,22 +239,22 @@ public final class OptionalTest extends TestCase {
public void testPresentInstances_somePresent() {
List<Optional<String>> optionals =
ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
- assertThat(Optional.presentInstances(optionals)).iteratesAs("a", "c");
+ assertThat(Optional.presentInstances(optionals)).containsExactly("a", "c").inOrder();
}
public void testPresentInstances_callingIteratorTwice() {
List<Optional<String>> optionals =
ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
Iterable<String> onlyPresent = Optional.presentInstances(optionals);
- assertThat(onlyPresent).iteratesAs("a", "c");
- assertThat(onlyPresent).iteratesAs("a", "c");
+ assertThat(onlyPresent).containsExactly("a", "c").inOrder();
+ assertThat(onlyPresent).containsExactly("a", "c").inOrder();
}
public void testPresentInstances_wildcards() {
List<Optional<? extends Number>> optionals =
ImmutableList.<Optional<? extends Number>>of(Optional.<Double>absent(), Optional.of(2));
Iterable<Number> onlyPresent = Optional.presentInstances(optionals);
- assertThat(onlyPresent).iteratesAs(2);
+ assertThat(onlyPresent).containsExactly(2).inOrder();
}
private static Optional<Integer> getSomeOptionalInt() {
diff --git a/guava-tests/test/com/google/common/base/PreconditionsTest.java b/guava-tests/test/com/google/common/base/PreconditionsTest.java
index df44a3f..e4b1aa8 100644
--- a/guava-tests/test/com/google/common/base/PreconditionsTest.java
+++ b/guava-tests/test/com/google/common/base/PreconditionsTest.java
@@ -16,6 +16,8 @@
package com.google.common.base;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.testing.NullPointerTester;
@@ -61,7 +63,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkArgument(false, null);
fail("no exception thrown");
} catch (IllegalArgumentException expected) {
- assertEquals("null", expected.getMessage());
+ assertThat(expected).hasMessage("null");
}
}
@@ -108,7 +110,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkState(false, null);
fail("no exception thrown");
} catch (IllegalStateException expected) {
- assertEquals("null", expected.getMessage());
+ assertThat(expected).hasMessage("null");
}
}
@@ -190,7 +192,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkElementIndex(-1, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("index (-1) must not be negative", expected.getMessage());
+ assertThat(expected).hasMessage("index (-1) must not be negative");
}
}
@@ -199,8 +201,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkElementIndex(1, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("index (1) must be less than size (1)",
- expected.getMessage());
+ assertThat(expected).hasMessage("index (1) must be less than size (1)");
}
}
@@ -209,7 +210,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkElementIndex(-1, 1, "foo");
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("foo (-1) must not be negative", expected.getMessage());
+ assertThat(expected).hasMessage("foo (-1) must not be negative");
}
}
@@ -218,8 +219,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkElementIndex(1, 1, "foo");
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("foo (1) must be less than size (1)",
- expected.getMessage());
+ assertThat(expected).hasMessage("foo (1) must be less than size (1)");
}
}
@@ -244,7 +244,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndex(-1, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("index (-1) must not be negative", expected.getMessage());
+ assertThat(expected).hasMessage("index (-1) must not be negative");
}
}
@@ -253,8 +253,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndex(2, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("index (2) must not be greater than size (1)",
- expected.getMessage());
+ assertThat(expected).hasMessage("index (2) must not be greater than size (1)");
}
}
@@ -263,7 +262,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndex(-1, 1, "foo");
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("foo (-1) must not be negative", expected.getMessage());
+ assertThat(expected).hasMessage("foo (-1) must not be negative");
}
}
@@ -272,8 +271,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndex(2, 1, "foo");
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("foo (2) must not be greater than size (1)",
- expected.getMessage());
+ assertThat(expected).hasMessage("foo (2) must not be greater than size (1)");
}
}
@@ -297,8 +295,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndexes(-1, 1, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("start index (-1) must not be negative",
- expected.getMessage());
+ assertThat(expected).hasMessage("start index (-1) must not be negative");
}
}
@@ -307,8 +304,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndexes(0, 2, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("end index (2) must not be greater than size (1)",
- expected.getMessage());
+ assertThat(expected).hasMessage("end index (2) must not be greater than size (1)");
}
}
@@ -317,8 +313,7 @@ public class PreconditionsTest extends TestCase {
Preconditions.checkPositionIndexes(1, 0, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
- assertEquals("end index (0) must not be less than start index (1)",
- expected.getMessage());
+ assertThat(expected).hasMessage("end index (0) must not be less than start index (1)");
}
}
@@ -364,10 +359,10 @@ public class PreconditionsTest extends TestCase {
private static final String FORMAT = "I ate %s pies.";
private static void verifySimpleMessage(Exception e) {
- assertEquals("A message", e.getMessage());
+ assertThat(e).hasMessage("A message");
}
private static void verifyComplexMessage(Exception e) {
- assertEquals("I ate 5 pies.", e.getMessage());
+ assertThat(e).hasMessage("I ate 5 pies.");
}
}
diff --git a/guava-tests/test/com/google/common/base/PredicatesTest.java b/guava-tests/test/com/google/common/base/PredicatesTest.java
index 3864dda..4e78b74 100644
--- a/guava-tests/test/com/google/common/base/PredicatesTest.java
+++ b/guava-tests/test/com/google/common/base/PredicatesTest.java
@@ -918,6 +918,7 @@ public class PredicatesTest extends TestCase {
}
@GwtIncompatible("reflection")
+ @SuppressUnderAndroid // TODO(cpovirk): ClassNotFoundException: com.google.common.base.Function
public void testEqualsAndSerializable() throws Exception {
new ClassSanityTester().forAllPublicStaticMethods(Predicates.class).testEqualsAndSerializable();
}
diff --git a/guava-tests/test/com/google/common/base/SplitterTest.java b/guava-tests/test/com/google/common/base/SplitterTest.java
index 88b4c80..49b8082 100644
--- a/guava-tests/test/com/google/common/base/SplitterTest.java
+++ b/guava-tests/test/com/google/common/base/SplitterTest.java
@@ -20,13 +20,11 @@ import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.testing.NullPointerTester;
import junit.framework.TestCase;
-import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -40,6 +38,7 @@ public class SplitterTest extends TestCase {
private static final Splitter COMMA_SPLITTER = Splitter.on(',');
+ @SuppressWarnings("CheckReturnValue")
public void testSplitNullString() {
try {
COMMA_SPLITTER.split(null);
@@ -51,7 +50,7 @@ public class SplitterTest extends TestCase {
public void testCharacterSimpleSplit() {
String simple = "a,b,c";
Iterable<String> letters = COMMA_SPLITTER.split(simple);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
/**
@@ -65,7 +64,7 @@ public class SplitterTest extends TestCase {
public void testCharacterSimpleSplitToList() {
String simple = "a,b,c";
List<String> letters = COMMA_SPLITTER.splitToList(simple);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
public void testToString() {
@@ -77,72 +76,74 @@ public class SplitterTest extends TestCase {
public void testCharacterSimpleSplitWithNoDelimiter() {
String simple = "a,b,c";
Iterable<String> letters = Splitter.on('.').split(simple);
- assertThat(letters).iteratesAs("a,b,c");
+ assertThat(letters).containsExactly("a,b,c").inOrder();
}
public void testCharacterSplitWithDoubleDelimiter() {
String doubled = "a,,b,c";
Iterable<String> letters = COMMA_SPLITTER.split(doubled);
- assertThat(letters).iteratesAs("a", "", "b", "c");
+ assertThat(letters).containsExactly("a", "", "b", "c").inOrder();
}
public void testCharacterSplitWithDoubleDelimiterAndSpace() {
String doubled = "a,, b,c";
Iterable<String> letters = COMMA_SPLITTER.split(doubled);
- assertThat(letters).iteratesAs("a", "", " b", "c");
+ assertThat(letters).containsExactly("a", "", " b", "c").inOrder();
}
public void testCharacterSplitWithTrailingDelimiter() {
String trailing = "a,b,c,";
Iterable<String> letters = COMMA_SPLITTER.split(trailing);
- assertThat(letters).iteratesAs("a", "b", "c", "");
+ assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
}
public void testCharacterSplitWithLeadingDelimiter() {
String leading = ",a,b,c";
Iterable<String> letters = COMMA_SPLITTER.split(leading);
- assertThat(letters).iteratesAs("", "a", "b", "c");
+ assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
}
public void testCharacterSplitWithMulitpleLetters() {
Iterable<String> testCharacteringMotto = Splitter.on('-').split(
"Testing-rocks-Debugging-sucks");
- assertThat(testCharacteringMotto).iteratesAs(
- "Testing", "rocks", "Debugging", "sucks");
+ assertThat(testCharacteringMotto)
+ .containsExactly("Testing", "rocks", "Debugging", "sucks")
+ .inOrder();
}
public void testCharacterSplitWithMatcherDelimiter() {
Iterable<String> testCharacteringMotto = Splitter
.on(CharMatcher.WHITESPACE)
.split("Testing\nrocks\tDebugging sucks");
- assertThat(testCharacteringMotto).iteratesAs(
- "Testing", "rocks", "Debugging", "sucks");
+ assertThat(testCharacteringMotto)
+ .containsExactly("Testing", "rocks", "Debugging", "sucks")
+ .inOrder();
}
public void testCharacterSplitWithDoubleDelimiterOmitEmptyStrings() {
String doubled = "a..b.c";
Iterable<String> letters = Splitter.on('.')
.omitEmptyStrings().split(doubled);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
public void testCharacterSplitEmptyToken() {
String emptyToken = "a. .c";
Iterable<String> letters = Splitter.on('.').trimResults()
.split(emptyToken);
- assertThat(letters).iteratesAs("a", "", "c");
+ assertThat(letters).containsExactly("a", "", "c").inOrder();
}
public void testCharacterSplitEmptyTokenOmitEmptyStrings() {
String emptyToken = "a. .c";
Iterable<String> letters = Splitter.on('.')
.omitEmptyStrings().trimResults().split(emptyToken);
- assertThat(letters).iteratesAs("a", "c");
+ assertThat(letters).containsExactly("a", "c").inOrder();
}
public void testCharacterSplitOnEmptyString() {
Iterable<String> nothing = Splitter.on('.').split("");
- assertThat(nothing).iteratesAs("");
+ assertThat(nothing).containsExactly("").inOrder();
}
public void testCharacterSplitOnEmptyStringOmitEmptyStrings() {
@@ -151,7 +152,7 @@ public class SplitterTest extends TestCase {
public void testCharacterSplitOnOnlyDelimiter() {
Iterable<String> blankblank = Splitter.on('.').split(".");
- assertThat(blankblank).iteratesAs("", "");
+ assertThat(blankblank).containsExactly("", "").inOrder();
}
public void testCharacterSplitOnOnlyDelimitersOmitEmptyStrings() {
@@ -165,99 +166,102 @@ public class SplitterTest extends TestCase {
Iterable<String> family = COMMA_SPLITTER
.trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
.split(jacksons);
- assertThat(family).iteratesAs(
- "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
+ assertThat(family)
+ .containsExactly("(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)")
+ .inOrder();
}
public void testStringSimpleSplit() {
String simple = "a,b,c";
Iterable<String> letters = Splitter.on(',').split(simple);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
public void testStringSimpleSplitWithNoDelimiter() {
String simple = "a,b,c";
Iterable<String> letters = Splitter.on('.').split(simple);
- assertThat(letters).iteratesAs("a,b,c");
+ assertThat(letters).containsExactly("a,b,c").inOrder();
}
public void testStringSplitWithDoubleDelimiter() {
String doubled = "a,,b,c";
Iterable<String> letters = Splitter.on(',').split(doubled);
- assertThat(letters).iteratesAs("a", "", "b", "c");
+ assertThat(letters).containsExactly("a", "", "b", "c").inOrder();
}
public void testStringSplitWithDoubleDelimiterAndSpace() {
String doubled = "a,, b,c";
Iterable<String> letters = Splitter.on(',').split(doubled);
- assertThat(letters).iteratesAs("a", "", " b", "c");
+ assertThat(letters).containsExactly("a", "", " b", "c").inOrder();
}
public void testStringSplitWithTrailingDelimiter() {
String trailing = "a,b,c,";
Iterable<String> letters = Splitter.on(',').split(trailing);
- assertThat(letters).iteratesAs("a", "b", "c", "");
+ assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
}
public void testStringSplitWithLeadingDelimiter() {
String leading = ",a,b,c";
Iterable<String> letters = Splitter.on(',').split(leading);
- assertThat(letters).iteratesAs("", "a", "b", "c");
+ assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
}
public void testStringSplitWithMultipleLetters() {
Iterable<String> testStringingMotto = Splitter.on('-').split(
"Testing-rocks-Debugging-sucks");
- assertThat(testStringingMotto).iteratesAs(
- "Testing", "rocks", "Debugging", "sucks");
+ assertThat(testStringingMotto)
+ .containsExactly("Testing", "rocks", "Debugging", "sucks")
+ .inOrder();
}
public void testStringSplitWithDoubleDelimiterOmitEmptyStrings() {
String doubled = "a..b.c";
Iterable<String> letters = Splitter.on('.')
.omitEmptyStrings().split(doubled);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
public void testStringSplitEmptyToken() {
String emptyToken = "a. .c";
Iterable<String> letters = Splitter.on('.').trimResults()
.split(emptyToken);
- assertThat(letters).iteratesAs("a", "", "c");
+ assertThat(letters).containsExactly("a", "", "c").inOrder();
}
public void testStringSplitEmptyTokenOmitEmptyStrings() {
String emptyToken = "a. .c";
Iterable<String> letters = Splitter.on('.')
.omitEmptyStrings().trimResults().split(emptyToken);
- assertThat(letters).iteratesAs("a", "c");
+ assertThat(letters).containsExactly("a", "c").inOrder();
}
public void testStringSplitWithLongDelimiter() {
String longDelimiter = "a, b, c";
Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
public void testStringSplitWithLongLeadingDelimiter() {
String longDelimiter = ", a, b, c";
Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
- assertThat(letters).iteratesAs("", "a", "b", "c");
+ assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
}
public void testStringSplitWithLongTrailingDelimiter() {
String longDelimiter = "a, b, c, ";
Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
- assertThat(letters).iteratesAs("a", "b", "c", "");
+ assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
}
public void testStringSplitWithDelimiterSubstringInValue() {
String fourCommasAndFourSpaces = ",,,, ";
Iterable<String> threeCommasThenThreeSpaces = Splitter.on(", ").split(
fourCommasAndFourSpaces);
- assertThat(threeCommasThenThreeSpaces).iteratesAs(",,,", " ");
+ assertThat(threeCommasThenThreeSpaces).containsExactly(",,,", " ").inOrder();
}
+ @SuppressWarnings("CheckReturnValue")
public void testStringSplitWithEmptyString() {
try {
Splitter.on("");
@@ -268,7 +272,7 @@ public class SplitterTest extends TestCase {
public void testStringSplitOnEmptyString() {
Iterable<String> notMuch = Splitter.on('.').split("");
- assertThat(notMuch).iteratesAs("");
+ assertThat(notMuch).containsExactly("").inOrder();
}
public void testStringSplitOnEmptyStringOmitEmptyString() {
@@ -277,7 +281,7 @@ public class SplitterTest extends TestCase {
public void testStringSplitOnOnlyDelimiter() {
Iterable<String> blankblank = Splitter.on('.').split(".");
- assertThat(blankblank).iteratesAs("", "");
+ assertThat(blankblank).containsExactly("", "").inOrder();
}
public void testStringSplitOnOnlyDelimitersOmitEmptyStrings() {
@@ -291,50 +295,51 @@ public class SplitterTest extends TestCase {
Iterable<String> family = Splitter.on(',')
.trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
.split(jacksons);
- assertThat(family).iteratesAs(
- "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
+ assertThat(family)
+ .containsExactly("(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)")
+ .inOrder();
}
@GwtIncompatible("Splitter.onPattern")
public void testPatternSimpleSplit() {
String simple = "a,b,c";
Iterable<String> letters = Splitter.onPattern(",").split(simple);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
@GwtIncompatible("Splitter.onPattern")
public void testPatternSimpleSplitWithNoDelimiter() {
String simple = "a,b,c";
Iterable<String> letters = Splitter.onPattern("foo").split(simple);
- assertThat(letters).iteratesAs("a,b,c");
+ assertThat(letters).containsExactly("a,b,c").inOrder();
}
@GwtIncompatible("Splitter.onPattern")
public void testPatternSplitWithDoubleDelimiter() {
String doubled = "a,,b,c";
Iterable<String> letters = Splitter.onPattern(",").split(doubled);
- assertThat(letters).iteratesAs("a", "", "b", "c");
+ assertThat(letters).containsExactly("a", "", "b", "c").inOrder();
}
@GwtIncompatible("Splitter.onPattern")
public void testPatternSplitWithDoubleDelimiterAndSpace() {
String doubled = "a,, b,c";
Iterable<String> letters = Splitter.onPattern(",").split(doubled);
- assertThat(letters).iteratesAs("a", "", " b", "c");
+ assertThat(letters).containsExactly("a", "", " b", "c").inOrder();
}
@GwtIncompatible("Splitter.onPattern")
public void testPatternSplitWithTrailingDelimiter() {
String trailing = "a,b,c,";
Iterable<String> letters = Splitter.onPattern(",").split(trailing);
- assertThat(letters).iteratesAs("a", "b", "c", "");
+ assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
}
@GwtIncompatible("Splitter.onPattern")
public void testPatternSplitWithLeadingDelimiter() {
String leading = ",a,b,c";
Iterable<String> letters = Splitter.onPattern(",").split(leading);
- assertThat(letters).iteratesAs("", "a", "b", "c");
+ assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
}
// TODO(kevinb): the name of this method suggests it might not actually be testing what it
@@ -343,7 +348,8 @@ public class SplitterTest extends TestCase {
public void testPatternSplitWithMultipleLetters() {
Iterable<String> testPatterningMotto = Splitter.onPattern("-").split(
"Testing-rocks-Debugging-sucks");
- assertThat(testPatterningMotto).iteratesAs("Testing", "rocks", "Debugging", "sucks");
+ assertThat(testPatterningMotto).containsExactly("Testing", "rocks", "Debugging", "sucks")
+ .inOrder();
}
@GwtIncompatible("java.util.regex.Pattern")
@@ -356,30 +362,32 @@ public class SplitterTest extends TestCase {
String doubled = "a..b.c";
Iterable<String> letters = Splitter.on(literalDotPattern())
.omitEmptyStrings().split(doubled);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
@GwtIncompatible("java.util.regex.Pattern")
+ @SuppressUnderAndroid // TODO(cpovirk): File Android bug.
public void testPatternSplitLookBehind() {
String toSplit = ":foo::barbaz:";
String regexPattern = "(?<=:)";
Iterable<String> split = Splitter.onPattern(regexPattern).split(toSplit);
- assertThat(split).iteratesAs(":", "foo:", ":", "barbaz:");
+ assertThat(split).containsExactly(":", "foo:", ":", "barbaz:").inOrder();
// splits into chunks ending in :
}
@GwtIncompatible("java.util.regex.Pattern")
+ @SuppressUnderAndroid // TODO(cpovirk): File Android bug.
public void testPatternSplitWordBoundary() {
String string = "foo<bar>bletch";
Iterable<String> words = Splitter.on(Pattern.compile("\\b")).split(string);
- assertThat(words).iteratesAs("foo", "<", "bar", ">", "bletch");
+ assertThat(words).containsExactly("foo", "<", "bar", ">", "bletch").inOrder();
}
@GwtIncompatible("java.util.regex.Pattern")
public void testPatternSplitEmptyToken() {
String emptyToken = "a. .c";
Iterable<String> letters = Splitter.on(literalDotPattern()).trimResults().split(emptyToken);
- assertThat(letters).iteratesAs("a", "", "c");
+ assertThat(letters).containsExactly("a", "", "c").inOrder();
}
@GwtIncompatible("java.util.regex.Pattern")
@@ -387,14 +395,14 @@ public class SplitterTest extends TestCase {
String emptyToken = "a. .c";
Iterable<String> letters = Splitter.on(literalDotPattern())
.omitEmptyStrings().trimResults().split(emptyToken);
- assertThat(letters).iteratesAs("a", "c");
+ assertThat(letters).containsExactly("a", "c").inOrder();
}
@GwtIncompatible("java.util.regex.Pattern")
public void testPatternSplitOnOnlyDelimiter() {
Iterable<String> blankblank = Splitter.on(literalDotPattern()).split(".");
- assertThat(blankblank).iteratesAs("", "");
+ assertThat(blankblank).containsExactly("", "").inOrder();
}
@GwtIncompatible("java.util.regex.Pattern")
@@ -409,7 +417,7 @@ public class SplitterTest extends TestCase {
String longDelimiter = "a, b, c";
Iterable<String> letters = Splitter.on(Pattern.compile(",\\s*"))
.split(longDelimiter);
- assertThat(letters).iteratesAs("a", "b", "c");
+ assertThat(letters).containsExactly("a", "b", "c").inOrder();
}
@GwtIncompatible("java.util.regex.Pattern")
@@ -417,7 +425,7 @@ public class SplitterTest extends TestCase {
String longDelimiter = ", a, b, c";
Iterable<String> letters = Splitter.on(Pattern.compile(", "))
.split(longDelimiter);
- assertThat(letters).iteratesAs("", "a", "b", "c");
+ assertThat(letters).containsExactly("", "a", "b", "c").inOrder();
}
@GwtIncompatible("java.util.regex.Pattern")
@@ -425,9 +433,10 @@ public class SplitterTest extends TestCase {
String longDelimiter = "a, b, c/ ";
Iterable<String> letters = Splitter.on(Pattern.compile("[,/]\\s"))
.split(longDelimiter);
- assertThat(letters).iteratesAs("a", "b", "c", "");
+ assertThat(letters).containsExactly("a", "b", "c", "").inOrder();
}
+ @SuppressWarnings("CheckReturnValue")
@GwtIncompatible("java.util.regex.Pattern")
public void testPatternSplitInvalidPattern() {
try {
@@ -444,8 +453,9 @@ public class SplitterTest extends TestCase {
Iterable<String> family = Splitter.on(Pattern.compile(","))
.trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
.split(jacksons);
- assertThat(family).iteratesAs(
- "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
+ assertThat(family)
+ .containsExactly("(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)")
+ .inOrder();
}
public void testSplitterIterableIsUnmodifiable_char() {
@@ -480,6 +490,7 @@ public class SplitterTest extends TestCase {
}
@GwtIncompatible("java.util.regex.Pattern")
+ @SuppressUnderAndroid // TODO(cpovirk): File Android bug (different from the two above).
public void testSplitterIterableIsLazy_pattern() {
assertSplitterIterableIsLazy(Splitter.onPattern(","));
}
@@ -505,31 +516,31 @@ public class SplitterTest extends TestCase {
public void testFixedLengthSimpleSplit() {
String simple = "abcde";
Iterable<String> letters = Splitter.fixedLength(2).split(simple);
- assertThat(letters).iteratesAs("ab", "cd", "e");
+ assertThat(letters).containsExactly("ab", "cd", "e").inOrder();
}
public void testFixedLengthSplitEqualChunkLength() {
String simple = "abcdef";
Iterable<String> letters = Splitter.fixedLength(2).split(simple);
- assertThat(letters).iteratesAs("ab", "cd", "ef");
+ assertThat(letters).containsExactly("ab", "cd", "ef").inOrder();
}
public void testFixedLengthSplitOnlyOneChunk() {
String simple = "abc";
Iterable<String> letters = Splitter.fixedLength(3).split(simple);
- assertThat(letters).iteratesAs("abc");
+ assertThat(letters).containsExactly("abc").inOrder();
}
public void testFixedLengthSplitSmallerString() {
String simple = "ab";
Iterable<String> letters = Splitter.fixedLength(3).split(simple);
- assertThat(letters).iteratesAs("ab");
+ assertThat(letters).containsExactly("ab").inOrder();
}
public void testFixedLengthSplitEmptyString() {
String simple = "";
Iterable<String> letters = Splitter.fixedLength(3).split(simple);
- assertThat(letters).iteratesAs("");
+ assertThat(letters).containsExactly("").inOrder();
}
public void testFixedLengthSplitEmptyStringWithOmitEmptyStrings() {
@@ -539,9 +550,10 @@ public class SplitterTest extends TestCase {
public void testFixedLengthSplitIntoChars() {
String simple = "abcd";
Iterable<String> letters = Splitter.fixedLength(1).split(simple);
- assertThat(letters).iteratesAs("a", "b", "c", "d");
+ assertThat(letters).containsExactly("a", "b", "c", "d").inOrder();
}
+ @SuppressWarnings("CheckReturnValue")
public void testFixedLengthSplitZeroChunkLen() {
try {
Splitter.fixedLength(0);
@@ -550,6 +562,7 @@ public class SplitterTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testFixedLengthSplitNegativeChunkLen() {
try {
Splitter.fixedLength(-1);
@@ -561,73 +574,73 @@ public class SplitterTest extends TestCase {
public void testLimitLarge() {
String simple = "abcd";
Iterable<String> letters = Splitter.fixedLength(1).limit(100).split(simple);
- assertThat(letters).iteratesAs("a", "b", "c", "d");
+ assertThat(letters).containsExactly("a", "b", "c", "d").inOrder();
}
public void testLimitOne() {
String simple = "abcd";
Iterable<String> letters = Splitter.fixedLength(1).limit(1).split(simple);
- assertThat(letters).iteratesAs("abcd");
+ assertThat(letters).containsExactly("abcd").inOrder();
}
public void testLimitFixedLength() {
String simple = "abcd";
Iterable<String> letters = Splitter.fixedLength(1).limit(2).split(simple);
- assertThat(letters).iteratesAs("a", "bcd");
+ assertThat(letters).containsExactly("a", "bcd").inOrder();
}
public void testLimitSeparator() {
String simple = "a,b,c,d";
Iterable<String> items = COMMA_SPLITTER.limit(2).split(simple);
- assertThat(items).iteratesAs("a", "b,c,d");
+ assertThat(items).containsExactly("a", "b,c,d").inOrder();
}
public void testLimitExtraSeparators() {
String text = "a,,,b,,c,d";
Iterable<String> items = COMMA_SPLITTER.limit(2).split(text);
- assertThat(items).iteratesAs("a", ",,b,,c,d");
+ assertThat(items).containsExactly("a", ",,b,,c,d").inOrder();
}
public void testLimitExtraSeparatorsOmitEmpty() {
String text = "a,,,b,,c,d";
Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().split(text);
- assertThat(items).iteratesAs("a", "b,,c,d");
+ assertThat(items).containsExactly("a", "b,,c,d").inOrder();
}
public void testLimitExtraSeparatorsOmitEmpty3() {
String text = "a,,,b,,c,d";
Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().split(text);
- assertThat(items).iteratesAs("a", "b", "c,d");
+ assertThat(items).containsExactly("a", "b", "c,d").inOrder();
}
public void testLimitExtraSeparatorsTrim() {
String text = ",,a,, , b ,, c,d ";
Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().trimResults().split(text);
- assertThat(items).iteratesAs("a", "b ,, c,d");
+ assertThat(items).containsExactly("a", "b ,, c,d").inOrder();
}
public void testLimitExtraSeparatorsTrim3() {
String text = ",,a,, , b ,, c,d ";
Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().trimResults().split(text);
- assertThat(items).iteratesAs("a", "b", "c,d");
+ assertThat(items).containsExactly("a", "b", "c,d").inOrder();
}
public void testLimitExtraSeparatorsTrim1() {
String text = ",,a,, , b ,, c,d ";
Iterable<String> items = COMMA_SPLITTER.limit(1).omitEmptyStrings().trimResults().split(text);
- assertThat(items).iteratesAs("a,, , b ,, c,d");
+ assertThat(items).containsExactly("a,, , b ,, c,d").inOrder();
}
public void testLimitExtraSeparatorsTrim1NoOmit() {
String text = ",,a,, , b ,, c,d ";
Iterable<String> items = COMMA_SPLITTER.limit(1).trimResults().split(text);
- assertThat(items).iteratesAs(",,a,, , b ,, c,d");
+ assertThat(items).containsExactly(",,a,, , b ,, c,d").inOrder();
}
public void testLimitExtraSeparatorsTrim1Empty() {
String text = "";
Iterable<String> items = COMMA_SPLITTER.limit(1).split(text);
- assertThat(items).iteratesAs("");
+ assertThat(items).containsExactly("").inOrder();
}
public void testLimitExtraSeparatorsTrim1EmptyOmit() {
@@ -653,19 +666,15 @@ public class SplitterTest extends TestCase {
tester.testAllPublicInstanceMethods(Splitter.on(',').trimResults());
}
- private static <E> List<E> asList(Collection<E> collection) {
- return ImmutableList.copyOf(collection);
- }
-
public void testMapSplitter_trimmedBoth() {
Map<String, String> m = COMMA_SPLITTER
.trimResults()
.withKeyValueSeparator(Splitter.on(':').trimResults())
.split("boy : tom , girl: tina , cat : kitty , dog: tommy ");
ImmutableMap<String, String> expected =
- ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
+ ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
assertThat(m).isEqualTo(expected);
- assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+ assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
}
public void testMapSplitter_trimmedEntries() {
@@ -677,7 +686,7 @@ public class SplitterTest extends TestCase {
ImmutableMap.of("boy ", " tom", "girl", " tina", "cat ", " kitty", "dog", " tommy");
assertThat(m).isEqualTo(expected);
- assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+ assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
}
public void testMapSplitter_trimmedKeyValue() {
@@ -687,7 +696,7 @@ public class SplitterTest extends TestCase {
ImmutableMap<String, String> expected =
ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
assertThat(m).isEqualTo(expected);
- assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+ assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
}
public void testMapSplitter_notTrimmed() {
@@ -696,7 +705,7 @@ public class SplitterTest extends TestCase {
ImmutableMap<String, String> expected =
ImmutableMap.of(" boy", "tom ", " girl", " tina ", " cat ", "kitty ", " dog", " tommy ");
assertThat(m).isEqualTo(expected);
- assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+ assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
}
public void testMapSplitter_CharacterSeparator() {
@@ -709,7 +718,7 @@ public class SplitterTest extends TestCase {
ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
assertThat(m).isEqualTo(expected);
- assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+ assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
}
public void testMapSplitter_multiCharacterSeparator() {
@@ -722,10 +731,10 @@ public class SplitterTest extends TestCase {
ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
assertThat(m).isEqualTo(expected);
- assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
+ assertThat(m.entrySet()).containsExactlyElementsIn(expected.entrySet()).inOrder();
}
- @SuppressWarnings("ReturnValueIgnored") // testing for exception
+ @SuppressWarnings("CheckReturnValue")
public void testMapSplitter_emptySeparator() {
try {
COMMA_SPLITTER.withKeyValueSeparator("");
@@ -734,6 +743,7 @@ public class SplitterTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testMapSplitter_malformedEntry() {
try {
COMMA_SPLITTER.withKeyValueSeparator("=").split("a=1,b,c=2");
@@ -747,7 +757,7 @@ public class SplitterTest extends TestCase {
.withKeyValueSeparator(":")
.split("boy:tom,girl:tina,cat:kitty,dog:tommy");
- assertThat(m.keySet()).iteratesAs("boy", "girl", "cat", "dog");
+ assertThat(m.keySet()).containsExactly("boy", "girl", "cat", "dog").inOrder();
assertThat(m).isEqualTo(
ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
@@ -756,11 +766,12 @@ public class SplitterTest extends TestCase {
.withKeyValueSeparator(":")
.split("girl:tina,boy:tom,dog:tommy,cat:kitty");
- assertThat(m.keySet()).iteratesAs("girl", "boy", "dog", "cat");
+ assertThat(m.keySet()).containsExactly("girl", "boy", "dog", "cat").inOrder();
assertThat(m).isEqualTo(
ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMapSplitter_duplicateKeys() {
try {
Splitter.on(',').withKeyValueSeparator(":").split("a:1,b:2,a:3");
diff --git a/guava-tests/test/com/google/common/base/StopwatchTest.java b/guava-tests/test/com/google/common/base/StopwatchTest.java
index bd6b2d2..44101dc 100644
--- a/guava-tests/test/com/google/common/base/StopwatchTest.java
+++ b/guava-tests/test/com/google/common/base/StopwatchTest.java
@@ -168,49 +168,6 @@ public class StopwatchTest extends TestCase {
assertEquals(1, stopwatch.elapsed(MILLISECONDS));
}
- public void testElapsedMillis() {
- stopwatch.start();
- ticker.advance(999999);
- assertEquals(0, stopwatch.elapsed(MILLISECONDS));
- ticker.advance(1);
- assertEquals(1, stopwatch.elapsed(MILLISECONDS));
- }
-
- public void testElapsedMillis_whileRunning() {
- ticker.advance(78000000);
- stopwatch.start();
- assertEquals(0, stopwatch.elapsed(MILLISECONDS));
-
- ticker.advance(345000000);
- assertEquals(345, stopwatch.elapsed(MILLISECONDS));
- }
-
- public void testElapsedMillis_notRunning() {
- ticker.advance(1000000);
- stopwatch.start();
- ticker.advance(4000000);
- stopwatch.stop();
- ticker.advance(9000000);
- assertEquals(4, stopwatch.elapsed(MILLISECONDS));
- }
-
- public void testElapsedMillis_multipleSegments() {
- stopwatch.start();
- ticker.advance(9000000);
- stopwatch.stop();
-
- ticker.advance(16000000);
-
- stopwatch.start();
- assertEquals(9, stopwatch.elapsed(MILLISECONDS));
- ticker.advance(25000000);
- assertEquals(34, stopwatch.elapsed(MILLISECONDS));
-
- stopwatch.stop();
- ticker.advance(36000000);
- assertEquals(34, stopwatch.elapsed(MILLISECONDS));
- }
-
@GwtIncompatible("String.format()")
public void testToString() {
stopwatch.start();
diff --git a/guava-tests/test/com/google/common/base/StringsTest.java b/guava-tests/test/com/google/common/base/StringsTest.java
index fb6ff1c..957f93a 100644
--- a/guava-tests/test/com/google/common/base/StringsTest.java
+++ b/guava-tests/test/com/google/common/base/StringsTest.java
@@ -68,6 +68,7 @@ public class StringsTest extends TestCase {
}
// TODO: could remove if we got NPT working in GWT somehow
+ @SuppressWarnings("CheckReturnValue")
public void testPadStart_null() {
try {
Strings.padStart(null, 5, '0');
@@ -97,6 +98,7 @@ public class StringsTest extends TestCase {
}
// TODO: could remove if we got NPT working in GWT somehow
+ @SuppressWarnings("CheckReturnValue")
public void testPadEnd_null() {
try {
Strings.padEnd(null, 5, '0');
@@ -105,6 +107,7 @@ public class StringsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testRepeat() {
String input = "20";
assertEquals("", Strings.repeat(input, 0));
@@ -132,6 +135,7 @@ public class StringsTest extends TestCase {
}
// TODO: could remove if we got NPT working in GWT somehow
+ @SuppressWarnings("CheckReturnValue")
public void testRepeat_null() {
try {
Strings.repeat(null, 5);
diff --git a/guava-tests/test/com/google/common/base/SuppliersTest.java b/guava-tests/test/com/google/common/base/SuppliersTest.java
index 6e6ea9c..1bd784d 100644
--- a/guava-tests/test/com/google/common/base/SuppliersTest.java
+++ b/guava-tests/test/com/google/common/base/SuppliersTest.java
@@ -399,6 +399,7 @@ public class SuppliersTest extends TestCase {
}
@GwtIncompatible("reflection")
+ @SuppressUnderAndroid // TODO(cpovirk): ClassNotFoundException: com.google.common.base.Function
public void testSuppliersSerializable() throws Exception {
new ClassSanityTester().forAllPublicStaticMethods(Suppliers.class)
.testSerializable();
diff --git a/guava-tests/test/com/google/common/base/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/base/SuppressUnderAndroid.java
new file mode 100644
index 0000000..b22c697
--- /dev/null
+++ b/guava-tests/test/com/google/common/base/SuppressUnderAndroid.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.base;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>Why use a custom annotation instead of {@code android.test.suitebuilder.annotation.Suppress}?
+ * I'm not completely sure that this is the right choice, but it has various advantages:
+ *
+ * <ul>
+ * <li>An annotation named just "Suppress" might someday be treated by a non-Android tool as a
+ * suppression. This would follow the precedent of many of our annotation processors, which look for
+ * any annotation named, e.g., "GwtIncompatible," regardless of package.
+ * <li>An annotation named just "Suppress" might suggest to users that the test is suppressed under
+ * all environments. We could fight this by fully qualifying the annotation, but the result will be
+ * verbose and attention-grabbing.
+ * <li>We need to be careful about how we suppress {@code suite()} methods in {@code common.io}. The
+ * generated suite for {@code FooTest} ends up containing {@code FooTest} itself plus some other
+ * tests. We want to exclude the other tests (which Android can't handle) while continuing to run
+ * {@code FooTest} itself. This is exactly what happens with {@code SuppressUnderAndroid}. (But:
+ * TODO(cpovirk): Consider renaming this to "AndroidIncompatible," which would make this clearer by
+ * following the precedent of {@code GwtIncompatible}.) But I'm not sure what would happen if we
+ * annotated the {@code suite()} method with {@code Suppress}. Would {@code FooTest} itself be
+ * suppressed, too?
+ * <li>In at least one case, a use of {@code sun.misc.FpUtils}, the test will not even
+ * <i>compile</i> against Android. Now, this might be an artifact of our build system, one that we
+ * could probably work around. Or we could manually strip the test from open-source Guava while
+ * continuing to run it internally, as we do with many other tests. This would suffice because we
+ * our Android users and tests are using the open-source version, which would no longer have the
+ * problematic test. But why bother when we can instead strip it with a more precisely named
+ * annotation?
+ * <li>While a dependency on Android ought to be easy if it's for annotations only, it will probably
+ * require adding the dep to various whitelists, license files, and Proguard configurations, and
+ * there's always the potential that something will go wrong. It <i>probably</i> won't, since the
+ * deps are needed only in tests (and maybe someday in testlib), but why bother?
+ * <li>Stripping code entirely might help us keep under the method limit someday. Even if it never
+ * comes to that, it may at least help with build and startup times.
+ * </ul>
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/base/ThrowablesTest.java b/guava-tests/test/com/google/common/base/ThrowablesTest.java
index 52d8a74..0af9302 100644
--- a/guava-tests/test/com/google/common/base/ThrowablesTest.java
+++ b/guava-tests/test/com/google/common/base/ThrowablesTest.java
@@ -17,6 +17,9 @@
package com.google.common.base;
import static com.google.common.base.Throwables.getStackTraceAsString;
+import static com.google.common.base.Throwables.lazyStackTrace;
+import static com.google.common.base.Throwables.lazyStackTraceIsLazy;
+import static com.google.common.truth.Truth.assertThat;
import static java.util.Arrays.asList;
import static java.util.regex.Pattern.quote;
@@ -26,6 +29,9 @@ import com.google.common.testing.NullPointerTester;
import junit.framework.TestCase;
import java.io.FileNotFoundException;
+import java.security.Permission;
+import java.security.Policy;
+import java.security.ProtectionDomain;
import java.util.List;
/**
@@ -335,7 +341,7 @@ public class ThrowablesTest extends TestCase {
sample.noneDeclared();
fail();
} catch (RuntimeException expected) {
- assertTrue(expected.getCause() instanceof SomeCheckedException);
+ assertThat(expected.getCause()).isInstanceOf(SomeCheckedException.class);
}
}
@@ -372,7 +378,7 @@ public class ThrowablesTest extends TestCase {
try {
sample.oneDeclared();
fail();
- } catch (SomeCheckedException e) {
+ } catch (SomeCheckedException expected) {
}
}
@@ -393,7 +399,7 @@ public class ThrowablesTest extends TestCase {
try {
sample.oneDeclared();
fail();
- } catch (SomeUncheckedException e) {
+ } catch (SomeUncheckedException expected) {
}
}
@@ -414,8 +420,8 @@ public class ThrowablesTest extends TestCase {
try {
sample.oneDeclared();
fail();
- } catch (RuntimeException e) {
- assertTrue(e.getCause() instanceof SomeOtherCheckedException);
+ } catch (RuntimeException expected) {
+ assertThat(expected.getCause()).isInstanceOf(SomeOtherCheckedException.class);
}
}
@@ -489,7 +495,7 @@ public class ThrowablesTest extends TestCase {
String secondLine = "\\s*at " + ThrowablesTest.class.getName() + "\\..*";
String moreLines = "(?:.*\n?)*";
String expected = firstLine + "\n" + secondLine + "\n" + moreLines;
- assertTrue(getStackTraceAsString(e).matches(expected));
+ assertThat(getStackTraceAsString(e)).matches(expected);
}
public void testGetCausalChain() {
@@ -500,18 +506,74 @@ public class ThrowablesTest extends TestCase {
assertEquals(asList(ex, re, iae, fnfe), Throwables.getCausalChain(ex));
assertSame(fnfe, Iterables.getOnlyElement(Throwables.getCausalChain(fnfe)));
+
+ List<Throwable> causes = Throwables.getCausalChain(ex);
+ try {
+ causes.add(new RuntimeException());
+ fail("List should be unmodifiable");
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
+
+ @SuppressWarnings("CheckReturnValue")
+ public void testGetCasualChainNull() {
try {
Throwables.getCausalChain(null);
fail("Should have throw NPE");
} catch (NullPointerException expected) {
}
+ }
+
+ @SuppressUnderAndroid // No getJavaLangAccess in Android (at least not in the version we use).
+ public void testLazyStackTraceWorksInProd() {
+ // Obviously this isn't guaranteed in every environment, but it works well enough for now:
+ assertTrue(lazyStackTraceIsLazy());
+ }
+
+ public void testLazyStackTrace() {
+ Exception e = new Exception();
+ StackTraceElement[] originalStackTrace = e.getStackTrace();
+
+ assertThat(lazyStackTrace(e)).containsExactly((Object[]) originalStackTrace).inOrder();
- List<Throwable> causes = Throwables.getCausalChain(ex);
try {
- causes.add(new RuntimeException());
- fail("List should be unmodifiable");
+ lazyStackTrace(e).set(0, null);
+ fail();
} catch (UnsupportedOperationException expected) {
}
+
+ // Now we test a property that holds only for the lazy implementation.
+
+ if (!lazyStackTraceIsLazy()) {
+ return;
+ }
+
+ e.setStackTrace(new StackTraceElement[0]);
+ assertThat(lazyStackTrace(e)).containsExactly((Object[]) originalStackTrace).inOrder();
+ }
+
+ private void doTestLazyStackTraceFallback() {
+ assertFalse(lazyStackTraceIsLazy());
+
+ Exception e = new Exception();
+
+ assertThat(lazyStackTrace(e)).containsExactly((Object[]) e.getStackTrace()).inOrder();
+
+ try {
+ lazyStackTrace(e).set(0, null);
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ e.setStackTrace(new StackTraceElement[0]);
+ assertThat(lazyStackTrace(e)).isEmpty();
+ }
+
+ private static class AllowSettingSecurityManagerPolicy extends Policy {
+ @Override
+ public boolean implies(ProtectionDomain pd, Permission perm) {
+ return true;
+ }
}
public void testNullPointers() {
diff --git a/guava-tests/test/com/google/common/base/Utf8Test.java b/guava-tests/test/com/google/common/base/Utf8Test.java
index f098123..88741e7 100644
--- a/guava-tests/test/com/google/common/base/Utf8Test.java
+++ b/guava-tests/test/com/google/common/base/Utf8Test.java
@@ -16,8 +16,17 @@
package com.google.common.base;
+import static com.google.common.truth.Truth.assertThat;
+import static java.lang.Character.MAX_CODE_POINT;
+import static java.lang.Character.MAX_HIGH_SURROGATE;
+import static java.lang.Character.MAX_LOW_SURROGATE;
+import static java.lang.Character.MIN_HIGH_SURROGATE;
+import static java.lang.Character.MIN_LOW_SURROGATE;
+import static java.lang.Character.MIN_SUPPLEMENTARY_CODE_POINT;
+
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
+import com.google.common.collect.ImmutableList;
import junit.framework.TestCase;
@@ -34,6 +43,26 @@ import java.util.Random;
*/
@GwtCompatible(emulated = true)
public class Utf8Test extends TestCase {
+
+ private static final ImmutableList<String> ILL_FORMED_STRINGS;
+ static {
+ ImmutableList.Builder<String> builder = ImmutableList.builder();
+ char[] surrogates = {
+ MAX_LOW_SURROGATE,
+ MAX_HIGH_SURROGATE,
+ MIN_LOW_SURROGATE,
+ MIN_HIGH_SURROGATE,
+ };
+ for (char surrogate : surrogates) {
+ builder.add(newString(surrogate));
+ builder.add(newString(surrogate, 'n'));
+ builder.add(newString('n', surrogate));
+ builder.add(newString(surrogate, surrogate));
+ }
+ builder.add(newString(MIN_LOW_SURROGATE, MAX_HIGH_SURROGATE));
+ ILL_FORMED_STRINGS = builder.build();
+ }
+
public void testEncodedLength_validStrings() {
assertEquals(0, Utf8.encodedLength(""));
assertEquals(11, Utf8.encodedLength("Hello world"));
@@ -45,11 +74,9 @@ public class Utf8Test extends TestCase {
+ "狹斯丕爾。[2]莎士比亞編寫過好多作品,佢嗰劇作響西洋文學好有影響,"
+ "哈都拕人翻譯做好多話。"));
// A surrogate pair
- assertEquals(4, Utf8.encodedLength(
- newString(Character.MIN_HIGH_SURROGATE, Character.MIN_LOW_SURROGATE)));
+ assertEquals(4, Utf8.encodedLength(newString(MIN_HIGH_SURROGATE, MIN_LOW_SURROGATE)));
}
- @GwtIncompatible("StringBuilder.appendCodePoint()")
public void testEncodedLength_validStrings2() {
HashMap<Integer, Integer> utf8Lengths = new HashMap<Integer, Integer>();
utf8Lengths.put(0x00, 1);
@@ -57,9 +84,9 @@ public class Utf8Test extends TestCase {
utf8Lengths.put(0x80, 2);
utf8Lengths.put(0x7ff, 2);
utf8Lengths.put(0x800, 3);
- utf8Lengths.put(Character.MIN_SUPPLEMENTARY_CODE_POINT - 1, 3);
- utf8Lengths.put(Character.MIN_SUPPLEMENTARY_CODE_POINT, 4);
- utf8Lengths.put(Character.MAX_CODE_POINT, 4);
+ utf8Lengths.put(MIN_SUPPLEMENTARY_CODE_POINT - 1, 3);
+ utf8Lengths.put(MIN_SUPPLEMENTARY_CODE_POINT, 4);
+ utf8Lengths.put(MAX_CODE_POINT, 4);
Integer[] codePoints = utf8Lengths.keySet().toArray(new Integer[]{});
StringBuilder sb = new StringBuilder();
@@ -83,24 +110,21 @@ public class Utf8Test extends TestCase {
}
public void testEncodedLength_invalidStrings() {
- testEncodedLengthFails(newString(Character.MIN_HIGH_SURROGATE), 0);
- testEncodedLengthFails("foobar" + newString(Character.MIN_HIGH_SURROGATE), 6);
- testEncodedLengthFails(newString(Character.MIN_LOW_SURROGATE), 0);
- testEncodedLengthFails("foobar" + newString(Character.MIN_LOW_SURROGATE), 6);
- testEncodedLengthFails(
- newString(
- Character.MIN_HIGH_SURROGATE,
- Character.MIN_HIGH_SURROGATE), 0);
+ testEncodedLengthFails(newString(MIN_HIGH_SURROGATE), 0);
+ testEncodedLengthFails("foobar" + newString(MIN_HIGH_SURROGATE), 6);
+ testEncodedLengthFails(newString(MIN_LOW_SURROGATE), 0);
+ testEncodedLengthFails("foobar" + newString(MIN_LOW_SURROGATE), 6);
+ testEncodedLengthFails(newString(MIN_HIGH_SURROGATE, MIN_HIGH_SURROGATE), 0);
}
+ @SuppressWarnings("CheckReturnValue")
private static void testEncodedLengthFails(String invalidString,
int invalidCodePointIndex) {
try {
Utf8.encodedLength(invalidString);
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("Unpaired surrogate at index " + invalidCodePointIndex,
- expected.getMessage());
+ assertThat(expected).hasMessage("Unpaired surrogate at index " + invalidCodePointIndex);
}
}
@@ -174,6 +198,7 @@ public class Utf8Test extends TestCase {
/** Tests that round tripping of all three byte permutations work. */
@GwtIncompatible("java.nio.charset.Charset")
+
public void testIsWellFormed_3Bytes() {
testBytes(3, EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
}
@@ -225,11 +250,11 @@ public class Utf8Test extends TestCase {
assertEquals(EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT, actual);
}
- private String newString(char... chars) {
+ private static String newString(char... chars) {
return new String(chars);
}
- private byte[] toByteArray(int... bytes) {
+ private static byte[] toByteArray(int... bytes) {
byte[] realBytes = new byte[bytes.length];
for (int i = 0; i < bytes.length; i++) {
realBytes[i] = (byte) bytes[i];
@@ -237,11 +262,11 @@ public class Utf8Test extends TestCase {
return realBytes;
}
- private void assertWellFormed(int... bytes) {
+ private static void assertWellFormed(int... bytes) {
assertTrue(Utf8.isWellFormed(toByteArray(bytes)));
}
- private void assertNotWellFormed(int... bytes) {
+ private static void assertNotWellFormed(int... bytes) {
assertFalse(Utf8.isWellFormed(toByteArray(bytes)));
}
diff --git a/guava-tests/test/com/google/common/base/VerifyTest.java b/guava-tests/test/com/google/common/base/VerifyTest.java
index bb08980..fb40263 100644
--- a/guava-tests/test/com/google/common/base/VerifyTest.java
+++ b/guava-tests/test/com/google/common/base/VerifyTest.java
@@ -16,6 +16,7 @@ package com.google.common.base;
import static com.google.common.base.Verify.verify;
import static com.google.common.base.Verify.verifyNotNull;
+import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
@@ -48,7 +49,7 @@ public class VerifyTest extends TestCase {
verify(false, "message");
fail();
} catch (VerifyException expected) {
- assertEquals("message", expected.getMessage());
+ assertThat(expected).hasMessage("message");
}
}
@@ -103,6 +104,6 @@ public class VerifyTest extends TestCase {
private static final String FORMAT = "I ate %s pies.";
private static void checkMessage(Exception e) {
- assertEquals("I ate 5 pies.", e.getMessage());
+ assertThat(e).hasMessage("I ate 5 pies.");
}
}
diff --git a/guava-tests/test/com/google/common/cache/CacheBuilderTest.java b/guava-tests/test/com/google/common/cache/CacheBuilderTest.java
index 1d882e6..3795db8 100644
--- a/guava-tests/test/com/google/common/cache/CacheBuilderTest.java
+++ b/guava-tests/test/com/google/common/cache/CacheBuilderTest.java
@@ -22,6 +22,7 @@ import static com.google.common.cache.TestingRemovalListeners.countingRemovalLis
import static com.google.common.cache.TestingRemovalListeners.nullRemovalListener;
import static com.google.common.cache.TestingRemovalListeners.queuingRemovalListener;
import static com.google.common.cache.TestingWeighers.constantWeigher;
+import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -87,7 +88,7 @@ public class CacheBuilderTest extends TestCase {
.build(identityLoader());
LocalCache<?, ?> map = CacheTesting.toLocalCache(cache);
- assertEquals(4, map.segments.length);
+ assertThat(map.segments).hasLength(4);
assertEquals(2, map.segments[0].table.length());
assertEquals(2, map.segments[1].table.length());
assertEquals(2, map.segments[2].table.length());
@@ -101,7 +102,7 @@ public class CacheBuilderTest extends TestCase {
.build(identityLoader());
LocalCache<?, ?> map = CacheTesting.toLocalCache(cache);
- assertEquals(4, map.segments.length);
+ assertThat(map.segments).hasLength(4);
// 1 is as low as it goes, not 0. it feels dirty to know this/test this.
assertEquals(1, map.segments[0].table.length());
assertEquals(1, map.segments[1].table.length());
@@ -138,7 +139,7 @@ public class CacheBuilderTest extends TestCase {
.concurrencyLevel(1)
.build(identityLoader());
LocalCache<?, ?> map = CacheTesting.toLocalCache(cache);
- assertEquals(1, map.segments.length);
+ assertThat(map.segments).hasLength(1);
}
public void testConcurrencyLevel_large() {
@@ -218,15 +219,11 @@ public class CacheBuilderTest extends TestCase {
@GwtIncompatible("weigher")
public void testWeigher_withMaximumSize() {
try {
- CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>()
- .weigher(constantWeigher(42))
- .maximumSize(1);
+ new CacheBuilder<Object, Object>().weigher(constantWeigher(42)).maximumSize(1);
fail();
} catch (IllegalStateException expected) {}
try {
- CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>()
- .maximumSize(1)
- .weigher(constantWeigher(42));
+ new CacheBuilder<Object, Object>().maximumSize(1).weigher(constantWeigher(42));
fail();
} catch (IllegalStateException expected) {}
}
@@ -363,6 +360,11 @@ public class CacheBuilderTest extends TestCase {
} catch (IllegalStateException expected) {}
}
+ public void testValuesIsNotASet() {
+ assertThat(new CacheBuilder<Object, Object>().build().asMap().values())
+ .isNotInstanceOf(Set.class);
+ }
+
@GwtIncompatible("CacheTesting")
public void testNullCache() {
CountingRemovalListener<Object, Object> listener = countingRemovalListener();
@@ -606,7 +608,7 @@ public class CacheBuilderTest extends TestCase {
public void testSizingDefaults() {
LoadingCache<?, ?> cache = CacheBuilder.newBuilder().build(identityLoader());
LocalCache<?, ?> map = CacheTesting.toLocalCache(cache);
- assertEquals(4, map.segments.length); // concurrency level
+ assertThat(map.segments).hasLength(4); // concurrency level
assertEquals(4, map.segments[0].table.length()); // capacity / conc level
}
diff --git a/guava-tests/test/com/google/common/cache/CacheEvictionTest.java b/guava-tests/test/com/google/common/cache/CacheEvictionTest.java
index 351af8b..041a212 100644
--- a/guava-tests/test/com/google/common/cache/CacheEvictionTest.java
+++ b/guava-tests/test/com/google/common/cache/CacheEvictionTest.java
@@ -18,6 +18,7 @@ import static com.google.common.cache.TestingCacheLoaders.identityLoader;
import static com.google.common.cache.TestingRemovalListeners.countingRemovalListener;
import static com.google.common.cache.TestingWeighers.constantWeigher;
import static com.google.common.cache.TestingWeighers.intKeyWeigher;
+import static com.google.common.cache.TestingWeighers.intValueWeigher;
import static com.google.common.truth.Truth.assertThat;
import static java.util.Arrays.asList;
@@ -131,6 +132,116 @@ public class CacheEvictionTest extends TestCase {
CacheTesting.checkValidState(cache);
}
+ /**
+ * With an unlimited-size cache with maxWeight of 0, entries weighing 0 should still be cached.
+ * Entries with positive weight should not be cached (nor dump existing cache).
+ */
+ public void testEviction_maxWeight_zero() {
+ CountingRemovalListener<Integer, Integer> removalListener = countingRemovalListener();
+ IdentityLoader<Integer> loader = identityLoader();
+
+ // Even numbers are free, odd are too expensive
+ Weigher<Integer, Integer> evensOnly =
+ new Weigher<Integer, Integer>() {
+ @Override public int weigh(Integer k, Integer v) {
+ return k % 2;
+ }
+ };
+
+ LoadingCache<Integer, Integer> cache = CacheBuilder.newBuilder()
+ .concurrencyLevel(1)
+ .maximumWeight(0)
+ .weigher(evensOnly)
+ .removalListener(removalListener)
+ .build(loader);
+
+ // 1 won't be cached
+ assertThat(cache.getUnchecked(1)).isEqualTo(1);
+ assertThat(cache.asMap().keySet()).isEmpty();
+
+ CacheTesting.processPendingNotifications(cache);
+ assertThat(removalListener.getCount()).isEqualTo(1);
+
+ // 2 will be cached
+ assertThat(cache.getUnchecked(2)).isEqualTo(2);
+ assertThat(cache.asMap().keySet()).containsExactly(2);
+
+ CacheTesting.processPendingNotifications(cache);
+ CacheTesting.checkValidState(cache);
+ assertThat(removalListener.getCount()).isEqualTo(1);
+
+ // 4 will be cached
+ assertThat(cache.getUnchecked(4)).isEqualTo(4);
+ assertThat(cache.asMap().keySet()).containsExactly(2, 4);
+
+ CacheTesting.processPendingNotifications(cache);
+ assertThat(removalListener.getCount()).isEqualTo(1);
+
+ // 5 won't be cached, won't dump cache
+ assertThat(cache.getUnchecked(5)).isEqualTo(5);
+ assertThat(cache.asMap().keySet()).containsExactly(2, 4);
+
+ CacheTesting.processPendingNotifications(cache);
+ assertThat(removalListener.getCount()).isEqualTo(2);
+
+ // Should we pepper more of these calls throughout the above? Where?
+ CacheTesting.checkValidState(cache);
+ }
+
+ /**
+ * Tests that when a single entry exceeds the segment's max weight, the new entry is
+ * immediately evicted and nothing else.
+ */
+ public void testEviction_maxWeight_entryTooBig() {
+ CountingRemovalListener<Integer, Integer> removalListener = countingRemovalListener();
+ IdentityLoader<Integer> loader = identityLoader();
+
+ LoadingCache<Integer, Integer> cache = CacheBuilder.newBuilder()
+ .concurrencyLevel(1)
+ .maximumWeight(4)
+ .weigher(intValueWeigher())
+ .removalListener(removalListener)
+ .build(loader);
+
+ // caches 2
+ assertThat(cache.getUnchecked(2)).isEqualTo(2);
+ assertThat(cache.asMap().keySet()).containsExactly(2);
+
+ CacheTesting.processPendingNotifications(cache);
+ assertThat(removalListener.getCount()).isEqualTo(0);
+
+ // caches 3, evicts 2
+ assertThat(cache.getUnchecked(3)).isEqualTo(3);
+ assertThat(cache.asMap().keySet()).containsExactly(3);
+
+ CacheTesting.processPendingNotifications(cache);
+ assertThat(removalListener.getCount()).isEqualTo(1);
+
+ // doesn't cache 5, doesn't evict
+ assertThat(cache.getUnchecked(5)).isEqualTo(5);
+ assertThat(cache.asMap().keySet()).containsExactly(3);
+
+ CacheTesting.processPendingNotifications(cache);
+ assertThat(removalListener.getCount()).isEqualTo(2);
+
+ // caches 1, evicts nothing
+ assertThat(cache.getUnchecked(1)).isEqualTo(1);
+ assertThat(cache.asMap().keySet()).containsExactly(3, 1);
+
+ CacheTesting.processPendingNotifications(cache);
+ assertThat(removalListener.getCount()).isEqualTo(2);
+
+ // caches 4, evicts 1 and 3
+ assertThat(cache.getUnchecked(4)).isEqualTo(4);
+ assertThat(cache.asMap().keySet()).containsExactly(4);
+
+ CacheTesting.processPendingNotifications(cache);
+ assertThat(removalListener.getCount()).isEqualTo(4);
+
+ // Should we pepper more of these calls throughout the above? Where?
+ CacheTesting.checkValidState(cache);
+ }
+
public void testEviction_overflow() {
CountingRemovalListener<Object, Object> removalListener = countingRemovalListener();
IdentityLoader<Object> loader = identityLoader();
@@ -184,27 +295,27 @@ public class CacheEvictionTest extends TestCase {
.build(loader);
CacheTesting.warmUp(cache, 0, 10);
Set<Integer> keySet = cache.asMap().keySet();
- assertThat(keySet).has().exactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ assertThat(keySet).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
// re-order
getAll(cache, asList(0, 1, 2));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(3, 4, 5, 6, 7, 8, 9, 0, 1, 2);
+ assertThat(keySet).containsExactly(3, 4, 5, 6, 7, 8, 9, 0, 1, 2);
// evict 3, 4, 5
getAll(cache, asList(10, 11, 12));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(6, 7, 8, 9, 0, 1, 2, 10, 11, 12);
+ assertThat(keySet).containsExactly(6, 7, 8, 9, 0, 1, 2, 10, 11, 12);
// re-order
getAll(cache, asList(6, 7, 8));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(9, 0, 1, 2, 10, 11, 12, 6, 7, 8);
+ assertThat(keySet).containsExactly(9, 0, 1, 2, 10, 11, 12, 6, 7, 8);
// evict 9, 0, 1
getAll(cache, asList(13, 14, 15));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(2, 10, 11, 12, 6, 7, 8, 13, 14, 15);
+ assertThat(keySet).containsExactly(2, 10, 11, 12, 6, 7, 8, 13, 14, 15);
}
public void testEviction_weightedLru() {
@@ -217,37 +328,37 @@ public class CacheEvictionTest extends TestCase {
.build(loader);
CacheTesting.warmUp(cache, 0, 10);
Set<Integer> keySet = cache.asMap().keySet();
- assertThat(keySet).has().exactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ assertThat(keySet).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
// re-order
getAll(cache, asList(0, 1, 2));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(3, 4, 5, 6, 7, 8, 9, 0, 1, 2);
+ assertThat(keySet).containsExactly(3, 4, 5, 6, 7, 8, 9, 0, 1, 2);
// evict 3, 4, 5
getAll(cache, asList(10));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(6, 7, 8, 9, 0, 1, 2, 10);
+ assertThat(keySet).containsExactly(6, 7, 8, 9, 0, 1, 2, 10);
// re-order
getAll(cache, asList(6, 7, 8));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(9, 0, 1, 2, 10, 6, 7, 8);
+ assertThat(keySet).containsExactly(9, 0, 1, 2, 10, 6, 7, 8);
// evict 9, 1, 2, 10
getAll(cache, asList(15));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(0, 6, 7, 8, 15);
+ assertThat(keySet).containsExactly(0, 6, 7, 8, 15);
// fill empty space
getAll(cache, asList(9));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(0, 6, 7, 8, 15, 9);
+ assertThat(keySet).containsExactly(0, 6, 7, 8, 15, 9);
// evict 6
getAll(cache, asList(1));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(0, 7, 8, 15, 9, 1);
+ assertThat(keySet).containsExactly(0, 7, 8, 15, 9, 1);
}
public void testEviction_overweight() {
@@ -260,17 +371,17 @@ public class CacheEvictionTest extends TestCase {
.build(loader);
CacheTesting.warmUp(cache, 0, 10);
Set<Integer> keySet = cache.asMap().keySet();
- assertThat(keySet).has().exactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ assertThat(keySet).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
// add an at-the-maximum-weight entry
getAll(cache, asList(45));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(0, 45);
+ assertThat(keySet).containsExactly(0, 45);
// add an over-the-maximum-weight entry
getAll(cache, asList(46));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().item(0);
+ assertThat(keySet).contains(0);
}
public void testEviction_invalidateAll() {
@@ -287,7 +398,7 @@ public class CacheEvictionTest extends TestCase {
// add 0, 1, 2, 3, 4
getAll(cache, asList(0, 1, 2, 3, 4));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(0, 1, 2, 3, 4);
+ assertThat(keySet).containsExactly(0, 1, 2, 3, 4);
// invalidate all
cache.invalidateAll();
@@ -297,7 +408,7 @@ public class CacheEvictionTest extends TestCase {
// add 5, 6, 7, 8, 9, 10, 11, 12
getAll(cache, asList(5, 6, 7, 8, 9, 10, 11, 12));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(5, 6, 7, 8, 9, 10, 11, 12);
+ assertThat(keySet).containsExactly(5, 6, 7, 8, 9, 10, 11, 12);
}
private void getAll(LoadingCache<Integer, Integer> cache, List<Integer> keys) {
diff --git a/guava-tests/test/com/google/common/cache/CacheExpirationTest.java b/guava-tests/test/com/google/common/cache/CacheExpirationTest.java
index b5c8266..c2c221e 100644
--- a/guava-tests/test/com/google/common/cache/CacheExpirationTest.java
+++ b/guava-tests/test/com/google/common/cache/CacheExpirationTest.java
@@ -260,42 +260,42 @@ public class CacheExpirationTest extends TestCase {
ticker.advance(1, MILLISECONDS);
}
Set<Integer> keySet = cache.asMap().keySet();
- assertThat(keySet).has().exactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ assertThat(keySet).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
// 0 expires
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(1, 2, 3, 4, 5, 6, 7, 8, 9);
+ assertThat(keySet).containsExactly(1, 2, 3, 4, 5, 6, 7, 8, 9);
// reorder
getAll(cache, asList(0, 1, 2));
CacheTesting.drainRecencyQueues(cache);
ticker.advance(2, MILLISECONDS);
- assertThat(keySet).has().exactly(3, 4, 5, 6, 7, 8, 9, 0, 1, 2);
+ assertThat(keySet).containsExactly(3, 4, 5, 6, 7, 8, 9, 0, 1, 2);
// 3 expires
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(4, 5, 6, 7, 8, 9, 0, 1, 2);
+ assertThat(keySet).containsExactly(4, 5, 6, 7, 8, 9, 0, 1, 2);
// reorder
getAll(cache, asList(5, 7, 9));
CacheTesting.drainRecencyQueues(cache);
- assertThat(keySet).has().exactly(4, 6, 8, 0, 1, 2, 5, 7, 9);
+ assertThat(keySet).containsExactly(4, 6, 8, 0, 1, 2, 5, 7, 9);
// 4 expires
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(6, 8, 0, 1, 2, 5, 7, 9);
+ assertThat(keySet).containsExactly(6, 8, 0, 1, 2, 5, 7, 9);
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(6, 8, 0, 1, 2, 5, 7, 9);
+ assertThat(keySet).containsExactly(6, 8, 0, 1, 2, 5, 7, 9);
// 6 expires
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(8, 0, 1, 2, 5, 7, 9);
+ assertThat(keySet).containsExactly(8, 0, 1, 2, 5, 7, 9);
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(8, 0, 1, 2, 5, 7, 9);
+ assertThat(keySet).containsExactly(8, 0, 1, 2, 5, 7, 9);
// 8 expires
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(0, 1, 2, 5, 7, 9);
+ assertThat(keySet).containsExactly(0, 1, 2, 5, 7, 9);
}
public void testExpirationOrder_write() throws ExecutionException {
@@ -312,37 +312,37 @@ public class CacheExpirationTest extends TestCase {
ticker.advance(1, MILLISECONDS);
}
Set<Integer> keySet = cache.asMap().keySet();
- assertThat(keySet).has().exactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ assertThat(keySet).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
// 0 expires
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(1, 2, 3, 4, 5, 6, 7, 8, 9);
+ assertThat(keySet).containsExactly(1, 2, 3, 4, 5, 6, 7, 8, 9);
// get doesn't stop 1 from expiring
getAll(cache, asList(0, 1, 2));
CacheTesting.drainRecencyQueues(cache);
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(2, 3, 4, 5, 6, 7, 8, 9, 0);
+ assertThat(keySet).containsExactly(2, 3, 4, 5, 6, 7, 8, 9, 0);
// get(K, Callable) doesn't stop 2 from expiring
cache.get(2, Callables.returning(-2));
CacheTesting.drainRecencyQueues(cache);
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(3, 4, 5, 6, 7, 8, 9, 0);
+ assertThat(keySet).containsExactly(3, 4, 5, 6, 7, 8, 9, 0);
// asMap.put saves 3
cache.asMap().put(3, -3);
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(4, 5, 6, 7, 8, 9, 0, 3);
+ assertThat(keySet).containsExactly(4, 5, 6, 7, 8, 9, 0, 3);
// asMap.replace saves 4
cache.asMap().replace(4, -4);
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(5, 6, 7, 8, 9, 0, 3, 4);
+ assertThat(keySet).containsExactly(5, 6, 7, 8, 9, 0, 3, 4);
// 5 expires
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(6, 7, 8, 9, 0, 3, 4);
+ assertThat(keySet).containsExactly(6, 7, 8, 9, 0, 3, 4);
}
public void testExpirationOrder_writeAccess() throws ExecutionException {
@@ -365,33 +365,33 @@ public class CacheExpirationTest extends TestCase {
ticker.advance(1, MILLISECONDS);
Set<Integer> keySet = cache.asMap().keySet();
- assertThat(keySet).has().exactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ assertThat(keySet).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
// get saves 1, 3; 0, 2, 4 expire
getAll(cache, asList(1, 3));
CacheTesting.drainRecencyQueues(cache);
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(5, 6, 7, 8, 9, 1, 3);
+ assertThat(keySet).containsExactly(5, 6, 7, 8, 9, 1, 3);
// get saves 6, 8; 5, 7, 9 expire
getAll(cache, asList(6, 8));
CacheTesting.drainRecencyQueues(cache);
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(1, 3, 6, 8);
+ assertThat(keySet).containsExactly(1, 3, 6, 8);
// get fails to save 1, put saves 3
cache.asMap().put(3, -3);
getAll(cache, asList(1));
CacheTesting.drainRecencyQueues(cache);
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(6, 8, 3);
+ assertThat(keySet).containsExactly(6, 8, 3);
// get(K, Callable) fails to save 8, replace saves 6
cache.asMap().replace(6, -6);
cache.get(8, Callables.returning(-8));
CacheTesting.drainRecencyQueues(cache);
ticker.advance(1, MILLISECONDS);
- assertThat(keySet).has().exactly(3, 6);
+ assertThat(keySet).containsExactly(3, 6);
}
private void runRemovalScheduler(LoadingCache<String, Integer> cache,
diff --git a/guava-tests/test/com/google/common/cache/CacheLoadingTest.java b/guava-tests/test/com/google/common/cache/CacheLoadingTest.java
index a08114d..3cf35b1 100644
--- a/guava-tests/test/com/google/common/cache/CacheLoadingTest.java
+++ b/guava-tests/test/com/google/common/cache/CacheLoadingTest.java
@@ -96,7 +96,7 @@ public class CacheLoadingTest extends TestCase {
}
private void checkLoggedInvalidLoad() {
- assertTrue(popLoggedThrowable() instanceof InvalidCacheLoadException);
+ assertThat(popLoggedThrowable()).isInstanceOf(InvalidCacheLoadException.class);
}
public void testLoad() throws ExecutionException {
@@ -440,7 +440,7 @@ public class CacheLoadingTest extends TestCase {
Object[] lookupKeys = new Object[] { new Object(), new Object(), new Object() };
Map<Object, Object> result = cache.getAll(asList(lookupKeys));
- assertThat(result.keySet()).has().exactlyAs(asList(lookupKeys));
+ assertThat(result.keySet()).containsExactlyElementsIn(asList(lookupKeys));
for (Map.Entry<Object, Object> entry : result.entrySet()) {
Object key = entry.getKey();
Object value = entry.getValue();
@@ -477,7 +477,7 @@ public class CacheLoadingTest extends TestCase {
Object[] lookupKeys = new Object[] { new Object(), new Object(), new Object() };
Map<Object, Object> result = cache.getAll(asList(lookupKeys));
- assertThat(result.keySet()).has().exactlyAs(asList(lookupKeys));
+ assertThat(result.keySet()).containsExactlyElementsIn(asList(lookupKeys));
for (Map.Entry<Object, Object> entry : result.entrySet()) {
Object key = entry.getKey();
Object value = entry.getValue();
@@ -1983,7 +1983,7 @@ public class CacheLoadingTest extends TestCase {
assertEquals(1, callCount.get());
for (int i = 0; i < count; i++) {
- assertTrue(result.get(i) instanceof InvalidCacheLoadException);
+ assertThat(result.get(i)).isInstanceOf(InvalidCacheLoadException.class);
}
// subsequent calls should call the loader again, not get the old exception
@@ -2023,7 +2023,7 @@ public class CacheLoadingTest extends TestCase {
for (int i = 0; i < count; i++) {
// doConcurrentGet alternates between calling getUnchecked and calling get, but an unchecked
// exception thrown by the loader is always wrapped as an UncheckedExecutionException.
- assertTrue(result.get(i) instanceof UncheckedExecutionException);
+ assertThat(result.get(i)).isInstanceOf(UncheckedExecutionException.class);
assertSame(e, ((UncheckedExecutionException) result.get(i)).getCause());
}
@@ -2067,10 +2067,10 @@ public class CacheLoadingTest extends TestCase {
// UncheckedExecutionException.
int mod = i % 3;
if (mod == 0 || mod == 2) {
- assertTrue(result.get(i) instanceof ExecutionException);
+ assertThat(result.get(i)).isInstanceOf(ExecutionException.class);
assertSame(e, ((ExecutionException) result.get(i)).getCause());
} else {
- assertTrue(result.get(i) instanceof UncheckedExecutionException);
+ assertThat(result.get(i)).isInstanceOf(UncheckedExecutionException.class);
assertSame(e, ((UncheckedExecutionException) result.get(i)).getCause());
}
}
@@ -2413,7 +2413,11 @@ public class CacheLoadingTest extends TestCase {
assertEquals("barfoo", cache.getUnchecked(key));
}
- public void testExpandDuringRefresh() throws InterruptedException, ExecutionException {
+ // Test ignored because it is extremely flaky in CI builds
+
+ public void
+ ignoreTestExpandDuringRefresh()
+ throws InterruptedException, ExecutionException {
final AtomicInteger callCount = new AtomicInteger();
// tells the computing thread when to start computing
final CountDownLatch computeSignal = new CountDownLatch(1);
diff --git a/guava-tests/test/com/google/common/cache/CacheReferencesTest.java b/guava-tests/test/com/google/common/cache/CacheReferencesTest.java
index 88d6b23..0750f74 100644
--- a/guava-tests/test/com/google/common/cache/CacheReferencesTest.java
+++ b/guava-tests/test/com/google/common/cache/CacheReferencesTest.java
@@ -94,7 +94,7 @@ public class CacheReferencesTest extends TestCase {
assertSame(value1, cache.getUnchecked(key1));
assertSame(value2, cache.getUnchecked(key2));
assertEquals(ImmutableSet.of(key1, key2), cache.asMap().keySet());
- assertThat(cache.asMap().values()).has().exactly(value1, value2);
+ assertThat(cache.asMap().values()).containsExactly(value1, value2);
assertEquals(ImmutableSet.of(immutableEntry(key1, value1), immutableEntry(key2, value2)),
cache.asMap().entrySet());
}
@@ -113,7 +113,7 @@ public class CacheReferencesTest extends TestCase {
assertTrue(cache.asMap().containsKey(key2));
assertEquals(1, cache.size());
assertEquals(ImmutableSet.of(key2), cache.asMap().keySet());
- assertThat(cache.asMap().values()).has().item(value2);
+ assertThat(cache.asMap().values()).contains(value2);
assertEquals(ImmutableSet.of(immutableEntry(key2, value2)), cache.asMap().entrySet());
}
}
diff --git a/guava-tests/test/com/google/common/cache/CacheTesting.java b/guava-tests/test/com/google/common/cache/CacheTesting.java
index 660fecd..83614da 100644
--- a/guava-tests/test/com/google/common/cache/CacheTesting.java
+++ b/guava-tests/test/com/google/common/cache/CacheTesting.java
@@ -15,6 +15,7 @@
package com.google.common.cache;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
@@ -199,7 +200,7 @@ class CacheTesting {
// cleanup and then check count after we have a strong reference to all entries
segment.cleanUp();
// under high memory pressure keys/values may be nulled out but not yet enqueued
- assertTrue(table.size() <= segment.count);
+ assertThat(table.size()).isAtMost(segment.count);
for (Entry<?, ?> entry : table.entrySet()) {
assertNotNull(entry.getKey());
assertNotNull(entry.getValue());
@@ -232,7 +233,7 @@ class CacheTesting {
if (prev != null) {
assertSame(prev, current.getPreviousInWriteQueue());
assertSame(prev.getNextInWriteQueue(), current);
- assertTrue(prev.getWriteTime() <= current.getWriteTime());
+ assertThat(prev.getWriteTime()).isAtMost(current.getWriteTime());
}
Object key = current.getKey();
if (key != null) {
@@ -480,8 +481,8 @@ class CacheTesting {
assertTrue(collection.isEmpty());
assertEquals(0, collection.size());
assertFalse(collection.iterator().hasNext());
- assertEquals(0, collection.toArray().length);
- assertEquals(0, collection.toArray(new Object[0]).length);
+ assertThat(collection.toArray()).isEmpty();
+ assertThat(collection.toArray(new Object[0])).isEmpty();
if (collection instanceof Set) {
new EqualsTester()
.addEqualityGroup(ImmutableSet.of(), collection)
diff --git a/guava-tests/test/com/google/common/cache/LocalCacheTest.java b/guava-tests/test/com/google/common/cache/LocalCacheTest.java
index 7e1d614..c959d54 100644
--- a/guava-tests/test/com/google/common/cache/LocalCacheTest.java
+++ b/guava-tests/test/com/google/common/cache/LocalCacheTest.java
@@ -27,6 +27,7 @@ import static com.google.common.cache.TestingRemovalListeners.queuingRemovalList
import static com.google.common.cache.TestingWeighers.constantWeigher;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.immutableEntry;
+import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -49,7 +50,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import com.google.common.collect.testing.MapTestSuiteBuilder;
+import com.google.common.collect.testing.ConcurrentMapTestSuiteBuilder;
import com.google.common.collect.testing.TestStringMapGenerator;
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
@@ -83,21 +84,101 @@ import java.util.logging.LogRecord;
* @author Charles Fry
*/
public class LocalCacheTest extends TestCase {
+ private static class TestStringCacheGenerator extends TestStringMapGenerator {
+ private final CacheBuilder<? super String, ? super String> builder;
+
+ TestStringCacheGenerator(CacheBuilder<? super String, ? super String> builder) {
+ this.builder = builder;
+ }
+
+ @Override
+ protected Map<String, String> create(Entry<String, String>[] entries) {
+ LocalCache<String, String> map = makeLocalCache(builder);
+ for (Entry<String, String> entry : entries) {
+ map.put(entry.getKey(), entry.getValue());
+ }
+ return map;
+ }
+ }
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(LocalCacheTest.class);
- suite.addTest(MapTestSuiteBuilder.using(new TestStringMapGenerator() {
- @Override public Map<String, String> create(
- Entry<String, String>[] entries) {
- LocalCache<String, String> map = makeLocalCache(createCacheBuilder());
- for (Entry<String, String> entry : entries) {
- map.put(entry.getKey(), entry.getValue());
- }
- return map;
- }
-
- }).named("LocalCache with defaults")
+ suite.addTest(ConcurrentMapTestSuiteBuilder
+ .using(new TestStringCacheGenerator(createCacheBuilder()))
+ .named("LocalCache with defaults")
+ .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+ CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+ .createTestSuite());
+ suite.addTest(ConcurrentMapTestSuiteBuilder
+ .using(new TestStringCacheGenerator(
+ createCacheBuilder().concurrencyLevel(1)))
+ .named("LocalCache with concurrencyLevel[1]")
+ .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+ CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+ .createTestSuite());
+ suite.addTest(ConcurrentMapTestSuiteBuilder
+ .using(new TestStringCacheGenerator(
+ createCacheBuilder().maximumSize(Integer.MAX_VALUE)))
+ .named("LocalCache with maximumSize")
+ .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+ CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+ .createTestSuite());
+ suite.addTest(ConcurrentMapTestSuiteBuilder
+ .using(new TestStringCacheGenerator(
+ createCacheBuilder()
+ .maximumWeight(Integer.MAX_VALUE)
+ .weigher(new SerializableWeigher<String, String>())))
+ .named("LocalCache with maximumWeight")
+ .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+ CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+ .createTestSuite());
+ suite.addTest(ConcurrentMapTestSuiteBuilder
+ .using(new TestStringCacheGenerator(
+ createCacheBuilder().weakKeys()))
+ .named("LocalCache with weakKeys") // keys are string literals and won't be GC'd
+ .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+ CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+ .createTestSuite());
+ suite.addTest(ConcurrentMapTestSuiteBuilder
+ .using(new TestStringCacheGenerator(
+ createCacheBuilder().weakValues()))
+ .named("LocalCache with weakValues") // values are string literals and won't be GC'd
+ .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+ CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+ .createTestSuite());
+ suite.addTest(ConcurrentMapTestSuiteBuilder
+ .using(new TestStringCacheGenerator(
+ createCacheBuilder().softValues()))
+ .named("LocalCache with softValues") // values are string literals and won't be GC'd
+ .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+ CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+ .createTestSuite());
+ suite.addTest(ConcurrentMapTestSuiteBuilder
+ .using(new TestStringCacheGenerator(
+ createCacheBuilder().expireAfterAccess(1, SECONDS).ticker(new SerializableTicker())))
+ .named("LocalCache with expireAfterAccess") // SerializableTicker never advances
+ .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+ CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+ .createTestSuite());
+ suite.addTest(ConcurrentMapTestSuiteBuilder
+ .using(new TestStringCacheGenerator(
+ createCacheBuilder().expireAfterWrite(1, SECONDS).ticker(new SerializableTicker())))
+ .named("LocalCache with expireAfterWrite") // SerializableTicker never advances
+ .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+ CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+ .createTestSuite());
+ suite.addTest(ConcurrentMapTestSuiteBuilder
+ .using(new TestStringCacheGenerator(
+ createCacheBuilder()
+ .removalListener(new SerializableRemovalListener<String, String>())))
+ .named("LocalCache with removalListener")
+ .withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
+ CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+ .createTestSuite());
+ suite.addTest(ConcurrentMapTestSuiteBuilder
+ .using(new TestStringCacheGenerator(createCacheBuilder().recordStats()))
+ .named("LocalCache with recordStats")
.withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE,
CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
.createTestSuite());
@@ -169,7 +250,7 @@ public class LocalCacheTest extends TestCase {
assertEquals(4, map.concurrencyLevel);
// concurrency level
- assertEquals(4, map.segments.length);
+ assertThat(map.segments).hasLength(4);
// initial capacity / concurrency level
assertEquals(16 / map.segments.length, map.segments[0].table.length());
@@ -234,7 +315,7 @@ public class LocalCacheTest extends TestCase {
private static void checkConcurrencyLevel(int concurrencyLevel, int segmentCount) {
LocalCache<Object, Object> map =
makeLocalCache(createCacheBuilder().concurrencyLevel(concurrencyLevel));
- assertEquals(segmentCount, map.segments.length);
+ assertThat(map.segments).hasLength(segmentCount);
}
public void testSetInitialCapacity() {
@@ -581,7 +662,7 @@ public class LocalCacheTest extends TestCase {
map.put("foo", "bar");
map.put("baz", "bar");
map.put("quux", "quux");
- assertFalse(map.values() instanceof Set);
+ assertThat(map.values()).isNotInstanceOf(Set.class);
assertTrue(map.values().removeAll(ImmutableSet.of("bar")));
assertEquals(1, map.size());
}
@@ -2248,7 +2329,7 @@ public class LocalCacheTest extends TestCase {
it.next();
it.remove();
}
- segment.evictEntries();
+ segment.evictEntries(entry);
assertEquals(maxSize, map.size());
assertEquals(originalMap, map);
}
diff --git a/guava-tests/test/com/google/common/cache/LocalLoadingCacheTest.java b/guava-tests/test/com/google/common/cache/LocalLoadingCacheTest.java
index 5ae1b45..0c07b94 100644
--- a/guava-tests/test/com/google/common/cache/LocalLoadingCacheTest.java
+++ b/guava-tests/test/com/google/common/cache/LocalLoadingCacheTest.java
@@ -160,17 +160,17 @@ public class LocalLoadingCacheTest extends TestCase {
assertNull(map.put(three, one));
assertNull(map.put(one, two));
- assertThat(map).hasKey(three).withValue(one);
- assertThat(map).hasKey(one).withValue(two);
+ assertThat(map).containsEntry(three, one);
+ assertThat(map).containsEntry(one, two);
- //TODO(user): Confirm with fry@ that this is a reasonable substitute.
+ //TODO(cgruber): Confirm with fry@ that this is a reasonable substitute.
//Set<Map.Entry<Object, Object>> entries = map.entrySet();
- //assertThat(entries).has().exactly(
+ //assertThat(entries).containsExactly(
// Maps.immutableEntry(three, one), Maps.immutableEntry(one, two));
//Set<Object> keys = map.keySet();
- //assertThat(keys).has().exactly(one, three);
+ //assertThat(keys).containsExactly(one, three);
//Collection<Object> values = map.values();
- //assertThat(values).has().exactly(one, two);
+ //assertThat(values).containsExactly(one, two);
map.clear();
diff --git a/guava-tests/test/com/google/common/cache/PopulatedCachesTest.java b/guava-tests/test/com/google/common/cache/PopulatedCachesTest.java
index d7fee82..a98238b 100644
--- a/guava-tests/test/com/google/common/cache/PopulatedCachesTest.java
+++ b/guava-tests/test/com/google/common/cache/PopulatedCachesTest.java
@@ -195,9 +195,9 @@ public class PopulatedCachesTest extends TestCase {
List<Entry<Object, Object>> warmed = warmUp(cache);
Set<Object> expected = Maps.newHashMap(cache.asMap()).keySet();
- assertThat(keys).has().exactlyAs(expected);
- assertThat(keys.toArray()).asList().has().exactlyAs(expected);
- assertThat(keys.toArray(new Object[0])).asList().has().exactlyAs(expected);
+ assertThat(keys).containsExactlyElementsIn(expected);
+ assertThat(keys.toArray()).asList().containsExactlyElementsIn(expected);
+ assertThat(keys.toArray(new Object[0])).asList().containsExactlyElementsIn(expected);
new EqualsTester()
.addEqualityGroup(cache.asMap().keySet(), keys)
@@ -222,9 +222,9 @@ public class PopulatedCachesTest extends TestCase {
List<Entry<Object, Object>> warmed = warmUp(cache);
Collection<Object> expected = Maps.newHashMap(cache.asMap()).values();
- assertThat(values).has().exactlyAs(expected);
- assertThat(values.toArray()).asList().has().exactlyAs(expected);
- assertThat(values.toArray(new Object[0])).asList().has().exactlyAs(expected);
+ assertThat(values).containsExactlyElementsIn(expected);
+ assertThat(values.toArray()).asList().containsExactlyElementsIn(expected);
+ assertThat(values.toArray(new Object[0])).asList().containsExactlyElementsIn(expected);
assertEquals(WARMUP_SIZE, values.size());
for (int i = WARMUP_MIN; i < WARMUP_MAX; i++) {
@@ -247,10 +247,13 @@ public class PopulatedCachesTest extends TestCase {
List<Entry<Object, Object>> warmed = warmUp(cache, WARMUP_MIN, WARMUP_MAX);
Set<?> expected = Maps.newHashMap(cache.asMap()).entrySet();
- assertThat(entries).has().exactlyAs((Collection<Entry<Object, Object>>) expected);
- assertThat(entries.toArray()).asList().has().exactlyAs((Collection<Object>) expected);
- assertThat(entries.toArray(new Entry[0])).asList()
- .has().exactlyAs((Collection<Entry>) expected);
+ assertThat(entries).containsExactlyElementsIn((Collection<Entry<Object, Object>>) expected);
+ assertThat(entries.toArray())
+ .asList()
+ .containsExactlyElementsIn((Collection<Object>) expected);
+ assertThat(entries.toArray(new Entry[0]))
+ .asList()
+ .containsExactlyElementsIn((Collection<Entry>) expected);
new EqualsTester()
.addEqualityGroup(cache.asMap().entrySet(), entries)
diff --git a/guava-tests/test/com/google/common/cache/RemovalNotificationTest.java b/guava-tests/test/com/google/common/cache/RemovalNotificationTest.java
index 0932829..273f0e1 100644
--- a/guava-tests/test/com/google/common/cache/RemovalNotificationTest.java
+++ b/guava-tests/test/com/google/common/cache/RemovalNotificationTest.java
@@ -30,12 +30,12 @@ public class RemovalNotificationTest extends TestCase {
public void testEquals() {
new EqualsTester()
.addEqualityGroup(
- new RemovalNotification<String, Integer>("one", 1, RemovalCause.EXPLICIT),
- new RemovalNotification<String, Integer>("one", 1, RemovalCause.REPLACED))
+ RemovalNotification.create("one", 1, RemovalCause.EXPLICIT),
+ RemovalNotification.create("one", 1, RemovalCause.REPLACED))
.addEqualityGroup(
- new RemovalNotification<String, Integer>("1", 1, RemovalCause.EXPLICIT))
+ RemovalNotification.create("1", 1, RemovalCause.EXPLICIT))
.addEqualityGroup(
- new RemovalNotification<String, Integer>("one", 2, RemovalCause.EXPLICIT))
+ RemovalNotification.create("one", 2, RemovalCause.EXPLICIT))
.testEquals();
}
}
diff --git a/guava-tests/test/com/google/common/collect/AbstractImmutableSetTest.java b/guava-tests/test/com/google/common/collect/AbstractImmutableSetTest.java
index ea309f4..854eb74 100644
--- a/guava-tests/test/com/google/common/collect/AbstractImmutableSetTest.java
+++ b/guava-tests/test/com/google/common/collect/AbstractImmutableSetTest.java
@@ -295,7 +295,7 @@ public abstract class AbstractImmutableSetTest extends TestCase {
.add("d", "e", "f")
.add("g", "h", "i", "j")
.build();
- assertThat(set).has().exactly(
+ assertThat(set).containsExactly(
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j").inOrder();
}
@@ -303,9 +303,9 @@ public abstract class AbstractImmutableSetTest extends TestCase {
ImmutableSet.Builder<String> builder = this.<String>builder()
.add("a")
.add("b");
- assertThat(builder.build()).has().exactly("a", "b").inOrder();
+ assertThat(builder.build()).containsExactly("a", "b").inOrder();
builder.add("c", "d");
- assertThat(builder.build()).has().exactly("a", "b", "c", "d").inOrder();
+ assertThat(builder.build()).containsExactly("a", "b", "c", "d").inOrder();
}
public void testBuilderWithDuplicateElements() {
@@ -325,9 +325,9 @@ public abstract class AbstractImmutableSetTest extends TestCase {
.add("a")
.add("a", "a")
.add("b");
- assertThat(builder.build()).has().exactly("a", "b").inOrder();
+ assertThat(builder.build()).containsExactly("a", "b").inOrder();
builder.add("a", "b", "c", "c");
- assertThat(builder.build()).has().exactly("a", "b", "c").inOrder();
+ assertThat(builder.build()).containsExactly("a", "b", "c").inOrder();
}
public void testBuilderAddAll() {
@@ -337,7 +337,7 @@ public abstract class AbstractImmutableSetTest extends TestCase {
.addAll(a)
.addAll(b)
.build();
- assertThat(set).has().exactly("a", "b", "c", "d", "e").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e").inOrder();
}
static final int LAST_COLOR_ADDED = 0x00BFFF;
diff --git a/guava-tests/test/com/google/common/collect/AbstractRangeSetTest.java b/guava-tests/test/com/google/common/collect/AbstractRangeSetTest.java
index 1a44e87..26e71ed 100644
--- a/guava-tests/test/com/google/common/collect/AbstractRangeSetTest.java
+++ b/guava-tests/test/com/google/common/collect/AbstractRangeSetTest.java
@@ -36,7 +36,9 @@ public abstract class AbstractRangeSetTest extends TestCase {
private static <C extends Comparable> void testInvariantsInternal(RangeSet<C> rangeSet) {
assertEquals(rangeSet.asRanges().isEmpty(), rangeSet.isEmpty());
+ assertEquals(rangeSet.asDescendingSetOfRanges().isEmpty(), rangeSet.isEmpty());
assertEquals(!rangeSet.asRanges().iterator().hasNext(), rangeSet.isEmpty());
+ assertEquals(!rangeSet.asDescendingSetOfRanges().iterator().hasNext(), rangeSet.isEmpty());
List<Range<C>> asRanges = ImmutableList.copyOf(rangeSet.asRanges());
@@ -52,6 +54,7 @@ public abstract class AbstractRangeSetTest extends TestCase {
assertFalse(range.isEmpty());
}
+ // test that the RangeSet's span is the span of all the ranges
Iterator<Range<C>> itr = rangeSet.asRanges().iterator();
Range<C> expectedSpan = null;
if (itr.hasNext()) {
@@ -67,5 +70,8 @@ public abstract class AbstractRangeSetTest extends TestCase {
} catch (NoSuchElementException e) {
assertNull(expectedSpan);
}
+
+ // test that asDescendingSetOfRanges is the reverse of asRanges
+ assertEquals(Lists.reverse(asRanges), ImmutableList.copyOf(rangeSet.asDescendingSetOfRanges()));
}
}
diff --git a/guava-tests/test/com/google/common/collect/AbstractSequentialIteratorTest.java b/guava-tests/test/com/google/common/collect/AbstractSequentialIteratorTest.java
index 83b3900..0892847 100644
--- a/guava-tests/test/com/google/common/collect/AbstractSequentialIteratorTest.java
+++ b/guava-tests/test/com/google/common/collect/AbstractSequentialIteratorTest.java
@@ -50,7 +50,7 @@ public class AbstractSequentialIteratorTest extends TestCase {
return newDoubler(2, 32);
}
};
- assertThat(doubled).iteratesAs(2, 4, 8, 16, 32);
+ assertThat(doubled).containsExactly(2, 4, 8, 16, 32).inOrder();
}
public void testSampleCode() {
@@ -65,9 +65,11 @@ public class AbstractSequentialIteratorTest extends TestCase {
return powersOfTwo;
}
};
- assertThat(actual).iteratesAs(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
- 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304,
- 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824);
+ assertThat(actual)
+ .containsExactly(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
+ 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216,
+ 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824)
+ .inOrder();
}
public void testEmpty() {
diff --git a/guava-tests/test/com/google/common/collect/AbstractTableReadTest.java b/guava-tests/test/com/google/common/collect/AbstractTableReadTest.java
index 45a08c5..d5fd444 100644
--- a/guava-tests/test/com/google/common/collect/AbstractTableReadTest.java
+++ b/guava-tests/test/com/google/common/collect/AbstractTableReadTest.java
@@ -183,7 +183,7 @@ public abstract class AbstractTableReadTest extends TestCase {
public void testColumnSetPartialOverlap() {
table = create(
"foo", 1, 'a', "bar", 1, 'b', "foo", 2, 'c', "bar", 3, 'd');
- assertThat(table.columnKeySet()).has().exactly(1, 2, 3);
+ assertThat(table.columnKeySet()).containsExactly(1, 2, 3);
}
@GwtIncompatible("NullPointerTester")
diff --git a/guava-tests/test/com/google/common/collect/ArrayListMultimapTest.java b/guava-tests/test/com/google/common/collect/ArrayListMultimapTest.java
index 6a567d8..a7b4ba0 100644
--- a/guava-tests/test/com/google/common/collect/ArrayListMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/ArrayListMultimapTest.java
@@ -119,9 +119,9 @@ public class ArrayListMultimapTest extends TestCase {
ListMultimap<String, Integer> multimap = create();
multimap.putAll("foo", asList(1, 2, 3, 4, 5));
List<Integer> list = multimap.get("foo");
- assertThat(multimap.get("foo")).has().exactly(1, 2, 3, 4, 5).inOrder();
+ assertThat(multimap.get("foo")).containsExactly(1, 2, 3, 4, 5).inOrder();
List<Integer> sublist = list.subList(0, 5);
- assertThat(sublist).has().exactly(1, 2, 3, 4, 5).inOrder();
+ assertThat(sublist).containsExactly(1, 2, 3, 4, 5).inOrder();
sublist.clear();
assertTrue(sublist.isEmpty());
@@ -190,7 +190,7 @@ public class ArrayListMultimapTest extends TestCase {
multimap.put("bar", 3);
multimap.trimToSize();
assertEquals(3, multimap.size());
- assertThat(multimap.get("foo")).has().exactly(1, 2).inOrder();
- assertThat(multimap.get("bar")).has().item(3);
+ assertThat(multimap.get("foo")).containsExactly(1, 2).inOrder();
+ assertThat(multimap.get("bar")).contains(3);
}
}
diff --git a/guava-tests/test/com/google/common/collect/ArrayTableTest.java b/guava-tests/test/com/google/common/collect/ArrayTableTest.java
index c535619..bf68e09 100644
--- a/guava-tests/test/com/google/common/collect/ArrayTableTest.java
+++ b/guava-tests/test/com/google/common/collect/ArrayTableTest.java
@@ -286,13 +286,13 @@ public class ArrayTableTest extends AbstractTableTest {
public void testRowKeyList() {
ArrayTable<String, Integer, Character> table
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
- assertThat(table.rowKeyList()).has().exactly("foo", "bar", "cat").inOrder();
+ assertThat(table.rowKeyList()).containsExactly("foo", "bar", "cat").inOrder();
}
public void testColumnKeyList() {
ArrayTable<String, Integer, Character> table
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
- assertThat(table.columnKeyList()).has().exactly(1, 2, 3).inOrder();
+ assertThat(table.columnKeyList()).containsExactly(1, 2, 3).inOrder();
}
public void testGetMissingKeys() {
@@ -369,13 +369,13 @@ public class ArrayTableTest extends AbstractTableTest {
table.put("dog", 1, 'd');
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("Row dog not in [foo, bar, cat]", expected.getMessage());
+ assertThat(expected).hasMessage("Row dog not in [foo, bar, cat]");
}
try {
table.put("foo", 4, 'd');
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("Column 4 not in [1, 2, 3]", expected.getMessage());
+ assertThat(expected).hasMessage("Column 4 not in [1, 2, 3]");
}
assertFalse(table.containsValue('d'));
}
@@ -399,10 +399,10 @@ public class ArrayTableTest extends AbstractTableTest {
ArrayTable<String, Integer, Character> table
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
Character[][] array = table.toArray(Character.class);
- assertEquals(3, array.length);
- assertThat(array[0]).asList().has().exactly('a', null, 'c').inOrder();
- assertThat(array[1]).asList().has().exactly('b', null, null).inOrder();
- assertThat(array[2]).asList().has().exactly(null, null, null).inOrder();
+ assertThat(array).hasLength(3);
+ assertThat(array[0]).asList().containsExactly('a', null, 'c').inOrder();
+ assertThat(array[1]).asList().containsExactly('b', null, null).inOrder();
+ assertThat(array[2]).asList().containsExactly(null, null, null).inOrder();
table.set(0, 2, 'd');
assertEquals((Character) 'c', array[0][2]);
array[0][2] = 'e';
@@ -444,7 +444,7 @@ public class ArrayTableTest extends AbstractTableTest {
map.put(4, 'd');
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("Column 4 not in [1, 2, 3]", expected.getMessage());
+ assertThat(expected).hasMessage("Column 4 not in [1, 2, 3]");
}
}
@@ -455,7 +455,7 @@ public class ArrayTableTest extends AbstractTableTest {
map.put("dog", 'd');
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("Row dog not in [foo, bar, cat]", expected.getMessage());
+ assertThat(expected).hasMessage("Row dog not in [foo, bar, cat]");
}
}
diff --git a/guava-tests/test/com/google/common/collect/Collections2Test.java b/guava-tests/test/com/google/common/collect/Collections2Test.java
index 83d9014..2968ddf 100644
--- a/guava-tests/test/com/google/common/collect/Collections2Test.java
+++ b/guava-tests/test/com/google/common/collect/Collections2Test.java
@@ -237,7 +237,7 @@ public class Collections2Test extends TestCase {
Collections2.orderedPermutations(list);
assertEquals(1, permutationSet.size());
- assertThat(permutationSet).has().item(list);
+ assertThat(permutationSet).contains(list);
Iterator<List<Integer>> permutations = permutationSet.iterator();
diff --git a/guava-tests/test/com/google/common/collect/ComparisonChainTest.java b/guava-tests/test/com/google/common/collect/ComparisonChainTest.java
index e24ed46..b9ad14b 100644
--- a/guava-tests/test/com/google/common/collect/ComparisonChainTest.java
+++ b/guava-tests/test/com/google/common/collect/ComparisonChainTest.java
@@ -37,6 +37,15 @@ public class ComparisonChainTest extends TestCase {
}
}
+ public void testCompareBooleans() {
+ assertEquals(0, ComparisonChain.start()
+ .compare(true, true)
+ .compare(true, Boolean.TRUE)
+ .compare(Boolean.TRUE, true)
+ .compare(Boolean.TRUE, Boolean.TRUE)
+ .result());
+ }
+
public void testDegenerate() {
// kinda bogus, but who cares?
assertEquals(0, ComparisonChain.start().result());
diff --git a/guava-tests/test/com/google/common/collect/ConstraintsTest.java b/guava-tests/test/com/google/common/collect/ConstraintsTest.java
index d93c642..f6c112a 100644
--- a/guava-tests/test/com/google/common/collect/ConstraintsTest.java
+++ b/guava-tests/test/com/google/common/collect/ConstraintsTest.java
@@ -68,10 +68,10 @@ public class ConstraintsTest extends TestCase {
constrained.add("qux");
constrained.addAll(asList("cat", "dog"));
/* equals and hashCode aren't defined for Collection */
- assertThat(collection).has()
- .exactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
- assertThat(constrained).has()
- .exactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
+ assertThat(collection)
+ .containsExactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
+ assertThat(constrained)
+ .containsExactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
}
public void testConstrainedCollectionIllegal() {
@@ -86,8 +86,8 @@ public class ConstraintsTest extends TestCase {
constrained.addAll(asList("baz", TEST_ELEMENT));
fail("TestElementException expected");
} catch (TestElementException expected) {}
- assertThat(constrained).has().exactly("foo", "bar").inOrder();
- assertThat(collection).has().exactly("foo", "bar").inOrder();
+ assertThat(constrained).containsExactly("foo", "bar").inOrder();
+ assertThat(collection).containsExactly("foo", "bar").inOrder();
}
public void testConstrainedSetLegal() {
@@ -100,9 +100,9 @@ public class ConstraintsTest extends TestCase {
assertTrue(constrained.equals(set));
assertEquals(set.toString(), constrained.toString());
assertEquals(set.hashCode(), constrained.hashCode());
- assertThat(set).has().exactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
- assertThat(constrained).has()
- .exactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
+ assertThat(set).containsExactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
+ assertThat(constrained)
+ .containsExactly("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder();
}
public void testConstrainedSetIllegal() {
@@ -116,8 +116,8 @@ public class ConstraintsTest extends TestCase {
constrained.addAll(asList("baz", TEST_ELEMENT));
fail("TestElementException expected");
} catch (TestElementException expected) {}
- assertThat(constrained).has().exactly("foo", "bar").inOrder();
- assertThat(set).has().exactly("foo", "bar").inOrder();
+ assertThat(constrained).containsExactly("foo", "bar").inOrder();
+ assertThat(set).containsExactly("foo", "bar").inOrder();
}
public void testConstrainedSortedSetLegal() {
@@ -131,9 +131,10 @@ public class ConstraintsTest extends TestCase {
assertTrue(constrained.equals(sortedSet));
assertEquals(sortedSet.toString(), constrained.toString());
assertEquals(sortedSet.hashCode(), constrained.hashCode());
- assertThat(sortedSet).has().exactly("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT).inOrder();
- assertThat(constrained).has()
- .exactly("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT).inOrder();
+ assertThat(sortedSet)
+ .containsExactly("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT).inOrder();
+ assertThat(constrained)
+ .containsExactly("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT).inOrder();
assertNull(constrained.comparator());
assertEquals("bar", constrained.first());
assertEquals(TEST_ELEMENT, constrained.last());
@@ -163,8 +164,8 @@ public class ConstraintsTest extends TestCase {
constrained.addAll(asList("baz", TEST_ELEMENT));
fail("TestElementException expected");
} catch (TestElementException expected) {}
- assertThat(constrained).has().exactly("bar", "foo").inOrder();
- assertThat(sortedSet).has().exactly("bar", "foo").inOrder();
+ assertThat(constrained).containsExactly("bar", "foo").inOrder();
+ assertThat(sortedSet).containsExactly("bar", "foo").inOrder();
}
public void testConstrainedListLegal() {
@@ -181,17 +182,17 @@ public class ConstraintsTest extends TestCase {
assertTrue(constrained.equals(list));
assertEquals(list.toString(), constrained.toString());
assertEquals(list.hashCode(), constrained.hashCode());
- assertThat(list).has().exactly(
+ assertThat(list).containsExactly(
"foo", "cow", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog").inOrder();
- assertThat(constrained).has().exactly(
+ assertThat(constrained).containsExactly(
"foo", "cow", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog").inOrder();
ListIterator<String> iterator = constrained.listIterator();
iterator.next();
iterator.set("sun");
constrained.listIterator(2).add("sky");
- assertThat(list).has().exactly(
+ assertThat(list).containsExactly(
"sun", "cow", "sky", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog").inOrder();
- assertThat(constrained).has().exactly(
+ assertThat(constrained).containsExactly(
"sun", "cow", "sky", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog").inOrder();
assertTrue(constrained instanceof RandomAccess);
}
@@ -202,7 +203,7 @@ public class ConstraintsTest extends TestCase {
list, TEST_CONSTRAINT);
list.add(TEST_ELEMENT);
constrained.add("qux");
- assertFalse(constrained instanceof RandomAccess);
+ assertThat(constrained).isNotInstanceOf(RandomAccess.class);
}
public void testConstrainedListIllegal() {
@@ -249,8 +250,8 @@ public class ConstraintsTest extends TestCase {
constrained.addAll(1, asList("baz", TEST_ELEMENT));
fail("TestElementException expected");
} catch (TestElementException expected) {}
- assertThat(constrained).has().exactly("foo", "bar").inOrder();
- assertThat(list).has().exactly("foo", "bar").inOrder();
+ assertThat(constrained).containsExactly("foo", "bar").inOrder();
+ assertThat(list).containsExactly("foo", "bar").inOrder();
}
public void testNefariousAddAll() {
@@ -259,8 +260,8 @@ public class ConstraintsTest extends TestCase {
list, TEST_CONSTRAINT);
Collection<String> onceIterable = onceIterableCollection("baz");
constrained.addAll(onceIterable);
- assertThat(constrained).has().exactly("foo", "bar", "baz").inOrder();
- assertThat(list).has().exactly("foo", "bar", "baz").inOrder();
+ assertThat(constrained).containsExactly("foo", "bar", "baz").inOrder();
+ assertThat(list).containsExactly("foo", "bar", "baz").inOrder();
}
/**
diff --git a/guava-tests/test/com/google/common/collect/ContiguousSetTest.java b/guava-tests/test/com/google/common/collect/ContiguousSetTest.java
index 5e01e02..74d740f 100644
--- a/guava-tests/test/com/google/common/collect/ContiguousSetTest.java
+++ b/guava-tests/test/com/google/common/collect/ContiguousSetTest.java
@@ -84,6 +84,10 @@ public class ContiguousSetTest extends TestCase {
ContiguousSet.create(Range.openClosed(0, 3), NOT_EQUAL_TO_INTEGERS),
ContiguousSet.create(Range.open(0, 4), NOT_EQUAL_TO_INTEGERS),
ImmutableSortedSet.of(1, 2, 3))
+ .addEqualityGroup(
+ ContiguousSet.create(Range.closedOpen(1, 1), integers()),
+ ImmutableSortedSet.of(),
+ ImmutableSet.of())
.testEquals();
// not testing hashCode for these because it takes forever to compute
assertEquals(
@@ -146,15 +150,15 @@ public class ContiguousSetTest extends TestCase {
public void testHeadSet() {
ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, 3), integers());
assertThat(set.headSet(1)).isEmpty();
- assertThat(set.headSet(2)).has().item(1);
- assertThat(set.headSet(3)).has().exactly(1, 2).inOrder();
- assertThat(set.headSet(4)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.headSet(Integer.MAX_VALUE)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.headSet(1, true)).has().item(1);
- assertThat(set.headSet(2, true)).has().exactly(1, 2).inOrder();
- assertThat(set.headSet(3, true)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.headSet(4, true)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.headSet(Integer.MAX_VALUE, true)).has().exactly(1, 2, 3).inOrder();
+ assertThat(set.headSet(2)).contains(1);
+ assertThat(set.headSet(3)).containsExactly(1, 2).inOrder();
+ assertThat(set.headSet(4)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.headSet(Integer.MAX_VALUE)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.headSet(1, true)).contains(1);
+ assertThat(set.headSet(2, true)).containsExactly(1, 2).inOrder();
+ assertThat(set.headSet(3, true)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.headSet(4, true)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.headSet(Integer.MAX_VALUE, true)).containsExactly(1, 2, 3).inOrder();
}
public void testHeadSet_tooSmall() {
@@ -163,13 +167,13 @@ public class ContiguousSetTest extends TestCase {
public void testTailSet() {
ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, 3), integers());
- assertThat(set.tailSet(Integer.MIN_VALUE)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.tailSet(1)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.tailSet(2)).has().exactly(2, 3).inOrder();
- assertThat(set.tailSet(3)).has().item(3);
- assertThat(set.tailSet(Integer.MIN_VALUE, false)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.tailSet(1, false)).has().exactly(2, 3).inOrder();
- assertThat(set.tailSet(2, false)).has().item(3);
+ assertThat(set.tailSet(Integer.MIN_VALUE)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.tailSet(1)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.tailSet(2)).containsExactly(2, 3).inOrder();
+ assertThat(set.tailSet(3)).contains(3);
+ assertThat(set.tailSet(Integer.MIN_VALUE, false)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.tailSet(1, false)).containsExactly(2, 3).inOrder();
+ assertThat(set.tailSet(2, false)).contains(3);
assertThat(set.tailSet(3, false)).isEmpty();
}
@@ -179,19 +183,19 @@ public class ContiguousSetTest extends TestCase {
public void testSubSet() {
ImmutableSortedSet<Integer> set = ContiguousSet.create(Range.closed(1, 3), integers());
- assertThat(set.subSet(1, 4)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.subSet(2, 4)).has().exactly(2, 3).inOrder();
- assertThat(set.subSet(3, 4)).has().item(3);
+ assertThat(set.subSet(1, 4)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.subSet(2, 4)).containsExactly(2, 3).inOrder();
+ assertThat(set.subSet(3, 4)).contains(3);
assertThat(set.subSet(3, 3)).isEmpty();
- assertThat(set.subSet(2, 3)).has().item(2);
- assertThat(set.subSet(1, 3)).has().exactly(1, 2).inOrder();
- assertThat(set.subSet(1, 2)).has().item(1);
+ assertThat(set.subSet(2, 3)).contains(2);
+ assertThat(set.subSet(1, 3)).containsExactly(1, 2).inOrder();
+ assertThat(set.subSet(1, 2)).contains(1);
assertThat(set.subSet(2, 2)).isEmpty();
- assertThat(set.subSet(Integer.MIN_VALUE, Integer.MAX_VALUE)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.subSet(1, true, 3, true)).has().exactly(1, 2, 3).inOrder();
- assertThat(set.subSet(1, false, 3, true)).has().exactly(2, 3).inOrder();
- assertThat(set.subSet(1, true, 3, false)).has().exactly(1, 2).inOrder();
- assertThat(set.subSet(1, false, 3, false)).has().item(2);
+ assertThat(set.subSet(Integer.MIN_VALUE, Integer.MAX_VALUE)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.subSet(1, true, 3, true)).containsExactly(1, 2, 3).inOrder();
+ assertThat(set.subSet(1, false, 3, true)).containsExactly(2, 3).inOrder();
+ assertThat(set.subSet(1, true, 3, false)).containsExactly(1, 2).inOrder();
+ assertThat(set.subSet(1, false, 3, false)).contains(2);
}
public void testSubSet_outOfOrder() {
diff --git a/guava-tests/test/com/google/common/collect/EnumBiMapTest.java b/guava-tests/test/com/google/common/collect/EnumBiMapTest.java
index 6d75bf3..a0c312c 100644
--- a/guava-tests/test/com/google/common/collect/EnumBiMapTest.java
+++ b/guava-tests/test/com/google/common/collect/EnumBiMapTest.java
@@ -197,16 +197,16 @@ public class EnumBiMapTest extends TestCase {
// forward map ordered by currency
assertThat(bimap.keySet())
- .has().exactly(Currency.DOLLAR, Currency.FRANC, Currency.PESO).inOrder();
+ .containsExactly(Currency.DOLLAR, Currency.FRANC, Currency.PESO).inOrder();
// forward map ordered by currency (even for country values)
assertThat(bimap.values())
- .has().exactly(Country.CANADA, Country.SWITZERLAND, Country.CHILE).inOrder();
+ .containsExactly(Country.CANADA, Country.SWITZERLAND, Country.CHILE).inOrder();
// backward map ordered by country
assertThat(bimap.inverse().keySet())
- .has().exactly(Country.CANADA, Country.CHILE, Country.SWITZERLAND).inOrder();
+ .containsExactly(Country.CANADA, Country.CHILE, Country.SWITZERLAND).inOrder();
// backward map ordered by country (even for currency values)
assertThat(bimap.inverse().values())
- .has().exactly(Currency.DOLLAR, Currency.PESO, Currency.FRANC).inOrder();
+ .containsExactly(Currency.DOLLAR, Currency.PESO, Currency.FRANC).inOrder();
}
public void testKeySetIteratorRemove() {
@@ -224,16 +224,16 @@ public class EnumBiMapTest extends TestCase {
// forward map ordered by currency
assertThat(bimap.keySet())
- .has().exactly(Currency.FRANC, Currency.PESO).inOrder();
+ .containsExactly(Currency.FRANC, Currency.PESO).inOrder();
// forward map ordered by currency (even for country values)
assertThat(bimap.values())
- .has().exactly(Country.SWITZERLAND, Country.CHILE).inOrder();
+ .containsExactly(Country.SWITZERLAND, Country.CHILE).inOrder();
// backward map ordered by country
assertThat(bimap.inverse().keySet())
- .has().exactly(Country.CHILE, Country.SWITZERLAND).inOrder();
+ .containsExactly(Country.CHILE, Country.SWITZERLAND).inOrder();
// backward map ordered by country (even for currency values)
assertThat(bimap.inverse().values())
- .has().exactly(Currency.PESO, Currency.FRANC).inOrder();
+ .containsExactly(Currency.PESO, Currency.FRANC).inOrder();
}
public void testValuesIteratorRemove() {
@@ -252,16 +252,16 @@ public class EnumBiMapTest extends TestCase {
// forward map ordered by currency
assertThat(bimap.keySet())
- .has().exactly(Currency.DOLLAR, Currency.PESO).inOrder();
+ .containsExactly(Currency.DOLLAR, Currency.PESO).inOrder();
// forward map ordered by currency (even for country values)
assertThat(bimap.values())
- .has().exactly(Country.CANADA, Country.CHILE).inOrder();
+ .containsExactly(Country.CANADA, Country.CHILE).inOrder();
// backward map ordered by country
assertThat(bimap.inverse().keySet())
- .has().exactly(Country.CANADA, Country.CHILE).inOrder();
+ .containsExactly(Country.CANADA, Country.CHILE).inOrder();
// backward map ordered by country (even for currency values)
assertThat(bimap.inverse().values())
- .has().exactly(Currency.DOLLAR, Currency.PESO).inOrder();
+ .containsExactly(Currency.DOLLAR, Currency.PESO).inOrder();
}
public void testEntrySet() {
diff --git a/guava-tests/test/com/google/common/collect/EvictingQueueTest.java b/guava-tests/test/com/google/common/collect/EvictingQueueTest.java
index 9567dee..d2c44ab 100644
--- a/guava-tests/test/com/google/common/collect/EvictingQueueTest.java
+++ b/guava-tests/test/com/google/common/collect/EvictingQueueTest.java
@@ -18,6 +18,8 @@ package com.google.common.collect;
import static java.util.Arrays.asList;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
import com.google.common.testing.NullPointerTester;
import com.google.common.testing.SerializableTester;
@@ -30,6 +32,7 @@ import java.util.NoSuchElementException;
*
* @author Kurt Alfred Kluever
*/
+ at GwtCompatible(emulated = true)
public class EvictingQueueTest extends TestCase {
public void testCreateWithNegativeSize() throws Exception {
@@ -157,6 +160,7 @@ public class EvictingQueueTest extends TestCase {
assertEquals(1, queue.remainingCapacity());
}
+ @GwtIncompatible("NullPointerTester")
public void testNullPointerExceptions() {
NullPointerTester tester = new NullPointerTester();
tester.testAllPublicStaticMethods(EvictingQueue.class);
diff --git a/guava-tests/test/com/google/common/collect/FauxveridesTest.java b/guava-tests/test/com/google/common/collect/FauxveridesTest.java
index c1d861c..10c71f6 100644
--- a/guava-tests/test/com/google/common/collect/FauxveridesTest.java
+++ b/guava-tests/test/com/google/common/collect/FauxveridesTest.java
@@ -17,8 +17,8 @@
package com.google.common.collect;
import static com.google.common.collect.Lists.transform;
+import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.newHashSet;
-import static com.google.common.collect.Sets.newTreeSet;
import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isStatic;
@@ -32,8 +32,8 @@ import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -112,10 +112,11 @@ public class FauxveridesTest extends TestCase {
private void doHasAllFauxveridesTest(Class<?> descendant, Class<?> ancestor) {
Set<MethodSignature> required = getAllRequiredToFauxveride(ancestor);
Set<MethodSignature> found = getAllFauxveridden(descendant, ancestor);
- required.removeAll(found);
-
- assertEquals("Must hide public static methods from ancestor classes",
- Collections.emptySet(), newTreeSet(required));
+ Set<MethodSignature> missing = ImmutableSortedSet.copyOf(difference(required, found));
+ if (!missing.isEmpty()) {
+ fail(rootLocaleFormat("%s should hide the public static methods declared in %s: %s",
+ descendant.getSimpleName(), ancestor.getSimpleName(), missing));
+ }
}
private static Set<MethodSignature> getAllRequiredToFauxveride(Class<?> ancestor) {
@@ -196,7 +197,7 @@ public class FauxveridesTest extends TestCase {
}
@Override public String toString() {
- return String.format("%s%s(%s)",
+ return rootLocaleFormat("%s%s(%s)",
typeSignature, name, getTypesString(parameterTypes));
}
@@ -287,4 +288,8 @@ public class FauxveridesTest extends TestCase {
return from.toString();
}
};
+
+ private static String rootLocaleFormat(String format, Object... args) {
+ return String.format(Locale.ROOT, format, args);
+ }
}
diff --git a/guava-tests/test/com/google/common/collect/FilteredCollectionsTest.java b/guava-tests/test/com/google/common/collect/FilteredCollectionsTest.java
index 579d378..59d5538 100644
--- a/guava-tests/test/com/google/common/collect/FilteredCollectionsTest.java
+++ b/guava-tests/test/com/google/common/collect/FilteredCollectionsTest.java
@@ -101,7 +101,7 @@ public class FilteredCollectionsTest extends TestCase {
target.add(4);
C addThenFilter = filter(createUnfiltered(target), EVEN);
- assertThat(filterThenAdd).has().exactlyAs(addThenFilter);
+ assertThat(filterThenAdd).containsExactlyElementsIn(addThenFilter);
}
}
@@ -157,7 +157,7 @@ public class FilteredCollectionsTest extends TestCase {
} catch (IllegalArgumentException expected) {
}
- assertThat(filteredToModify).has().exactlyAs(filtered);
+ assertThat(filteredToModify).containsExactlyElementsIn(filtered);
}
}
@@ -191,7 +191,7 @@ public class FilteredCollectionsTest extends TestCase {
Predicates.not(Predicates.and(EVEN, PRIME_DIGIT)));
filtered2.clear();
- assertThat(unfiltered).has().exactlyAs(inverseFiltered);
+ assertThat(unfiltered).containsExactlyElementsIn(inverseFiltered);
}
}
}
@@ -328,7 +328,9 @@ public class FilteredCollectionsTest extends TestCase {
NavigableSet<Integer> filtered = filter(createUnfiltered(contents), EVEN);
NavigableSet<Integer> unfiltered = createUnfiltered(filtered);
- assertThat(filtered.descendingSet()).has().exactlyAs(unfiltered.descendingSet()).inOrder();
+ assertThat(filtered.descendingSet())
+ .containsExactlyElementsIn(unfiltered.descendingSet())
+ .inOrder();
}
}
diff --git a/guava-tests/test/com/google/common/collect/FluentIterableTest.java b/guava-tests/test/com/google/common/collect/FluentIterableTest.java
index 674c642..af70b4c 100644
--- a/guava-tests/test/com/google/common/collect/FluentIterableTest.java
+++ b/guava-tests/test/com/google/common/collect/FluentIterableTest.java
@@ -24,7 +24,6 @@ import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
-import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.testing.IteratorFeature;
@@ -49,6 +48,7 @@ import javax.annotation.Nullable;
*
* @author Marcin Mikosik
*/
+ at SuppressWarnings("CheckReturnValue")
@GwtCompatible(emulated = true)
public class FluentIterableTest extends TestCase {
@@ -221,7 +221,7 @@ public class FluentIterableTest extends TestCase {
FluentIterable<TypeA> alist =
FluentIterable.from(asList(new TypeA(), new TypeA(), hasBoth, new TypeA()));
Iterable<TypeB> blist = alist.filter(TypeB.class);
- assertThat(blist).iteratesAs(hasBoth);
+ assertThat(blist).containsExactly(hasBoth).inOrder();
}
public void testAnyMatch() {
@@ -250,10 +250,10 @@ public class FluentIterableTest extends TestCase {
public void testFirstMatch() {
FluentIterable<String> iterable = FluentIterable.from(Lists.newArrayList("cool", "pants"));
- assertEquals(Optional.of("cool"), iterable.firstMatch(Predicates.equalTo("cool")));
- assertEquals(Optional.of("pants"), iterable.firstMatch(Predicates.equalTo("pants")));
- assertEquals(Optional.absent(), iterable.firstMatch(Predicates.alwaysFalse()));
- assertEquals(Optional.of("cool"), iterable.firstMatch(Predicates.alwaysTrue()));
+ assertThat(iterable.firstMatch(Predicates.equalTo("cool"))).hasValue("cool");
+ assertThat(iterable.firstMatch(Predicates.equalTo("pants"))).hasValue("pants");
+ assertThat(iterable.firstMatch(Predicates.alwaysFalse())).isAbsent();
+ assertThat(iterable.firstMatch(Predicates.alwaysTrue())).hasValue("cool");
}
private static final class IntegerValueOfFunction implements Function<String, Integer> {
@@ -334,7 +334,7 @@ public class FluentIterableTest extends TestCase {
public void testFirst_list() {
List<String> list = Lists.newArrayList("a", "b", "c");
- assertEquals("a", FluentIterable.from(list).first().get());
+ assertThat(FluentIterable.from(list).first()).hasValue("a");
}
public void testFirst_null() {
@@ -348,32 +348,32 @@ public class FluentIterableTest extends TestCase {
public void testFirst_emptyList() {
List<String> list = Collections.emptyList();
- assertEquals(Optional.absent(), FluentIterable.from(list).first());
+ assertThat(FluentIterable.from(list).first()).isAbsent();
}
public void testFirst_sortedSet() {
SortedSet<String> sortedSet = ImmutableSortedSet.of("b", "c", "a");
- assertEquals("a", FluentIterable.from(sortedSet).first().get());
+ assertThat(FluentIterable.from(sortedSet).first()).hasValue("a");
}
public void testFirst_emptySortedSet() {
SortedSet<String> sortedSet = ImmutableSortedSet.of();
- assertEquals(Optional.absent(), FluentIterable.from(sortedSet).first());
+ assertThat(FluentIterable.from(sortedSet).first()).isAbsent();
}
public void testFirst_iterable() {
Set<String> set = ImmutableSet.of("a", "b", "c");
- assertEquals("a", FluentIterable.from(set).first().get());
+ assertThat(FluentIterable.from(set).first()).hasValue("a");
}
public void testFirst_emptyIterable() {
Set<String> set = Sets.newHashSet();
- assertEquals(Optional.absent(), FluentIterable.from(set).first());
+ assertThat(FluentIterable.from(set).first()).isAbsent();
}
public void testLast_list() {
List<String> list = Lists.newArrayList("a", "b", "c");
- assertEquals("c", FluentIterable.from(list).last().get());
+ assertThat(FluentIterable.from(list).last()).hasValue("c");
}
public void testLast_null() {
@@ -387,27 +387,27 @@ public class FluentIterableTest extends TestCase {
public void testLast_emptyList() {
List<String> list = Collections.emptyList();
- assertEquals(Optional.absent(), FluentIterable.from(list).last());
+ assertThat(FluentIterable.from(list).last()).isAbsent();
}
public void testLast_sortedSet() {
SortedSet<String> sortedSet = ImmutableSortedSet.of("b", "c", "a");
- assertEquals("c", FluentIterable.from(sortedSet).last().get());
+ assertThat(FluentIterable.from(sortedSet).last()).hasValue("c");
}
public void testLast_emptySortedSet() {
SortedSet<String> sortedSet = ImmutableSortedSet.of();
- assertEquals(Optional.absent(), FluentIterable.from(sortedSet).last());
+ assertThat(FluentIterable.from(sortedSet).last()).isAbsent();
}
public void testLast_iterable() {
Set<String> set = ImmutableSet.of("a", "b", "c");
- assertEquals("c", FluentIterable.from(set).last().get());
+ assertThat(FluentIterable.from(set).last()).hasValue("c");
}
public void testLast_emptyIterable() {
Set<String> set = Sets.newHashSet();
- assertEquals(Optional.absent(), FluentIterable.from(set).last());
+ assertThat(FluentIterable.from(set).last()).isAbsent();
}
public void testSkip_simple() {
@@ -482,7 +482,7 @@ public class FluentIterableTest extends TestCase {
FluentIterable<String> tail = FluentIterable.from(set).skip(1);
set.remove("b");
set.addAll(Lists.newArrayList("X", "Y", "Z"));
- assertThat(tail).iteratesAs("c", "X", "Y", "Z");
+ assertThat(tail).containsExactly("c", "X", "Y", "Z").inOrder();
}
public void testSkip_structurallyModifiedSkipSomeList() throws Exception {
@@ -490,7 +490,7 @@ public class FluentIterableTest extends TestCase {
FluentIterable<String> tail = FluentIterable.from(list).skip(1);
list.subList(1, 3).clear();
list.addAll(0, Lists.newArrayList("X", "Y", "Z"));
- assertThat(tail).iteratesAs("Y", "Z", "a");
+ assertThat(tail).containsExactly("Y", "Z", "a").inOrder();
}
public void testSkip_structurallyModifiedSkipAll() throws Exception {
@@ -560,11 +560,11 @@ public class FluentIterableTest extends TestCase {
}
public void testToSet() {
- assertThat(fluent(1, 2, 3, 4).toSet()).has().exactly(1, 2, 3, 4).inOrder();
+ assertThat(fluent(1, 2, 3, 4).toSet()).containsExactly(1, 2, 3, 4).inOrder();
}
public void testToSet_removeDuplicates() {
- assertThat(fluent(1, 2, 1, 2).toSet()).has().exactly(1, 2).inOrder();
+ assertThat(fluent(1, 2, 1, 2).toSet()).containsExactly(1, 2).inOrder();
}
public void testToSet_empty() {
@@ -573,17 +573,25 @@ public class FluentIterableTest extends TestCase {
public void testToSortedSet() {
assertThat(fluent(1, 4, 2, 3).toSortedSet(Ordering.<Integer>natural().reverse()))
- .has().exactly(4, 3, 2, 1).inOrder();
+ .containsExactly(4, 3, 2, 1).inOrder();
}
public void testToSortedSet_removeDuplicates() {
assertThat(fluent(1, 4, 1, 3).toSortedSet(Ordering.<Integer>natural().reverse()))
- .has().exactly(4, 3, 1).inOrder();
+ .containsExactly(4, 3, 1).inOrder();
+ }
+
+ public void testToMultiset() {
+ assertThat(fluent(1, 2, 1, 3, 2, 4).toMultiset()).containsExactly(1, 1, 2, 2, 3, 4).inOrder();
+ }
+
+ public void testToMultiset_empty() {
+ assertThat(fluent().toMultiset()).isEmpty();
}
public void testToMap() {
assertThat(fluent(1, 2, 3).toMap(Functions.toStringFunction()).entrySet())
- .has().exactly(
+ .containsExactly(
Maps.immutableEntry(1, "1"),
Maps.immutableEntry(2, "2"),
Maps.immutableEntry(3, "3")).inOrder();
@@ -690,17 +698,17 @@ public class FluentIterableTest extends TestCase {
public void testCopyInto_List() {
assertThat(fluent(1, 3, 5).copyInto(Lists.newArrayList(1, 2)))
- .has().exactly(1, 2, 1, 3, 5).inOrder();
+ .containsExactly(1, 2, 1, 3, 5).inOrder();
}
public void testCopyInto_Set() {
assertThat(fluent(1, 3, 5).copyInto(Sets.newHashSet(1, 2)))
- .has().exactly(1, 2, 3, 5);
+ .containsExactly(1, 2, 3, 5);
}
public void testCopyInto_SetAllDuplicates() {
assertThat(fluent(1, 3, 5).copyInto(Sets.newHashSet(1, 2, 3, 5)))
- .has().exactly(1, 2, 3, 5);
+ .containsExactly(1, 2, 3, 5);
}
public void testCopyInto_NonCollection() {
@@ -715,7 +723,7 @@ public class FluentIterableTest extends TestCase {
};
assertThat(FluentIterable.from(iterable).copyInto(list))
- .has().exactly(1, 2, 3, 9, 8, 7).inOrder();
+ .containsExactly(1, 2, 3, 9, 8, 7).inOrder();
}
public void testJoin() {
diff --git a/guava-tests/test/com/google/common/collect/ForwardingListTest.java b/guava-tests/test/com/google/common/collect/ForwardingListTest.java
index a6a71b4..d292768 100644
--- a/guava-tests/test/com/google/common/collect/ForwardingListTest.java
+++ b/guava-tests/test/com/google/common/collect/ForwardingListTest.java
@@ -16,6 +16,8 @@
package com.google.common.collect;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.collect.testing.ListTestSuiteBuilder;
import com.google.common.collect.testing.TestStringListGenerator;
import com.google.common.collect.testing.features.CollectionFeature;
@@ -305,7 +307,7 @@ public class ForwardingListTest extends ForwardingTestCase {
}
public void testRandomAccess() {
- assertFalse(forward instanceof RandomAccess);
+ assertThat(forward).isNotInstanceOf(RandomAccess.class);
}
public void testToString() {
diff --git a/guava-tests/test/com/google/common/collect/ForwardingMultisetTest.java b/guava-tests/test/com/google/common/collect/ForwardingMultisetTest.java
index 0cf4e4a..af36238 100644
--- a/guava-tests/test/com/google/common/collect/ForwardingMultisetTest.java
+++ b/guava-tests/test/com/google/common/collect/ForwardingMultisetTest.java
@@ -385,6 +385,7 @@ public class ForwardingMultisetTest extends ForwardingTestCase {
assertEquals("[setCount(Object,int,int)]", getCalls());
}
+ @SuppressUnderAndroid // Proxy problem, perhaps around SortedMultisetBridge?
public void testElementSet() {
forward().elementSet();
assertEquals("[elementSet]", getCalls());
diff --git a/guava-tests/test/com/google/common/collect/ForwardingNavigableMapTest.java b/guava-tests/test/com/google/common/collect/ForwardingNavigableMapTest.java
index d10ff09..6889376 100644
--- a/guava-tests/test/com/google/common/collect/ForwardingNavigableMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ForwardingNavigableMapTest.java
@@ -249,7 +249,7 @@ public class ForwardingNavigableMapTest extends ForwardingSortedMapTest {
CollectionFeature.KNOWN_ORDER, MapFeature.ALLOWS_NULL_VALUES,
CollectionFeature.SUPPORTS_ITERATOR_REMOVE, MapFeature.GENERAL_PURPOSE)
.createTestSuite());
- // TODO(user): add forwarding-to-ImmutableSortedMap test
+ // TODO(lowasser): add forwarding-to-ImmutableSortedMap test
return suite;
}
diff --git a/guava-tests/test/com/google/common/collect/HashBiMapTest.java b/guava-tests/test/com/google/common/collect/HashBiMapTest.java
index b547bc1..d2035fb 100644
--- a/guava-tests/test/com/google/common/collect/HashBiMapTest.java
+++ b/guava-tests/test/com/google/common/collect/HashBiMapTest.java
@@ -16,6 +16,8 @@
package com.google.common.collect;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.testing.features.CollectionFeature;
@@ -60,6 +62,7 @@ public class HashBiMapTest extends TestCase {
.withFeatures(CollectionSize.ANY,
CollectionFeature.SERIALIZABLE,
CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
+ CollectionFeature.KNOWN_ORDER,
MapFeature.ALLOWS_NULL_KEYS,
MapFeature.ALLOWS_NULL_VALUES,
MapFeature.ALLOWS_ANY_NULL_QUERIES,
@@ -126,4 +129,102 @@ public class HashBiMapTest extends TestCase {
iterator.remove(); // removes the updated entry
assertTrue(map.isEmpty());
}
+
+ @GwtIncompatible("insertion order currently not preserved in GWT")
+ public void testInsertionOrder() {
+ BiMap<String, Integer> map = HashBiMap.create();
+ map.put("foo", 1);
+ map.put("bar", 2);
+ map.put("quux", 3);
+ assertThat(map.entrySet()).containsExactly(
+ Maps.immutableEntry("foo", 1),
+ Maps.immutableEntry("bar", 2),
+ Maps.immutableEntry("quux", 3)).inOrder();
+ }
+
+ @GwtIncompatible("insertion order currently not preserved in GWT")
+ public void testInsertionOrderAfterRemoveFirst() {
+ BiMap<String, Integer> map = HashBiMap.create();
+ map.put("foo", 1);
+ map.put("bar", 2);
+ map.put("quux", 3);
+
+ map.remove("foo");
+ assertThat(map.entrySet()).containsExactly(
+ Maps.immutableEntry("bar", 2),
+ Maps.immutableEntry("quux", 3)).inOrder();
+ }
+
+ @GwtIncompatible("insertion order currently not preserved in GWT")
+ public void testInsertionOrderAfterRemoveMiddle() {
+ BiMap<String, Integer> map = HashBiMap.create();
+ map.put("foo", 1);
+ map.put("bar", 2);
+ map.put("quux", 3);
+
+ map.remove("bar");
+ assertThat(map.entrySet()).containsExactly(
+ Maps.immutableEntry("foo", 1),
+ Maps.immutableEntry("quux", 3)).inOrder();
+ }
+
+ @GwtIncompatible("insertion order currently not preserved in GWT")
+ public void testInsertionOrderAfterRemoveLast() {
+ BiMap<String, Integer> map = HashBiMap.create();
+ map.put("foo", 1);
+ map.put("bar", 2);
+ map.put("quux", 3);
+
+ map.remove("quux");
+ assertThat(map.entrySet()).containsExactly(
+ Maps.immutableEntry("foo", 1),
+ Maps.immutableEntry("bar", 2)).inOrder();
+ }
+
+ @GwtIncompatible("insertion order currently not preserved in GWT")
+ public void testInsertionOrderAfterForcePut() {
+ BiMap<String, Integer> map = HashBiMap.create();
+ map.put("foo", 1);
+ map.put("bar", 2);
+ map.put("quux", 3);
+
+ map.forcePut("quux", 1);
+ assertThat(map.entrySet()).containsExactly(
+ Maps.immutableEntry("bar", 2),
+ Maps.immutableEntry("quux", 1)).inOrder();
+ }
+
+ @GwtIncompatible("insertion order currently not preserved in GWT")
+ public void testInsertionOrderAfterInverseForcePut() {
+ BiMap<String, Integer> map = HashBiMap.create();
+ map.put("foo", 1);
+ map.put("bar", 2);
+ map.put("quux", 3);
+
+ map.inverse().forcePut(1, "quux");
+ assertThat(map.entrySet()).containsExactly(
+ Maps.immutableEntry("bar", 2),
+ Maps.immutableEntry("quux", 1)).inOrder();
+ }
+
+ @GwtIncompatible("insertion order currently not preserved in GWT")
+ public void testInverseInsertionOrderAfterInverseForcePut() {
+ BiMap<String, Integer> map = HashBiMap.create();
+ map.put("foo", 1);
+ map.put("bar", 2);
+ map.put("quux", 3);
+
+ map.inverse().forcePut(1, "quux");
+ assertThat(map.inverse().entrySet()).containsExactly(
+ Maps.immutableEntry(2, "bar"),
+ Maps.immutableEntry(1, "quux")).inOrder();
+ }
+
+ public void testInverseEntrySetValue() {
+ BiMap<Integer, String> map = HashBiMap.create();
+ map.put(1, "one");
+ Entry<String, Integer> inverseEntry = Iterables.getOnlyElement(map.inverse().entrySet());
+ inverseEntry.setValue(2);
+ assertEquals(Integer.valueOf(2), inverseEntry.getValue());
+ }
}
diff --git a/guava-tests/test/com/google/common/collect/ImmutableBiMapTest.java b/guava-tests/test/com/google/common/collect/ImmutableBiMapTest.java
index 8609e05..69534e9 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableBiMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableBiMapTest.java
@@ -26,6 +26,7 @@ import com.google.common.collect.testing.MapInterfaceTest;
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
import com.google.common.collect.testing.features.MapFeature;
+import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapCopyOfEntriesGenerator;
import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapCopyOfGenerator;
import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapGenerator;
import com.google.common.collect.testing.google.BiMapInverseTester;
@@ -71,13 +72,22 @@ public class ImmutableBiMapTest extends TestCase {
.suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods())
.createTestSuite());
suite.addTest(BiMapTestSuiteBuilder.using(new ImmutableBiMapCopyOfGenerator())
- .named("ImmutableBiMap.copyOf")
+ .named("ImmutableBiMap.copyOf[Map]")
.withFeatures(CollectionSize.ANY,
CollectionFeature.SERIALIZABLE,
CollectionFeature.KNOWN_ORDER,
MapFeature.ALLOWS_ANY_NULL_QUERIES)
.suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods())
.createTestSuite());
+ suite.addTest(BiMapTestSuiteBuilder.using(new ImmutableBiMapCopyOfEntriesGenerator())
+ .named("ImmutableBiMap.copyOf[Iterable<Entry>]")
+ .withFeatures(CollectionSize.ANY,
+ CollectionFeature.SERIALIZABLE,
+ CollectionFeature.KNOWN_ORDER,
+ MapFeature.REJECTS_DUPLICATES_AT_CREATION,
+ MapFeature.ALLOWS_ANY_NULL_QUERIES)
+ .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods())
+ .createTestSuite());
return suite;
}
@@ -172,6 +182,13 @@ public class ImmutableBiMapTest extends TestCase {
assertMapEquals(map.inverse(), 1, "one");
}
+ public void testBuilder_withImmutableEntry() {
+ ImmutableBiMap<String, Integer> map = new Builder<String, Integer>()
+ .put(Maps.immutableEntry("one", 1))
+ .build();
+ assertMapEquals(map, "one", 1);
+ }
+
public void testBuilder() {
ImmutableBiMap<String, Integer> map
= ImmutableBiMap.<String, Integer>builder()
@@ -187,6 +204,41 @@ public class ImmutableBiMapTest extends TestCase {
1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
}
+ public void testBuilder_orderEntriesByValue() {
+ ImmutableBiMap<String, Integer> map =
+ ImmutableBiMap.<String, Integer>builder()
+ .orderEntriesByValue(Ordering.natural())
+ .put("three", 3)
+ .put("one", 1)
+ .put("five", 5)
+ .put("four", 4)
+ .put("two", 2)
+ .build();
+ assertMapEquals(map,
+ "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
+ assertMapEquals(map.inverse(),
+ 1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
+ }
+
+ public void testBuilder_orderEntriesByValueAfterExactSizeBuild() {
+ ImmutableBiMap.Builder<String, Integer> builder =
+ new ImmutableBiMap.Builder<String, Integer>(2).put("four", 4).put("one", 1);
+ ImmutableMap<String, Integer> keyOrdered = builder.build();
+ ImmutableMap<String, Integer> valueOrdered =
+ builder.orderEntriesByValue(Ordering.natural()).build();
+ assertMapEquals(keyOrdered, "four", 4, "one", 1);
+ assertMapEquals(valueOrdered, "one", 1, "four", 4);
+ }
+
+ public void testBuilder_orderEntriesByValue_usedTwiceFails() {
+ ImmutableBiMap.Builder<String, Integer> builder = new Builder<String, Integer>()
+ .orderEntriesByValue(Ordering.natural());
+ try {
+ builder.orderEntriesByValue(Ordering.natural());
+ fail("Expected IllegalStateException");
+ } catch (IllegalStateException expected) {}
+ }
+
public void testBuilderPutAllWithEmptyMap() {
ImmutableBiMap<String, Integer> map = new Builder<String, Integer>()
.putAll(Collections.<String, Integer>emptyMap())
@@ -276,7 +328,7 @@ public class ImmutableBiMapTest extends TestCase {
builder.build();
fail();
} catch (IllegalArgumentException expected) {
- assertTrue(expected.getMessage().contains("one"));
+ assertThat(expected.getMessage()).contains("one");
}
}
@@ -349,7 +401,7 @@ public class ImmutableBiMapTest extends TestCase {
ImmutableBiMap.of("one", 1, "one", 1);
fail();
} catch (IllegalArgumentException expected) {
- assertTrue(expected.getMessage().contains("one"));
+ assertThat(expected.getMessage()).contains("one");
}
}
@@ -423,7 +475,7 @@ public class ImmutableBiMapTest extends TestCase {
ImmutableBiMap.copyOf(map);
fail();
} catch (IllegalArgumentException expected) {
- assertTrue(expected.getMessage().contains("1"));
+ assertThat(expected.getMessage()).contains("1");
}
}
}
@@ -445,7 +497,7 @@ public class ImmutableBiMapTest extends TestCase {
ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4));
Set<String> keys = bimap.keySet();
assertEquals(Sets.newHashSet("one", "two", "three", "four"), keys);
- assertThat(keys).has().exactly("one", "two", "three", "four").inOrder();
+ assertThat(keys).containsExactly("one", "two", "three", "four").inOrder();
}
public void testValues() {
@@ -453,7 +505,7 @@ public class ImmutableBiMapTest extends TestCase {
ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4));
Set<Integer> values = bimap.values();
assertEquals(Sets.newHashSet(1, 2, 3, 4), values);
- assertThat(values).has().exactly(1, 2, 3, 4).inOrder();
+ assertThat(values).containsExactly(1, 2, 3, 4).inOrder();
}
public void testDoubleInverse() {
diff --git a/guava-tests/test/com/google/common/collect/ImmutableClassToInstanceMapTest.java b/guava-tests/test/com/google/common/collect/ImmutableClassToInstanceMapTest.java
index 74ca804..4434f8c 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableClassToInstanceMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableClassToInstanceMapTest.java
@@ -22,6 +22,7 @@ import com.google.common.collect.testing.TestMapGenerator;
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
import com.google.common.collect.testing.features.MapFeature;
+import com.google.common.testing.SerializableTester;
import junit.framework.Test;
import junit.framework.TestCase;
@@ -70,14 +71,29 @@ public class ImmutableClassToInstanceMapTest extends TestCase {
return suite;
}
+
+ public void testSerialization_empty() {
+ assertSame(ImmutableClassToInstanceMap.of(),
+ SerializableTester.reserialize(ImmutableClassToInstanceMap.of()));
+ }
public void testCopyOf_map_empty() {
Map<Class<?>, Object> in = Collections.emptyMap();
ClassToInstanceMap<Object> map = ImmutableClassToInstanceMap.copyOf(in);
assertTrue(map.isEmpty());
-
+ assertSame(map, ImmutableClassToInstanceMap.of());
assertSame(map, ImmutableClassToInstanceMap.copyOf(map));
}
+
+ public void testOf_zero() {
+ assertTrue(ImmutableClassToInstanceMap.of().isEmpty());
+ }
+
+ public void testOf_one() {
+ ImmutableClassToInstanceMap<Number> map =
+ ImmutableClassToInstanceMap.of(int.class, 1);
+ assertEquals(1, map.size());
+ }
public void testCopyOf_map_valid() {
Map<Class<? extends Number>, Number> in = Maps.newHashMap();
diff --git a/guava-tests/test/com/google/common/collect/ImmutableEnumMapTest.java b/guava-tests/test/com/google/common/collect/ImmutableEnumMapTest.java
index e8244a9..fe641d4 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableEnumMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableEnumMapTest.java
@@ -16,6 +16,8 @@
package com.google.common.collect;
+import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_QUERIES;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
@@ -24,7 +26,6 @@ import com.google.common.collect.testing.AnEnum;
import com.google.common.collect.testing.Helpers;
import com.google.common.collect.testing.MapTestSuiteBuilder;
import com.google.common.collect.testing.TestEnumMapGenerator;
-import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
import junit.framework.Test;
@@ -58,8 +59,8 @@ public class ImmutableEnumMapTest extends TestCase {
suite.addTest(MapTestSuiteBuilder.using(new ImmutableEnumMapGenerator())
.named("Maps.immutableEnumMap")
.withFeatures(CollectionSize.ANY,
- CollectionFeature.SERIALIZABLE,
- CollectionFeature.ALLOWS_NULL_QUERIES)
+ SERIALIZABLE,
+ ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTestSuite(ImmutableEnumMapTest.class);
return suite;
@@ -74,7 +75,7 @@ public class ImmutableEnumMapTest extends TestCase {
ImmutableMap<AnEnum, String> map = Maps.immutableEnumMap(
ImmutableMap.of(AnEnum.C, "c", AnEnum.A, "a", AnEnum.E, "e"));
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
Helpers.mapEntry(AnEnum.A, "a"),
Helpers.mapEntry(AnEnum.C, "c"),
Helpers.mapEntry(AnEnum.E, "e")).inOrder();
diff --git a/guava-tests/test/com/google/common/collect/ImmutableListMultimapTest.java b/guava-tests/test/com/google/common/collect/ImmutableListMultimapTest.java
index b632735..4360f66 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableListMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableListMultimapTest.java
@@ -16,14 +16,15 @@
package com.google.common.collect;
+import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_ANY_NULL_QUERIES;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.ImmutableListMultimap.Builder;
-import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
-import com.google.common.collect.testing.features.MapFeature;
import com.google.common.collect.testing.google.ListMultimapTestSuiteBuilder;
import com.google.common.collect.testing.google.TestStringListMultimapGenerator;
import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
@@ -56,6 +57,13 @@ public class ImmutableListMultimapTest extends TestCase {
return builder.build();
}
}
+ public static class ImmutableListMultimapCopyOfEntriesGenerator
+ extends TestStringListMultimapGenerator {
+ @Override
+ protected ListMultimap<String, String> create(Entry<String, String>[] entries) {
+ return ImmutableListMultimap.copyOf(Arrays.asList(entries));
+ }
+ }
@GwtIncompatible("suite")
public static Test suite() {
@@ -63,11 +71,20 @@ public class ImmutableListMultimapTest extends TestCase {
suite.addTest(ListMultimapTestSuiteBuilder.using(new ImmutableListMultimapGenerator())
.named("ImmutableListMultimap")
.withFeatures(
- MapFeature.ALLOWS_ANY_NULL_QUERIES,
- CollectionFeature.SERIALIZABLE,
- CollectionFeature.KNOWN_ORDER,
+ ALLOWS_ANY_NULL_QUERIES,
+ SERIALIZABLE,
+ KNOWN_ORDER,
CollectionSize.ANY)
.createTestSuite());
+ suite.addTest(ListMultimapTestSuiteBuilder.using(
+ new ImmutableListMultimapCopyOfEntriesGenerator())
+ .named("ImmutableListMultimap.copyOf[Iterable<Entry>]")
+ .withFeatures(
+ ALLOWS_ANY_NULL_QUERIES,
+ SERIALIZABLE,
+ KNOWN_ORDER,
+ CollectionSize.ANY)
+ .createTestSuite());
suite.addTestSuite(ImmutableListMultimapTest.class);
return suite;
}
@@ -263,10 +280,10 @@ public class ImmutableListMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("b", 6);
ImmutableListMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
- assertThat(multimap.values()).has().exactly(2, 4, 3, 6, 5, 2).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("b")).has().exactly(3, 6).inOrder();
+ assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+ assertThat(multimap.values()).containsExactly(2, 4, 3, 6, 5, 2).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("b")).containsExactly(3, 6).inOrder();
}
public void testBuilderOrderKeysByDuplicates() {
@@ -285,10 +302,10 @@ public class ImmutableListMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("bb", 6);
ImmutableListMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("d", "a", "bb", "cc").inOrder();
- assertThat(multimap.values()).has().exactly(2, 5, 2, 3, 6, 4).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("bb")).has().exactly(3, 6).inOrder();
+ assertThat(multimap.keySet()).containsExactly("d", "a", "bb", "cc").inOrder();
+ assertThat(multimap.values()).containsExactly(2, 5, 2, 3, 6, 4).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("bb")).containsExactly(3, 6).inOrder();
}
public void testBuilderOrderValuesBy() {
@@ -302,10 +319,10 @@ public class ImmutableListMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("b", 6);
ImmutableListMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("b", "d", "a", "c").inOrder();
- assertThat(multimap.values()).has().exactly(6, 3, 2, 5, 2, 4).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+ assertThat(multimap.keySet()).containsExactly("b", "d", "a", "c").inOrder();
+ assertThat(multimap.values()).containsExactly(6, 3, 2, 5, 2, 4).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
}
public void testBuilderOrderKeysAndValuesBy() {
@@ -320,10 +337,10 @@ public class ImmutableListMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("b", 6);
ImmutableListMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
- assertThat(multimap.values()).has().exactly(2, 4, 6, 3, 5, 2).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+ assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+ assertThat(multimap.values()).containsExactly(2, 4, 6, 3, 5, 2).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
}
public void testCopyOf() {
diff --git a/guava-tests/test/com/google/common/collect/ImmutableListTest.java b/guava-tests/test/com/google/common/collect/ImmutableListTest.java
index 57c64d2..d7600ab 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableListTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableListTest.java
@@ -19,6 +19,8 @@ package com.google.common.collect;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Iterables.unmodifiableIterable;
import static com.google.common.collect.Sets.newHashSet;
+import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_QUERIES;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
import static java.lang.reflect.Proxy.newProxyInstance;
import static java.util.Arrays.asList;
@@ -28,7 +30,6 @@ import com.google.common.collect.testing.Helpers;
import com.google.common.collect.testing.ListTestSuiteBuilder;
import com.google.common.collect.testing.MinimalCollection;
import com.google.common.collect.testing.MinimalIterable;
-import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
import com.google.common.collect.testing.google.ListGenerators.BuilderAddAllListGenerator;
import com.google.common.collect.testing.google.ListGenerators.BuilderReversedListGenerator;
@@ -72,54 +73,54 @@ public class ImmutableListTest extends TestCase {
suite.addTest(ListTestSuiteBuilder.using(new ImmutableListOfGenerator())
.named("ImmutableList")
.withFeatures(CollectionSize.ANY,
- CollectionFeature.SERIALIZABLE,
- CollectionFeature.ALLOWS_NULL_QUERIES)
+ SERIALIZABLE,
+ ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(ListTestSuiteBuilder.using(new BuilderAddAllListGenerator())
.named("ImmutableList, built with Builder.add")
.withFeatures(CollectionSize.ANY,
- CollectionFeature.SERIALIZABLE,
- CollectionFeature.ALLOWS_NULL_QUERIES)
+ SERIALIZABLE,
+ ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(ListTestSuiteBuilder.using(new BuilderAddAllListGenerator())
.named("ImmutableList, built with Builder.addAll")
.withFeatures(CollectionSize.ANY,
- CollectionFeature.SERIALIZABLE,
- CollectionFeature.ALLOWS_NULL_QUERIES)
+ SERIALIZABLE,
+ ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(ListTestSuiteBuilder.using(new BuilderReversedListGenerator())
.named("ImmutableList, reversed")
.withFeatures(CollectionSize.ANY,
- CollectionFeature.SERIALIZABLE,
- CollectionFeature.ALLOWS_NULL_QUERIES)
+ SERIALIZABLE,
+ ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(ListTestSuiteBuilder.using(
new ImmutableListHeadSubListGenerator())
.named("ImmutableList, head subList")
.withFeatures(CollectionSize.ANY,
- CollectionFeature.SERIALIZABLE,
- CollectionFeature.ALLOWS_NULL_QUERIES)
+ SERIALIZABLE,
+ ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(ListTestSuiteBuilder.using(
new ImmutableListTailSubListGenerator())
.named("ImmutableList, tail subList")
.withFeatures(CollectionSize.ANY,
- CollectionFeature.SERIALIZABLE,
- CollectionFeature.ALLOWS_NULL_QUERIES)
+ SERIALIZABLE,
+ ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(ListTestSuiteBuilder.using(
new ImmutableListMiddleSubListGenerator())
.named("ImmutableList, middle subList")
.withFeatures(CollectionSize.ANY,
- CollectionFeature.SERIALIZABLE,
- CollectionFeature.ALLOWS_NULL_QUERIES)
+ SERIALIZABLE,
+ ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(ListTestSuiteBuilder.using(
new UnhashableElementsImmutableListGenerator())
.suppressing(ListHashCodeTester.getHashCodeMethod())
.named("ImmutableList, unhashable values")
.withFeatures(CollectionSize.ANY,
- CollectionFeature.ALLOWS_NULL_QUERIES)
+ ALLOWS_NULL_QUERIES)
.createTestSuite());
return suite;
}
diff --git a/guava-tests/test/com/google/common/collect/ImmutableMapTest.java b/guava-tests/test/com/google/common/collect/ImmutableMapTest.java
index e79ab50..749dc4a 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableMapTest.java
@@ -34,6 +34,7 @@ import com.google.common.collect.testing.UnhashableObject;
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
import com.google.common.collect.testing.features.MapFeature;
+import com.google.common.collect.testing.google.MapGenerators.ImmutableMapCopyOfEntriesGenerator;
import com.google.common.collect.testing.google.MapGenerators.ImmutableMapCopyOfEnumMapGenerator;
import com.google.common.collect.testing.google.MapGenerators.ImmutableMapCopyOfGenerator;
import com.google.common.collect.testing.google.MapGenerators.ImmutableMapEntryListGenerator;
@@ -87,7 +88,17 @@ public class ImmutableMapTest extends TestCase {
CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
CollectionFeature.KNOWN_ORDER,
CollectionFeature.ALLOWS_NULL_QUERIES)
- .named("ImmutableMap.copyOf")
+ .named("ImmutableMap.copyOf[Map]")
+ .createTestSuite());
+
+ suite.addTest(MapTestSuiteBuilder.using(new ImmutableMapCopyOfEntriesGenerator())
+ .withFeatures(
+ CollectionSize.ANY,
+ MapFeature.REJECTS_DUPLICATES_AT_CREATION,
+ CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
+ CollectionFeature.KNOWN_ORDER,
+ CollectionFeature.ALLOWS_NULL_QUERIES)
+ .named("ImmutableMap.copyOf[Iterable<Entry>]")
.createTestSuite());
suite.addTest(MapTestSuiteBuilder.using(new ImmutableMapCopyOfEnumMapGenerator())
@@ -228,14 +239,14 @@ public class ImmutableMapTest extends TestCase {
@Override protected Map<Object, Integer> makePopulatedMap() {
Colliders colliders = new Colliders();
return ImmutableMap.of(
- colliders.e0, 0,
- colliders.e1, 1,
- colliders.e2, 2,
- colliders.e3, 3);
+ colliders.e0(), 0,
+ colliders.e1(), 1,
+ colliders.e2(), 2,
+ colliders.e3(), 3);
}
@Override protected Object getKeyNotInPopulatedMap() {
- return new Colliders().e4;
+ return new Colliders().e4();
}
@Override protected Integer getValueNotInPopulatedMap() {
@@ -253,7 +264,7 @@ public class ImmutableMapTest extends TestCase {
@Override protected Map<Integer, UnhashableObject> makePopulatedMap() {
Unhashables unhashables = new Unhashables();
return ImmutableMap.of(
- 0, unhashables.e0, 1, unhashables.e1, 2, unhashables.e2);
+ 0, unhashables.e0(), 1, unhashables.e1(), 2, unhashables.e2());
}
@Override protected Integer getKeyNotInPopulatedMap() {
@@ -261,7 +272,7 @@ public class ImmutableMapTest extends TestCase {
}
@Override protected UnhashableObject getValueNotInPopulatedMap() {
- return new Unhashables().e3;
+ return new Unhashables().e3();
}
}
@@ -270,7 +281,7 @@ public class ImmutableMapTest extends TestCase {
extends MapTestsWithUnhashableValues {
@Override protected Map<Integer, UnhashableObject> makePopulatedMap() {
Unhashables unhashables = new Unhashables();
- return ImmutableMap.of(0, unhashables.e0);
+ return ImmutableMap.of(0, unhashables.e0());
}
}
@@ -300,6 +311,39 @@ public class ImmutableMapTest extends TestCase {
"one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
}
+ public void testBuilder_orderEntriesByValue() {
+ ImmutableMap<String, Integer> map = new Builder<String, Integer>()
+ .orderEntriesByValue(Ordering.natural())
+ .put("three", 3)
+ .put("one", 1)
+ .put("five", 5)
+ .put("four", 4)
+ .put("two", 2)
+ .build();
+ assertMapEquals(map,
+ "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
+ }
+
+ public void testBuilder_orderEntriesByValueAfterExactSizeBuild() {
+ Builder<String, Integer> builder = new Builder<String, Integer>(2)
+ .put("four", 4)
+ .put("one", 1);
+ ImmutableMap<String, Integer> keyOrdered = builder.build();
+ ImmutableMap<String, Integer> valueOrdered =
+ builder.orderEntriesByValue(Ordering.natural()).build();
+ assertMapEquals(keyOrdered, "four", 4, "one", 1);
+ assertMapEquals(valueOrdered, "one", 1, "four", 4);
+ }
+
+ public void testBuilder_orderEntriesByValue_usedTwiceFails() {
+ ImmutableMap.Builder<String, Integer> builder = new Builder<String, Integer>()
+ .orderEntriesByValue(Ordering.natural());
+ try {
+ builder.orderEntriesByValue(Ordering.natural());
+ fail("Expected IllegalStateException");
+ } catch (IllegalStateException expected) {}
+ }
+
public void testBuilder_withImmutableEntry() {
ImmutableMap<String, Integer> map = new Builder<String, Integer>()
.put(Maps.immutableEntry("one", 1))
diff --git a/guava-tests/test/com/google/common/collect/ImmutableMultimapTest.java b/guava-tests/test/com/google/common/collect/ImmutableMultimapTest.java
index d02359c..5896e15 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableMultimapTest.java
@@ -101,18 +101,18 @@ public class ImmutableMultimapTest extends TestCase {
public void testUnhashableSingletonValue() {
SampleElements<UnhashableObject> unhashables = new Unhashables();
Multimap<Integer, UnhashableObject> multimap = ImmutableMultimap.of(
- 0, unhashables.e0);
+ 0, unhashables.e0());
assertEquals(1, multimap.get(0).size());
- assertTrue(multimap.get(0).contains(unhashables.e0));
+ assertTrue(multimap.get(0).contains(unhashables.e0()));
}
public void testUnhashableMixedValues() {
SampleElements<UnhashableObject> unhashables = new Unhashables();
Multimap<Integer, Object> multimap = ImmutableMultimap.<Integer, Object>of(
- 0, unhashables.e0, 2, "hey you", 0, unhashables.e1);
+ 0, unhashables.e0(), 2, "hey you", 0, unhashables.e1());
assertEquals(2, multimap.get(0).size());
- assertTrue(multimap.get(0).contains(unhashables.e0));
- assertTrue(multimap.get(0).contains(unhashables.e1));
+ assertTrue(multimap.get(0).contains(unhashables.e0()));
+ assertTrue(multimap.get(0).contains(unhashables.e1()));
assertTrue(multimap.get(2).contains("hey you"));
}
diff --git a/guava-tests/test/com/google/common/collect/ImmutableMultisetTest.java b/guava-tests/test/com/google/common/collect/ImmutableMultisetTest.java
index a0ad481..ce2503e 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableMultisetTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableMultisetTest.java
@@ -452,7 +452,7 @@ public class ImmutableMultisetTest extends TestCase {
public void testSerialization_multiple() {
Collection<String> c = ImmutableMultiset.of("a", "b", "a");
Collection<String> copy = SerializableTester.reserializeAndAssert(c);
- assertThat(copy).has().exactly("a", "a", "b").inOrder();
+ assertThat(copy).containsExactly("a", "a", "b").inOrder();
}
@GwtIncompatible("SerializableTester")
@@ -460,7 +460,7 @@ public class ImmutableMultisetTest extends TestCase {
Multiset<String> c = ImmutableMultiset.of("a", "b", "a");
Collection<String> copy =
LenientSerializableTester.reserializeAndAssertLenient(c.elementSet());
- assertThat(copy).has().exactly("a", "b").inOrder();
+ assertThat(copy).containsExactly("a", "b").inOrder();
}
@GwtIncompatible("SerializableTester")
@@ -479,7 +479,7 @@ public class ImmutableMultisetTest extends TestCase {
public void testIterationOrder() {
Collection<String> c = ImmutableMultiset.of("a", "b", "a");
- assertThat(c).has().exactly("a", "a", "b").inOrder();
+ assertThat(c).containsExactly("a", "a", "b").inOrder();
}
public void testMultisetWrites() {
diff --git a/guava-tests/test/com/google/common/collect/ImmutableRangeMapTest.java b/guava-tests/test/com/google/common/collect/ImmutableRangeMapTest.java
index 3d1d7b4..cedb746 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableRangeMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableRangeMapTest.java
@@ -17,6 +17,7 @@ package com.google.common.collect;
import static com.google.common.collect.BoundType.OPEN;
import com.google.common.annotations.GwtIncompatible;
+import com.google.common.testing.SerializableTester;
import junit.framework.TestCase;
@@ -190,7 +191,13 @@ public class ImmutableRangeMapTest extends TestCase {
ImmutableMap<Range<Integer>, Integer> expectedAsMap =
ImmutableMap.of(range1, 1, range2, 2);
ImmutableMap<Range<Integer>, Integer> asMap = rangeMap.asMapOfRanges();
+ ImmutableMap<Range<Integer>, Integer> descendingMap = rangeMap.asDescendingMapOfRanges();
assertEquals(expectedAsMap, asMap);
+ assertEquals(expectedAsMap, descendingMap);
+ SerializableTester.reserializeAndAssert(asMap);
+ SerializableTester.reserializeAndAssert(descendingMap);
+ assertEquals(ImmutableList.copyOf(asMap.entrySet()).reverse(),
+ ImmutableList.copyOf(descendingMap.entrySet()));
for (Range<Integer> query : RANGES) {
assertEquals(expectedAsMap.get(query), asMap.get(query));
@@ -225,4 +232,27 @@ public class ImmutableRangeMapTest extends TestCase {
}
}
}
+
+ public void testSerialization() {
+ ImmutableRangeMap<Integer, Integer> emptyRangeMap = ImmutableRangeMap.of();
+ SerializableTester.reserializeAndAssert(emptyRangeMap);
+
+ ImmutableRangeMap<Integer, Integer> nonEmptyRangeMap =
+ new ImmutableRangeMap.Builder<Integer, Integer>()
+ .put(Range.closed(2, 4), 5)
+ .put(Range.open(6, 7), 3)
+ .put(Range.closedOpen(8, 10), 4)
+ .put(Range.openClosed(15, 17), 2)
+ .build();
+
+ ImmutableMap<Range<Integer>, Integer> test = nonEmptyRangeMap.asMapOfRanges();
+
+ for (Range<Integer> range : test.keySet()) {
+ SerializableTester.reserializeAndAssert(range);
+ }
+
+ SerializableTester.reserializeAndAssert(test.keySet());
+
+ SerializableTester.reserializeAndAssert(nonEmptyRangeMap);
+ }
}
diff --git a/guava-tests/test/com/google/common/collect/ImmutableRangeSetTest.java b/guava-tests/test/com/google/common/collect/ImmutableRangeSetTest.java
index cf7843b..62033c6 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableRangeSetTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableRangeSetTest.java
@@ -154,7 +154,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
public void testAll() {
ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.all();
- assertThat(rangeSet.asRanges()).has().item(Range.<Integer>all());
+ assertThat(rangeSet.asRanges()).contains(Range.<Integer>all());
assertTrue(rangeSet.contains(0));
assertTrue(rangeSet.encloses(Range.<Integer>all()));
assertTrue(rangeSet.enclosesAll(rangeSet));
@@ -164,7 +164,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
public void testSingleBoundedRange() {
ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.of(Range.closedOpen(1, 5));
- assertThat(rangeSet.asRanges()).has().item(Range.closedOpen(1, 5));
+ assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 5));
assertTrue(rangeSet.encloses(Range.closed(3, 4)));
assertTrue(rangeSet.encloses(Range.closedOpen(1, 4)));
@@ -185,7 +185,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
public void testSingleBoundedBelowRange() {
ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.of(Range.greaterThan(2));
- assertThat(rangeSet.asRanges()).has().item(Range.greaterThan(2));
+ assertThat(rangeSet.asRanges()).contains(Range.greaterThan(2));
assertTrue(rangeSet.encloses(Range.closed(3, 4)));
assertTrue(rangeSet.encloses(Range.greaterThan(3)));
@@ -202,7 +202,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
public void testSingleBoundedAboveRange() {
ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.of(Range.atMost(3));
- assertThat(rangeSet.asRanges()).has().item(Range.atMost(3));
+ assertThat(rangeSet.asRanges()).contains(Range.atMost(3));
assertTrue(rangeSet.encloses(Range.closed(2, 3)));
assertTrue(rangeSet.encloses(Range.lessThan(1)));
@@ -221,7 +221,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
.add(Range.closed(5, 8)).add(Range.closedOpen(1, 3)).build();
assertThat(rangeSet.asRanges())
- .has().exactly(Range.closedOpen(1, 3), Range.closed(5, 8)).inOrder();
+ .containsExactly(Range.closedOpen(1, 3), Range.closed(5, 8)).inOrder();
assertTrue(rangeSet.encloses(Range.closed(1, 2)));
assertTrue(rangeSet.encloses(Range.open(5, 8)));
@@ -242,7 +242,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
.add(Range.greaterThan(6)).add(Range.closedOpen(1, 3)).build();
assertThat(rangeSet.asRanges())
- .has().exactly(Range.closedOpen(1, 3), Range.greaterThan(6)).inOrder();
+ .containsExactly(Range.closedOpen(1, 3), Range.greaterThan(6)).inOrder();
assertTrue(rangeSet.encloses(Range.closed(1, 2)));
assertTrue(rangeSet.encloses(Range.open(6, 8)));
@@ -262,7 +262,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
.add(Range.atMost(0)).add(Range.closedOpen(2, 5)).build();
assertThat(rangeSet.asRanges())
- .has().exactly(Range.atMost(0), Range.closedOpen(2, 5)).inOrder();
+ .containsExactly(Range.atMost(0), Range.closedOpen(2, 5)).inOrder();
assertTrue(rangeSet.encloses(Range.closed(2, 4)));
assertTrue(rangeSet.encloses(Range.open(-5, -2)));
@@ -378,6 +378,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
}
SerializableTester.reserializeAndAssert(built);
+ SerializableTester.reserializeAndAssert(built.asRanges());
}
}
@@ -391,7 +392,7 @@ public class ImmutableRangeSetTest extends AbstractRangeSetTest {
ImmutableSortedSet<Integer> expectedSet = ImmutableSortedSet.of(2, 3, 4, 8, 9, 16, 17);
ImmutableSortedSet<Integer> asSet = rangeSet.asSet(DiscreteDomain.integers());
assertEquals(expectedSet, asSet);
- assertThat(asSet).has().exactlyAs(expectedSet).inOrder();
+ assertThat(asSet).containsExactlyElementsIn(expectedSet).inOrder();
assertTrue(asSet.containsAll(expectedSet));
SerializableTester.reserializeAndAssert(asSet);
}
diff --git a/guava-tests/test/com/google/common/collect/ImmutableSetMultimapTest.java b/guava-tests/test/com/google/common/collect/ImmutableSetMultimapTest.java
index cf50625..7a235cd 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableSetMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableSetMultimapTest.java
@@ -16,14 +16,15 @@
package com.google.common.collect;
+import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
+import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE;
+import static com.google.common.collect.testing.features.MapFeature.ALLOWS_ANY_NULL_QUERIES;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.ImmutableSetMultimap.Builder;
-import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
-import com.google.common.collect.testing.features.MapFeature;
import com.google.common.collect.testing.google.SetMultimapTestSuiteBuilder;
import com.google.common.collect.testing.google.TestStringSetMultimapGenerator;
import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
@@ -46,27 +47,47 @@ import java.util.Map.Entry;
*/
@GwtCompatible(emulated = true)
public class ImmutableSetMultimapTest extends TestCase {
+ private static final class ImmutableSetMultimapGenerator extends
+ TestStringSetMultimapGenerator {
+ @Override
+ protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
+ ImmutableSetMultimap.Builder<String, String> builder = ImmutableSetMultimap.builder();
+ for (Entry<String, String> entry : entries) {
+ builder.put(entry.getKey(), entry.getValue());
+ }
+ return builder.build();
+ }
+ }
+
+ private static final class ImmutableSetMultimapCopyOfEntriesGenerator extends
+ TestStringSetMultimapGenerator {
+ @Override
+ protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
+ return ImmutableSetMultimap.copyOf(Arrays.asList(entries));
+ }
+ }
+
@GwtIncompatible("suite")
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(ImmutableSetMultimapTest.class);
- suite.addTest(SetMultimapTestSuiteBuilder.using(new TestStringSetMultimapGenerator() {
- @Override
- protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
- ImmutableSetMultimap.Builder<String, String> builder = ImmutableSetMultimap.builder();
- for (Entry<String, String> entry : entries) {
- builder.put(entry.getKey(), entry.getValue());
- }
- return builder.build();
- }
- })
- .named("ImmutableSetMultimap")
- .withFeatures(
- MapFeature.ALLOWS_ANY_NULL_QUERIES,
- CollectionFeature.KNOWN_ORDER,
- CollectionFeature.SERIALIZABLE,
- CollectionSize.ANY)
- .createTestSuite());
+ suite.addTest(SetMultimapTestSuiteBuilder.using(new ImmutableSetMultimapGenerator())
+ .named("ImmutableSetMultimap")
+ .withFeatures(
+ ALLOWS_ANY_NULL_QUERIES,
+ KNOWN_ORDER,
+ SERIALIZABLE,
+ CollectionSize.ANY)
+ .createTestSuite());
+ suite.addTest(SetMultimapTestSuiteBuilder.using(
+ new ImmutableSetMultimapCopyOfEntriesGenerator())
+ .named("ImmutableSetMultimap.copyOf[Iterable<Entry>]")
+ .withFeatures(
+ ALLOWS_ANY_NULL_QUERIES,
+ KNOWN_ORDER,
+ SERIALIZABLE,
+ CollectionSize.ANY)
+ .createTestSuite());
return suite;
}
@@ -249,13 +270,13 @@ public class ImmutableSetMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("b", 6);
ImmutableSetMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
- assertThat(multimap.values()).has().exactly(2, 4, 3, 6, 5, 2).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("b")).has().exactly(3, 6).inOrder();
- assertFalse(multimap.get("a") instanceof ImmutableSortedSet);
- assertFalse(multimap.get("x") instanceof ImmutableSortedSet);
- assertFalse(multimap.asMap().get("a") instanceof ImmutableSortedSet);
+ assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+ assertThat(multimap.values()).containsExactly(2, 4, 3, 6, 5, 2).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("b")).containsExactly(3, 6).inOrder();
+ assertThat(multimap.get("a")).isNotInstanceOf(ImmutableSortedSet.class);
+ assertThat(multimap.get("x")).isNotInstanceOf(ImmutableSortedSet.class);
+ assertThat(multimap.asMap().get("a")).isNotInstanceOf(ImmutableSortedSet.class);
}
public void testBuilderOrderKeysByDuplicates() {
@@ -274,13 +295,13 @@ public class ImmutableSetMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("bb", 6);
ImmutableSetMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("d", "a", "bb", "cc").inOrder();
- assertThat(multimap.values()).has().exactly(2, 5, 2, 3, 6, 4).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("bb")).has().exactly(3, 6).inOrder();
- assertFalse(multimap.get("a") instanceof ImmutableSortedSet);
- assertFalse(multimap.get("x") instanceof ImmutableSortedSet);
- assertFalse(multimap.asMap().get("a") instanceof ImmutableSortedSet);
+ assertThat(multimap.keySet()).containsExactly("d", "a", "bb", "cc").inOrder();
+ assertThat(multimap.values()).containsExactly(2, 5, 2, 3, 6, 4).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("bb")).containsExactly(3, 6).inOrder();
+ assertThat(multimap.get("a")).isNotInstanceOf(ImmutableSortedSet.class);
+ assertThat(multimap.get("x")).isNotInstanceOf(ImmutableSortedSet.class);
+ assertThat(multimap.asMap().get("a")).isNotInstanceOf(ImmutableSortedSet.class);
}
public void testBuilderOrderValuesBy() {
@@ -294,10 +315,10 @@ public class ImmutableSetMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("b", 6);
ImmutableSetMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("b", "d", "a", "c").inOrder();
- assertThat(multimap.values()).has().exactly(6, 3, 2, 5, 2, 4).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+ assertThat(multimap.keySet()).containsExactly("b", "d", "a", "c").inOrder();
+ assertThat(multimap.values()).containsExactly(6, 3, 2, 5, 2, 4).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
assertTrue(multimap.get("a") instanceof ImmutableSortedSet);
assertEquals(Collections.reverseOrder(),
((ImmutableSortedSet<Integer>) multimap.get("a")).comparator());
@@ -321,10 +342,10 @@ public class ImmutableSetMultimapTest extends TestCase {
builder.put("a", 2);
builder.put("b", 6);
ImmutableSetMultimap<String, Integer> multimap = builder.build();
- assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
- assertThat(multimap.values()).has().exactly(2, 4, 6, 3, 5, 2).inOrder();
- assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
- assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
+ assertThat(multimap.keySet()).containsExactly("d", "c", "b", "a").inOrder();
+ assertThat(multimap.values()).containsExactly(2, 4, 6, 3, 5, 2).inOrder();
+ assertThat(multimap.get("a")).containsExactly(5, 2).inOrder();
+ assertThat(multimap.get("b")).containsExactly(6, 3).inOrder();
assertTrue(multimap.get("a") instanceof ImmutableSortedSet);
assertEquals(Collections.reverseOrder(),
((ImmutableSortedSet<Integer>) multimap.get("a")).comparator());
@@ -536,8 +557,8 @@ public class ImmutableSetMultimapTest extends TestCase {
.put("b", 1)
.build();
multimap = SerializableTester.reserialize(multimap);
- assertThat(multimap.keySet()).has().exactly("b", "a").inOrder();
- assertThat(multimap.get("a")).has().exactly(10, 2).inOrder();
+ assertThat(multimap.keySet()).containsExactly("b", "a").inOrder();
+ assertThat(multimap.get("a")).containsExactly(10, 2).inOrder();
assertEquals(Ordering.usingToString(),
((ImmutableSortedSet<Integer>) multimap.get("a")).comparator());
assertEquals(Ordering.usingToString(),
diff --git a/guava-tests/test/com/google/common/collect/ImmutableSetTest.java b/guava-tests/test/com/google/common/collect/ImmutableSetTest.java
index 43a9352..839671c 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableSetTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableSetTest.java
@@ -153,7 +153,7 @@ public class ImmutableSetTest extends AbstractImmutableSetTest {
// now we'll get the varargs overload
ImmutableSet<String> set = ImmutableSet.of(
"a", "b", "c", "c", "c", "c", "b", "b", "a", "a", "c", "c", "c", "a");
- assertThat(set).has().exactly("a", "b", "c").inOrder();
+ assertThat(set).containsExactly("a", "b", "c").inOrder();
}
public void testCreation_arrayOfArray() {
diff --git a/guava-tests/test/com/google/common/collect/ImmutableSortedMapTest.java b/guava-tests/test/com/google/common/collect/ImmutableSortedMapTest.java
index 8ea6660..daf1ba0 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableSortedMapTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableSortedMapTest.java
@@ -23,11 +23,13 @@ import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSortedMap.Builder;
import com.google.common.collect.testing.ListTestSuiteBuilder;
+import com.google.common.collect.testing.MapTestSuiteBuilder;
import com.google.common.collect.testing.NavigableMapTestSuiteBuilder;
import com.google.common.collect.testing.SortedMapInterfaceTest;
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
import com.google.common.collect.testing.features.MapFeature;
+import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapCopyOfEntriesGenerator;
import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapEntryListGenerator;
import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapGenerator;
import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapKeyListGenerator;
@@ -73,6 +75,16 @@ public class ImmutableSortedMapTest extends TestCase {
MapFeature.ALLOWS_ANY_NULL_QUERIES)
.named("ImmutableSortedMap")
.createTestSuite());
+ suite.addTest(MapTestSuiteBuilder.using(
+ new ImmutableSortedMapCopyOfEntriesGenerator())
+ .withFeatures(
+ CollectionSize.ANY,
+ CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
+ CollectionFeature.KNOWN_ORDER,
+ MapFeature.REJECTS_DUPLICATES_AT_CREATION,
+ MapFeature.ALLOWS_ANY_NULL_QUERIES)
+ .named("ImmutableSortedMap.copyOf[Iterable<Entry>]")
+ .createTestSuite());
suite.addTest(ListTestSuiteBuilder.using(
new ImmutableSortedMapEntryListGenerator())
@@ -290,6 +302,14 @@ public class ImmutableSortedMapTest extends TestCase {
"five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
}
+ public void testBuilder_orderEntriesByValueFails() {
+ ImmutableSortedMap.Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
+ try {
+ builder.orderEntriesByValue(Ordering.natural());
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {}
+ }
+
public void testBuilder_withImmutableEntry() {
ImmutableSortedMap<String, Integer> map =
ImmutableSortedMap.<String, Integer>naturalOrder()
@@ -710,7 +730,7 @@ public class ImmutableSortedMapTest extends TestCase {
public void testHeadMapInclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", true);
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
Maps.immutableEntry("one", 1),
Maps.immutableEntry("three", 3)).inOrder();
}
@@ -719,14 +739,14 @@ public class ImmutableSortedMapTest extends TestCase {
public void testHeadMapExclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", false);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1)).inOrder();
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("one", 1));
}
@SuppressWarnings("unchecked") // varargs
public void testTailMapInclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", true);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3),
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("three", 3),
Maps.immutableEntry("two", 2)).inOrder();
}
@@ -734,21 +754,21 @@ public class ImmutableSortedMapTest extends TestCase {
public void testTailMapExclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", false);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("two", 2)).inOrder();
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("two", 2));
}
@SuppressWarnings("unchecked") // varargs
public void testSubMapExclusiveExclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", false);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3)).inOrder();
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("three", 3));
}
@SuppressWarnings("unchecked") // varargs
public void testSubMapInclusiveExclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", false);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1),
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("one", 1),
Maps.immutableEntry("three", 3)).inOrder();
}
@@ -756,7 +776,7 @@ public class ImmutableSortedMapTest extends TestCase {
public void testSubMapExclusiveInclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", true);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3),
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("three", 3),
Maps.immutableEntry("two", 2)).inOrder();
}
@@ -764,7 +784,7 @@ public class ImmutableSortedMapTest extends TestCase {
public void testSubMapInclusiveInclusive() {
Map<String, Integer> map =
ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", true);
- assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1),
+ assertThat(map.entrySet()).containsExactly(Maps.immutableEntry("one", 1),
Maps.immutableEntry("three", 3), Maps.immutableEntry("two", 2)).inOrder();
}
diff --git a/guava-tests/test/com/google/common/collect/ImmutableSortedMultisetTest.java b/guava-tests/test/com/google/common/collect/ImmutableSortedMultisetTest.java
index ed069fb..34df049 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableSortedMultisetTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableSortedMultisetTest.java
@@ -422,13 +422,13 @@ public class ImmutableSortedMultisetTest extends TestCase {
public void testSerialization_multiple() {
Collection<String> c = ImmutableSortedMultiset.of("a", "b", "a");
Collection<String> copy = SerializableTester.reserializeAndAssert(c);
- assertThat(copy).has().exactly("a", "a", "b").inOrder();
+ assertThat(copy).containsExactly("a", "a", "b").inOrder();
}
public void testSerialization_elementSet() {
Multiset<String> c = ImmutableSortedMultiset.of("a", "b", "a");
Collection<String> copy = SerializableTester.reserializeAndAssert(c.elementSet());
- assertThat(copy).has().exactly("a", "b").inOrder();
+ assertThat(copy).containsExactly("a", "b").inOrder();
}
public void testSerialization_entrySet() {
@@ -446,7 +446,7 @@ public class ImmutableSortedMultisetTest extends TestCase {
public void testIterationOrder() {
Collection<String> c = ImmutableSortedMultiset.of("a", "b", "a");
- assertThat(c).has().exactly("a", "a", "b").inOrder();
+ assertThat(c).containsExactly("a", "a", "b").inOrder();
}
public void testMultisetWrites() {
diff --git a/guava-tests/test/com/google/common/collect/ImmutableSortedSetTest.java b/guava-tests/test/com/google/common/collect/ImmutableSortedSetTest.java
index ea0c825..9602610 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableSortedSetTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableSortedSetTest.java
@@ -264,7 +264,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testSingle_headSet() {
SortedSet<String> set = of("e");
assertTrue(set.headSet("g") instanceof ImmutableSortedSet);
- assertThat(set.headSet("g")).has().item("e");
+ assertThat(set.headSet("g")).contains("e");
assertSame(of(), set.headSet("c"));
assertSame(of(), set.headSet("e"));
}
@@ -272,16 +272,16 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testSingle_tailSet() {
SortedSet<String> set = of("e");
assertTrue(set.tailSet("c") instanceof ImmutableSortedSet);
- assertThat(set.tailSet("c")).has().item("e");
- assertThat(set.tailSet("e")).has().item("e");
+ assertThat(set.tailSet("c")).contains("e");
+ assertThat(set.tailSet("e")).contains("e");
assertSame(of(), set.tailSet("g"));
}
public void testSingle_subSet() {
SortedSet<String> set = of("e");
assertTrue(set.subSet("c", "g") instanceof ImmutableSortedSet);
- assertThat(set.subSet("c", "g")).has().item("e");
- assertThat(set.subSet("e", "g")).has().item("e");
+ assertThat(set.subSet("c", "g")).contains("e");
+ assertThat(set.subSet("e", "g")).contains("e");
assertSame(of(), set.subSet("f", "g"));
assertSame(of(), set.subSet("c", "e"));
assertSame(of(), set.subSet("c", "d"));
@@ -306,7 +306,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testOf_ordering() {
SortedSet<String> set = of("e", "a", "f", "b", "d", "c");
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
/*
@@ -355,7 +355,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testOf_ordering_dupes() {
SortedSet<String> set = of("e", "a", "e", "f", "b", "b", "d", "a", "c");
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
public void testOf_comparator() {
@@ -366,8 +366,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testOf_headSet() {
SortedSet<String> set = of("e", "f", "b", "d", "c");
assertTrue(set.headSet("e") instanceof ImmutableSortedSet);
- assertThat(set.headSet("e")).has().exactly("b", "c", "d").inOrder();
- assertThat(set.headSet("g")).has().exactly("b", "c", "d", "e", "f").inOrder();
+ assertThat(set.headSet("e")).containsExactly("b", "c", "d").inOrder();
+ assertThat(set.headSet("g")).containsExactly("b", "c", "d", "e", "f").inOrder();
assertSame(of(), set.headSet("a"));
assertSame(of(), set.headSet("b"));
}
@@ -375,16 +375,16 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testOf_tailSet() {
SortedSet<String> set = of("e", "f", "b", "d", "c");
assertTrue(set.tailSet("e") instanceof ImmutableSortedSet);
- assertThat(set.tailSet("e")).has().exactly("e", "f").inOrder();
- assertThat(set.tailSet("a")).has().exactly("b", "c", "d", "e", "f").inOrder();
+ assertThat(set.tailSet("e")).containsExactly("e", "f").inOrder();
+ assertThat(set.tailSet("a")).containsExactly("b", "c", "d", "e", "f").inOrder();
assertSame(of(), set.tailSet("g"));
}
public void testOf_subSet() {
SortedSet<String> set = of("e", "f", "b", "d", "c");
assertTrue(set.subSet("c", "e") instanceof ImmutableSortedSet);
- assertThat(set.subSet("c", "e")).has().exactly("c", "d").inOrder();
- assertThat(set.subSet("a", "g")).has().exactly("b", "c", "d", "e", "f").inOrder();
+ assertThat(set.subSet("c", "e")).containsExactly("c", "d").inOrder();
+ assertThat(set.subSet("a", "g")).containsExactly("b", "c", "d", "e", "f").inOrder();
assertSame(of(), set.subSet("a", "b"));
assertSame(of(), set.subSet("g", "h"));
assertSame(of(), set.subSet("c", "c"));
@@ -424,14 +424,14 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testExplicit_ordering() {
SortedSet<String> set = ImmutableSortedSet.orderedBy(STRING_LENGTH).add(
"in", "the", "quick", "jumped", "over", "a").build();
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
}
public void testExplicit_ordering_dupes() {
SortedSet<String> set = ImmutableSortedSet.orderedBy(STRING_LENGTH).add(
"in", "the", "quick", "brown", "fox", "jumped",
"over", "a", "lazy", "dog").build();
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
}
public void testExplicit_contains() {
@@ -461,9 +461,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
"in", "the", "quick", "jumped", "over", "a").build();
assertTrue(set.headSet("a") instanceof ImmutableSortedSet);
assertTrue(set.headSet("fish") instanceof ImmutableSortedSet);
- assertThat(set.headSet("fish")).has().exactly("a", "in", "the").inOrder();
- assertThat(set.headSet("california")).has()
- .exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set.headSet("fish")).containsExactly("a", "in", "the").inOrder();
+ assertThat(set.headSet("california"))
+ .containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
assertTrue(set.headSet("a").isEmpty());
assertTrue(set.headSet("").isEmpty());
}
@@ -473,9 +473,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
"in", "the", "quick", "jumped", "over", "a").build();
assertTrue(set.tailSet("california") instanceof ImmutableSortedSet);
assertTrue(set.tailSet("fish") instanceof ImmutableSortedSet);
- assertThat(set.tailSet("fish")).has().exactly("over", "quick", "jumped").inOrder();
+ assertThat(set.tailSet("fish")).containsExactly("over", "quick", "jumped").inOrder();
assertThat(
- set.tailSet("a")).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ set.tailSet("a")).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
assertTrue(set.tailSet("california").isEmpty());
}
@@ -484,9 +484,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
"in", "the", "quick", "jumped", "over", "a").build();
assertTrue(set.subSet("the", "quick") instanceof ImmutableSortedSet);
assertTrue(set.subSet("", "b") instanceof ImmutableSortedSet);
- assertThat(set.subSet("the", "quick")).has().exactly("the", "over").inOrder();
+ assertThat(set.subSet("the", "quick")).containsExactly("the", "over").inOrder();
assertThat(set.subSet("a", "california"))
- .has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ .containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
assertTrue(set.subSet("", "b").isEmpty());
assertTrue(set.subSet("vermont", "california").isEmpty());
assertTrue(set.subSet("aaa", "zzz").isEmpty());
@@ -530,13 +530,13 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testCopyOf_ordering() {
SortedSet<String> set =
copyOf(asList("e", "a", "f", "b", "d", "c"));
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
public void testCopyOf_ordering_dupes() {
SortedSet<String> set =
copyOf(asList("e", "a", "e", "f", "b", "b", "d", "a", "c"));
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
public void testCopyOf_subSet() {
@@ -567,13 +567,13 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testCopyOf_iterator_ordering() {
SortedSet<String> set = copyOf(asIterator("e", "a", "f", "b", "d", "c"));
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
public void testCopyOf_iterator_ordering_dupes() {
SortedSet<String> set =
copyOf(asIterator("e", "a", "e", "f", "b", "b", "d", "a", "c"));
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
public void testCopyOf_iterator_comparator() {
@@ -584,7 +584,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testCopyOf_sortedSet_ordering() {
SortedSet<String> set =
copyOf(Sets.newTreeSet(asList("e", "a", "f", "b", "d", "c")));
- assertThat(set).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(set).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
}
public void testCopyOf_sortedSet_comparator() {
@@ -596,7 +596,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
SortedSet<String> set =
ImmutableSortedSet.copyOf(STRING_LENGTH, asList(
"in", "the", "quick", "jumped", "over", "a"));
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
}
public void testCopyOfExplicit_ordering_dupes() {
@@ -604,7 +604,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
ImmutableSortedSet.copyOf(STRING_LENGTH, asList(
"in", "the", "quick", "brown", "fox", "jumped", "over", "a",
"lazy", "dog"));
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
}
public void testCopyOfExplicit_comparator() {
@@ -618,7 +618,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
SortedSet<String> set =
ImmutableSortedSet.copyOf(STRING_LENGTH, asIterator(
"in", "the", "quick", "jumped", "over", "a"));
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
}
public void testCopyOfExplicit_iterator_ordering_dupes() {
@@ -626,7 +626,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
ImmutableSortedSet.copyOf(STRING_LENGTH, asIterator(
"in", "the", "quick", "brown", "fox", "jumped", "over", "a",
"lazy", "dog"));
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
}
public void testCopyOfExplicit_iterator_comparator() {
@@ -640,14 +640,14 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
SortedSet<String> input = Sets.newTreeSet(STRING_LENGTH);
Collections.addAll(input, "in", "the", "quick", "jumped", "over", "a");
SortedSet<String> set = copyOf(input);
- assertThat(set).has().exactly("a", "in", "jumped", "over", "quick", "the").inOrder();
+ assertThat(set).containsExactly("a", "in", "jumped", "over", "quick", "the").inOrder();
}
public void testCopyOfSorted_natural_ordering() {
SortedSet<String> input = Sets.newTreeSet(
asList("in", "the", "quick", "jumped", "over", "a"));
SortedSet<String> set = ImmutableSortedSet.copyOfSorted(input);
- assertThat(set).has().exactly("a", "in", "jumped", "over", "quick", "the").inOrder();
+ assertThat(set).containsExactly("a", "in", "jumped", "over", "quick", "the").inOrder();
}
public void testCopyOfSorted_natural_comparator() {
@@ -661,7 +661,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
SortedSet<String> input = Sets.newTreeSet(STRING_LENGTH);
Collections.addAll(input, "in", "the", "quick", "jumped", "over", "a");
SortedSet<String> set = ImmutableSortedSet.copyOfSorted(input);
- assertThat(set).has().exactly("a", "in", "the", "over", "quick", "jumped").inOrder();
+ assertThat(set).containsExactly("a", "in", "the", "over", "quick", "jumped").inOrder();
assertSame(STRING_LENGTH, set.comparator());
}
@@ -760,7 +760,7 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testReverseOrder() {
SortedSet<String> set = ImmutableSortedSet.<String>reverseOrder()
.add("a", "b", "c").build();
- assertThat(set).has().exactly("c", "b", "a").inOrder();
+ assertThat(set).containsExactly("c", "b", "a").inOrder();
assertEquals(Ordering.natural().reverse(), set.comparator());
}
@@ -775,13 +775,13 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
public void testSupertypeComparator() {
SortedSet<Integer> set = new ImmutableSortedSet.Builder<Integer>(TO_STRING)
.add(3, 12, 101, 44).build();
- assertThat(set).has().exactly(101, 12, 3, 44).inOrder();
+ assertThat(set).containsExactly(101, 12, 3, 44).inOrder();
}
public void testSupertypeComparatorSubtypeElements() {
SortedSet<Number> set = new ImmutableSortedSet.Builder<Number>(TO_STRING)
.add(3, 12, 101, 44).build();
- assertThat(set).has().exactly(101, 12, 3, 44).inOrder();
+ assertThat(set).containsExactly(101, 12, 3, 44).inOrder();
}
@Override <E extends Comparable<E>> ImmutableSortedSet.Builder<E> builder() {
@@ -923,7 +923,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
Arrays.sort(strings);
for (int i = 0; i < strings.length; i++) {
assertThat(set.headSet(strings[i], true))
- .has().exactlyAs(sortedNumberNames(0, i + 1)).inOrder();
+ .containsExactlyElementsIn(sortedNumberNames(0, i + 1))
+ .inOrder();
}
}
@@ -932,8 +933,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
ImmutableSortedSet<String> set = ImmutableSortedSet.copyOf(strings);
Arrays.sort(strings);
for (int i = 0; i < strings.length; i++) {
- assertThat(set.headSet(strings[i], false)).has().exactlyAs(
- sortedNumberNames(0, i)).inOrder();
+ assertThat(set.headSet(strings[i], false))
+ .containsExactlyElementsIn(sortedNumberNames(0, i))
+ .inOrder();
}
}
@@ -942,8 +944,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
ImmutableSortedSet<String> set = ImmutableSortedSet.copyOf(strings);
Arrays.sort(strings);
for (int i = 0; i < strings.length; i++) {
- assertThat(set.tailSet(strings[i], true)).has().exactlyAs(
- sortedNumberNames(i, strings.length)).inOrder();
+ assertThat(set.tailSet(strings[i], true))
+ .containsExactlyElementsIn(sortedNumberNames(i, strings.length))
+ .inOrder();
}
}
@@ -952,8 +955,9 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
ImmutableSortedSet<String> set = ImmutableSortedSet.copyOf(strings);
Arrays.sort(strings);
for (int i = 0; i < strings.length; i++) {
- assertThat(set.tailSet(strings[i], false)).has().exactlyAs(
- sortedNumberNames(i + 1, strings.length)).inOrder();
+ assertThat(set.tailSet(strings[i], false))
+ .containsExactlyElementsIn(sortedNumberNames(i + 1, strings.length))
+ .inOrder();
}
}
@@ -964,7 +968,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
for (int i = 0; i < strings.length; i++) {
for (int j = i; j < strings.length; j++) {
assertThat(set.subSet(strings[i], false, strings[j], false))
- .has().exactlyAs(sortedNumberNames(Math.min(i + 1, j), j)).inOrder();
+ .containsExactlyElementsIn(sortedNumberNames(Math.min(i + 1, j), j))
+ .inOrder();
}
}
}
@@ -976,7 +981,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
for (int i = 0; i < strings.length; i++) {
for (int j = i; j < strings.length; j++) {
assertThat(set.subSet(strings[i], true, strings[j], false))
- .has().exactlyAs(sortedNumberNames(i, j)).inOrder();
+ .containsExactlyElementsIn(sortedNumberNames(i, j))
+ .inOrder();
}
}
}
@@ -988,7 +994,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
for (int i = 0; i < strings.length; i++) {
for (int j = i; j < strings.length; j++) {
assertThat(set.subSet(strings[i], false, strings[j], true))
- .has().exactlyAs(sortedNumberNames(i + 1, j + 1)).inOrder();
+ .containsExactlyElementsIn(sortedNumberNames(i + 1, j + 1))
+ .inOrder();
}
}
}
@@ -1000,7 +1007,8 @@ public class ImmutableSortedSetTest extends AbstractImmutableSetTest {
for (int i = 0; i < strings.length; i++) {
for (int j = i; j < strings.length; j++) {
assertThat(set.subSet(strings[i], true, strings[j], true))
- .has().exactlyAs(sortedNumberNames(i, j + 1)).inOrder();
+ .containsExactlyElementsIn(sortedNumberNames(i, j + 1))
+ .inOrder();
}
}
}
diff --git a/guava-tests/test/com/google/common/collect/ImmutableTableTest.java b/guava-tests/test/com/google/common/collect/ImmutableTableTest.java
index 7d88619..0a75cf8 100644
--- a/guava-tests/test/com/google/common/collect/ImmutableTableTest.java
+++ b/guava-tests/test/com/google/common/collect/ImmutableTableTest.java
@@ -185,9 +185,9 @@ public class ImmutableTableTest extends AbstractTableReadTest {
validateTableCopies(table);
// Even though rowKeySet, columnKeySet, and cellSet have the same
// iteration ordering, row has an inconsistent ordering.
- assertThat(table.row('b').keySet()).has().exactly(1, 2).inOrder();
+ assertThat(table.row('b').keySet()).containsExactly(1, 2).inOrder();
assertThat(ImmutableTable.copyOf(table).row('b').keySet())
- .has().exactly(2, 1).inOrder();
+ .containsExactly(2, 1).inOrder();
}
public void testCopyOfSparse() {
@@ -228,10 +228,10 @@ public class ImmutableTableTest extends AbstractTableReadTest {
= builder.orderRowsBy(Ordering.natural())
.orderColumnsBy(Ordering.natural())
.putAll(table).build();
- assertThat(copy.rowKeySet()).has().exactly('a', 'b').inOrder();
- assertThat(copy.columnKeySet()).has().exactly(1, 2).inOrder();
- assertThat(copy.values()).has().exactly("baz", "bar", "foo").inOrder();
- assertThat(copy.row('b').keySet()).has().exactly(1, 2).inOrder();
+ assertThat(copy.rowKeySet()).containsExactly('a', 'b').inOrder();
+ assertThat(copy.columnKeySet()).containsExactly(1, 2).inOrder();
+ assertThat(copy.values()).containsExactly("baz", "bar", "foo").inOrder();
+ assertThat(copy.row('b').keySet()).containsExactly(1, 2).inOrder();
}
public void testBuilder_orderRowsAndColumnsBy_sparse() {
@@ -249,12 +249,12 @@ public class ImmutableTableTest extends AbstractTableReadTest {
builder.put('r', 4, "foo");
builder.put('x', 5, "bar");
Table<Character, Integer, String> table = builder.build();
- assertThat(table.rowKeySet()).has().exactly('b', 'c', 'e', 'r', 'x').inOrder();
- assertThat(table.columnKeySet()).has().exactly(0, 1, 2, 3, 4, 5, 7).inOrder();
- assertThat(table.values()).has().exactly("cat", "axe", "baz", "tub",
+ assertThat(table.rowKeySet()).containsExactly('b', 'c', 'e', 'r', 'x').inOrder();
+ assertThat(table.columnKeySet()).containsExactly(0, 1, 2, 3, 4, 5, 7).inOrder();
+ assertThat(table.values()).containsExactly("cat", "axe", "baz", "tub",
"dog", "bar", "foo", "foo", "bar").inOrder();
- assertThat(table.row('c').keySet()).has().exactly(0, 3).inOrder();
- assertThat(table.column(5).keySet()).has().exactly('e', 'x').inOrder();
+ assertThat(table.row('c').keySet()).containsExactly(0, 3).inOrder();
+ assertThat(table.column(5).keySet()).containsExactly('e', 'x').inOrder();
}
public void testBuilder_orderRowsAndColumnsBy_dense() {
@@ -271,12 +271,12 @@ public class ImmutableTableTest extends AbstractTableReadTest {
builder.put('a', 2, "bar");
builder.put('a', 1, "baz");
Table<Character, Integer, String> table = builder.build();
- assertThat(table.rowKeySet()).has().exactly('a', 'b', 'c').inOrder();
- assertThat(table.columnKeySet()).has().exactly(1, 2, 3).inOrder();
- assertThat(table.values()).has().exactly("baz", "bar", "foo", "dog",
+ assertThat(table.rowKeySet()).containsExactly('a', 'b', 'c').inOrder();
+ assertThat(table.columnKeySet()).containsExactly(1, 2, 3).inOrder();
+ assertThat(table.values()).containsExactly("baz", "bar", "foo", "dog",
"cat", "baz", "bar", "foo").inOrder();
- assertThat(table.row('c').keySet()).has().exactly(1, 2, 3).inOrder();
- assertThat(table.column(1).keySet()).has().exactly('a', 'b', 'c').inOrder();
+ assertThat(table.row('c').keySet()).containsExactly(1, 2, 3).inOrder();
+ assertThat(table.column(1).keySet()).containsExactly('a', 'b', 'c').inOrder();
}
public void testBuilder_orderRowsBy_sparse() {
@@ -293,8 +293,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
builder.put('r', 4, "foo");
builder.put('x', 5, "bar");
Table<Character, Integer, String> table = builder.build();
- assertThat(table.rowKeySet()).has().exactly('b', 'c', 'e', 'r', 'x').inOrder();
- assertThat(table.column(5).keySet()).has().exactly('e', 'x').inOrder();
+ assertThat(table.rowKeySet()).containsExactly('b', 'c', 'e', 'r', 'x').inOrder();
+ assertThat(table.column(5).keySet()).containsExactly('e', 'x').inOrder();
}
public void testBuilder_orderRowsBy_dense() {
@@ -310,8 +310,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
builder.put('a', 2, "bar");
builder.put('a', 1, "baz");
Table<Character, Integer, String> table = builder.build();
- assertThat(table.rowKeySet()).has().exactly('a', 'b', 'c').inOrder();
- assertThat(table.column(1).keySet()).has().exactly('a', 'b', 'c').inOrder();
+ assertThat(table.rowKeySet()).containsExactly('a', 'b', 'c').inOrder();
+ assertThat(table.column(1).keySet()).containsExactly('a', 'b', 'c').inOrder();
}
public void testBuilder_orderColumnsBy_sparse() {
@@ -328,8 +328,8 @@ public class ImmutableTableTest extends AbstractTableReadTest {
builder.put('r', 4, "foo");
builder.put('x', 5, "bar");
Table<Character, Integer, String> table = builder.build();
- assertThat(table.columnKeySet()).has().exactly(0, 1, 2, 3, 4, 5, 7).inOrder();
- assertThat(table.row('c').keySet()).has().exactly(0, 3).inOrder();
+ assertThat(table.columnKeySet()).containsExactly(0, 1, 2, 3, 4, 5, 7).inOrder();
+ assertThat(table.row('c').keySet()).containsExactly(0, 3).inOrder();
}
public void testBuilder_orderColumnsBy_dense() {
@@ -345,11 +345,12 @@ public class ImmutableTableTest extends AbstractTableReadTest {
builder.put('a', 2, "bar");
builder.put('a', 1, "baz");
Table<Character, Integer, String> table = builder.build();
- assertThat(table.columnKeySet()).has().exactly(1, 2, 3).inOrder();
- assertThat(table.row('c').keySet()).has().exactly(1, 2, 3).inOrder();
+ assertThat(table.columnKeySet()).containsExactly(1, 2, 3).inOrder();
+ assertThat(table.row('c').keySet()).containsExactly(1, 2, 3).inOrder();
}
@GwtIncompatible("Mind-bogglingly slow in GWT")
+ @SuppressUnderAndroid // slow
public void testOverflowCondition() {
// See https://code.google.com/p/guava-libraries/issues/detail?id=1322 for details.
ImmutableTable.Builder<Integer, Integer, String> builder = ImmutableTable.builder();
diff --git a/guava-tests/test/com/google/common/collect/IterablesTest.java b/guava-tests/test/com/google/common/collect/IterablesTest.java
index 1dbbb97..9a853cc 100644
--- a/guava-tests/test/com/google/common/collect/IterablesTest.java
+++ b/guava-tests/test/com/google/common/collect/IterablesTest.java
@@ -28,7 +28,6 @@ import static java.util.Collections.emptyList;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
-import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.testing.IteratorTester;
@@ -262,14 +261,10 @@ public class IterablesTest extends TestCase {
public void testTryFind() {
Iterable<String> list = newArrayList("cool", "pants");
- assertEquals(Optional.of("cool"),
- Iterables.tryFind(list, Predicates.equalTo("cool")));
- assertEquals(Optional.of("pants"),
- Iterables.tryFind(list, Predicates.equalTo("pants")));
- assertEquals(Optional.of("cool"),
- Iterables.tryFind(list, Predicates.alwaysTrue()));
- assertEquals(Optional.absent(),
- Iterables.tryFind(list, Predicates.alwaysFalse()));
+ assertThat(Iterables.tryFind(list, Predicates.equalTo("cool"))).hasValue("cool");
+ assertThat(Iterables.tryFind(list, Predicates.equalTo("pants"))).hasValue("pants");
+ assertThat(Iterables.tryFind(list, Predicates.alwaysTrue())).hasValue("cool");
+ assertThat(Iterables.tryFind(list, Predicates.alwaysFalse())).isAbsent();
assertCanIterateAgain(list);
}
@@ -283,7 +278,7 @@ public class IterablesTest extends TestCase {
Iterable<TypeA> alist = Lists
.newArrayList(new TypeA(), new TypeA(), hasBoth, new TypeA());
Iterable<TypeB> blist = Iterables.filter(alist, TypeB.class);
- assertThat(blist).iteratesAs(hasBoth);
+ assertThat(blist).containsExactly(hasBoth).inOrder();
}
public void testTransform() {
@@ -411,8 +406,7 @@ public class IterablesTest extends TestCase {
int n = 4;
Iterable<Integer> repeated
= Iterables.concat(Collections.nCopies(n, iterable));
- assertThat(repeated).iteratesAs(
- 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3);
+ assertThat(repeated).containsExactly(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3).inOrder();
}
public void testPartition_badSize() {
@@ -510,7 +504,7 @@ public class IterablesTest extends TestCase {
List<String> freshlyAdded = newArrayList("freshly", "added");
boolean changed = Iterables.addAll(alreadyThere, freshlyAdded);
- assertThat(alreadyThere).has().exactly(
+ assertThat(alreadyThere).containsExactly(
"already", "there", "freshly", "added").inOrder();
assertTrue(changed);
}
@@ -688,7 +682,7 @@ public class IterablesTest extends TestCase {
Iterable<String> tail = skip(set, 1);
set.remove("b");
set.addAll(newArrayList("A", "B", "C"));
- assertThat(tail).iteratesAs("c", "A", "B", "C");
+ assertThat(tail).containsExactly("c", "A", "B", "C").inOrder();
}
public void testSkip_structurallyModifiedSkipSomeList() throws Exception {
@@ -696,7 +690,7 @@ public class IterablesTest extends TestCase {
Iterable<String> tail = skip(list, 1);
list.subList(1, 3).clear();
list.addAll(0, newArrayList("A", "B", "C"));
- assertThat(tail).iteratesAs("B", "C", "a");
+ assertThat(tail).containsExactly("B", "C", "a").inOrder();
}
public void testSkip_structurallyModifiedSkipAll() throws Exception {
@@ -1127,12 +1121,12 @@ public class IterablesTest extends TestCase {
assertEquals("Iterables.consumingIterable(...)", consumingIterable.toString());
Iterator<String> consumingIterator = consumingIterable.iterator();
- assertThat(list).has().exactly("a", "b").inOrder();
+ assertThat(list).containsExactly("a", "b").inOrder();
assertTrue(consumingIterator.hasNext());
- assertThat(list).has().exactly("a", "b").inOrder();
+ assertThat(list).containsExactly("a", "b").inOrder();
assertEquals("a", consumingIterator.next());
- assertThat(list).has().item("b");
+ assertThat(list).contains("b");
assertTrue(consumingIterator.hasNext());
assertEquals("b", consumingIterator.next());
diff --git a/guava-tests/test/com/google/common/collect/IteratorsTest.java b/guava-tests/test/com/google/common/collect/IteratorsTest.java
index c3f9263..92e9b1f 100644
--- a/guava-tests/test/com/google/common/collect/IteratorsTest.java
+++ b/guava-tests/test/com/google/common/collect/IteratorsTest.java
@@ -16,6 +16,7 @@
package com.google.common.collect;
+import static com.google.common.collect.CollectPreconditions.checkRemove;
import static com.google.common.collect.Iterators.advance;
import static com.google.common.collect.Iterators.get;
import static com.google.common.collect.Iterators.getLast;
@@ -45,6 +46,7 @@ import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -194,8 +196,7 @@ public class IteratorsTest extends TestCase {
Iterators.getOnlyElement(iterator);
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("expected one element but was: <one, two>",
- expected.getMessage());
+ assertThat(expected).hasMessage("expected one element but was: <one, two>");
}
}
@@ -206,9 +207,8 @@ public class IteratorsTest extends TestCase {
Iterators.getOnlyElement(iterator);
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("expected one element but was: "
- + "<one, two, three, four, five>",
- expected.getMessage());
+ assertThat(expected)
+ .hasMessage("expected one element but was: " + "<one, two, three, four, five>");
}
}
@@ -219,9 +219,8 @@ public class IteratorsTest extends TestCase {
Iterators.getOnlyElement(iterator);
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("expected one element but was: "
- + "<one, two, three, four, five, ...>",
- expected.getMessage());
+ assertThat(expected)
+ .hasMessage("expected one element but was: " + "<one, two, three, four, five, ...>");
}
}
@@ -246,8 +245,7 @@ public class IteratorsTest extends TestCase {
Iterators.getOnlyElement(iterator, "x");
fail();
} catch (IllegalArgumentException expected) {
- assertEquals("expected one element but was: <foo, bar>",
- expected.getMessage());
+ assertThat(expected).hasMessage("expected one element but was: <foo, bar>");
}
}
@@ -429,22 +427,19 @@ public class IteratorsTest extends TestCase {
public void testTryFind_firstElement() {
Iterable<String> list = Lists.newArrayList("cool", "pants");
Iterator<String> iterator = list.iterator();
- assertEquals("cool",
- Iterators.tryFind(iterator, Predicates.equalTo("cool")).get());
+ assertThat(Iterators.tryFind(iterator, Predicates.equalTo("cool"))).hasValue("cool");
}
public void testTryFind_lastElement() {
Iterable<String> list = Lists.newArrayList("cool", "pants");
Iterator<String> iterator = list.iterator();
- assertEquals("pants",
- Iterators.tryFind(iterator, Predicates.equalTo("pants")).get());
+ assertThat(Iterators.tryFind(iterator, Predicates.equalTo("pants"))).hasValue("pants");
}
public void testTryFind_alwaysTrue() {
Iterable<String> list = Lists.newArrayList("cool", "pants");
Iterator<String> iterator = list.iterator();
- assertEquals("cool",
- Iterators.tryFind(iterator, Predicates.alwaysTrue()).get());
+ assertThat(Iterators.tryFind(iterator, Predicates.alwaysTrue())).hasValue("cool");
}
public void testTryFind_alwaysFalse_orDefault() {
@@ -458,8 +453,7 @@ public class IteratorsTest extends TestCase {
public void testTryFind_alwaysFalse_isPresent() {
Iterable<String> list = Lists.newArrayList("cool", "pants");
Iterator<String> iterator = list.iterator();
- assertFalse(
- Iterators.tryFind(iterator, Predicates.alwaysFalse()).isPresent());
+ assertThat(Iterators.tryFind(iterator, Predicates.alwaysFalse())).isAbsent();
assertFalse(iterator.hasNext());
}
@@ -626,6 +620,69 @@ public class IteratorsTest extends TestCase {
assertFalse(cycle.hasNext());
}
+ /** An Iterable whose Iterator is rigorous in checking for concurrent modification. */
+ private static final class PickyIterable<E> implements Iterable<E> {
+ final List<E> elements;
+ int modCount = 0;
+
+ PickyIterable(E... elements) {
+ this.elements = new ArrayList<E>(asList(elements));
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new PickyIterator();
+ }
+
+ final class PickyIterator implements Iterator<E> {
+ int expectedModCount = modCount;
+ int index = 0;
+ boolean canRemove;
+
+ @Override
+ public boolean hasNext() {
+ checkConcurrentModification();
+ return index < elements.size();
+ }
+
+ @Override
+ public E next() {
+ checkConcurrentModification();
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ canRemove = true;
+ return elements.get(index++);
+ }
+
+ @Override
+ public void remove() {
+ checkConcurrentModification();
+ checkRemove(canRemove);
+ elements.remove(--index);
+ expectedModCount = ++modCount;
+ canRemove = false;
+ }
+
+ void checkConcurrentModification() {
+ if (expectedModCount != modCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+ }
+ }
+
+ public void testCycleRemoveAfterHasNextExtraPicky() {
+ PickyIterable<String> iterable = new PickyIterable("a");
+ Iterator<String> cycle = Iterators.cycle(iterable);
+ assertTrue(cycle.hasNext());
+ assertEquals("a", cycle.next());
+ assertTrue(cycle.hasNext());
+ cycle.remove();
+ assertTrue(iterable.elements.isEmpty());
+ assertFalse(cycle.hasNext());
+ }
+
public void testCycleNoSuchElementException() {
Iterable<String> iterable = Lists.newArrayList("a");
Iterator<String> cycle = Iterators.cycle(iterable);
@@ -765,7 +822,7 @@ public class IteratorsTest extends TestCase {
boolean changed = Iterators.addAll(alreadyThere,
Iterators.<String>emptyIterator());
- assertThat(alreadyThere).has().exactly("already", "there").inOrder();
+ assertThat(alreadyThere).containsExactly("already", "there").inOrder();
assertFalse(changed);
}
@@ -775,7 +832,7 @@ public class IteratorsTest extends TestCase {
boolean changed = Iterators.addAll(alreadyThere, freshlyAdded.iterator());
- assertThat(alreadyThere).has().exactly("already", "there", "freshly", "added");
+ assertThat(alreadyThere).containsExactly("already", "there", "freshly", "added");
assertTrue(changed);
}
@@ -785,7 +842,7 @@ public class IteratorsTest extends TestCase {
List<String> oneMore = Lists.newArrayList("there");
boolean changed = Iterators.addAll(alreadyThere, oneMore.iterator());
- assertThat(alreadyThere).has().exactly("already", "there").inOrder();
+ assertThat(alreadyThere).containsExactly("already", "there").inOrder();
assertFalse(changed);
}
@@ -1523,12 +1580,12 @@ public class IteratorsTest extends TestCase {
assertEquals("Iterators.consumingIterator(...)", consumingIterator.toString());
- assertThat(list).has().exactly("a", "b").inOrder();
+ assertThat(list).containsExactly("a", "b").inOrder();
assertTrue(consumingIterator.hasNext());
- assertThat(list).has().exactly("a", "b").inOrder();
+ assertThat(list).containsExactly("a", "b").inOrder();
assertEquals("a", consumingIterator.next());
- assertThat(list).has().item("b");
+ assertThat(list).contains("b");
assertTrue(consumingIterator.hasNext());
assertEquals("b", consumingIterator.next());
diff --git a/guava-tests/test/com/google/common/collect/LinkedHashMultimapTest.java b/guava-tests/test/com/google/common/collect/LinkedHashMultimapTest.java
index 80bbcc1..fef4863 100644
--- a/guava-tests/test/com/google/common/collect/LinkedHashMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/LinkedHashMultimapTest.java
@@ -151,8 +151,8 @@ public class LinkedHashMultimapTest extends TestCase {
multimap.put("c", 4);
multimap.remove("a", 1);
multimap = SerializableTester.reserializeAndAssert(multimap);
- assertThat(multimap.keySet()).has().exactly("a", "b", "c").inOrder();
- assertThat(multimap.entries()).has().exactly(
+ assertThat(multimap.keySet()).containsExactly("a", "b", "c").inOrder();
+ assertThat(multimap.entries()).containsExactly(
mapEntry("b", 2),
mapEntry("a", 3),
mapEntry("c", 4)).inOrder();
@@ -160,12 +160,12 @@ public class LinkedHashMultimapTest extends TestCase {
}
private void assertOrderingReadOnly(Multimap<String, Integer> multimap) {
- assertThat(multimap.get("foo")).has().exactly(5, 3).inOrder();
- assertThat(multimap.get("bar")).has().exactly(4, 1).inOrder();
- assertThat(multimap.get("cow")).has().item(2);
+ assertThat(multimap.get("foo")).containsExactly(5, 3).inOrder();
+ assertThat(multimap.get("bar")).containsExactly(4, 1).inOrder();
+ assertThat(multimap.get("cow")).contains(2);
- assertThat(multimap.keySet()).has().exactly("foo", "bar", "cow").inOrder();
- assertThat(multimap.values()).has().exactly(5, 4, 3, 2, 1).inOrder();
+ assertThat(multimap.keySet()).containsExactly("foo", "bar", "cow").inOrder();
+ assertThat(multimap.values()).containsExactly(5, 4, 3, 2, 1).inOrder();
Iterator<Map.Entry<String, Integer>> entryIterator =
multimap.entries().iterator();
@@ -179,28 +179,28 @@ public class LinkedHashMultimapTest extends TestCase {
multimap.asMap().entrySet().iterator();
Map.Entry<String, Collection<Integer>> entry = collectionIterator.next();
assertEquals("foo", entry.getKey());
- assertThat(entry.getValue()).has().exactly(5, 3).inOrder();
+ assertThat(entry.getValue()).containsExactly(5, 3).inOrder();
entry = collectionIterator.next();
assertEquals("bar", entry.getKey());
- assertThat(entry.getValue()).has().exactly(4, 1).inOrder();
+ assertThat(entry.getValue()).containsExactly(4, 1).inOrder();
entry = collectionIterator.next();
assertEquals("cow", entry.getKey());
- assertThat(entry.getValue()).has().item(2);
+ assertThat(entry.getValue()).contains(2);
}
public void testOrderingUpdates() {
Multimap<String, Integer> multimap = initializeMultimap5();
- assertThat(multimap.replaceValues("foo", asList(6, 7))).has().exactly(5, 3).inOrder();
- assertThat(multimap.keySet()).has().exactly("foo", "bar", "cow").inOrder();
- assertThat(multimap.removeAll("foo")).has().exactly(6, 7).inOrder();
- assertThat(multimap.keySet()).has().exactly("bar", "cow").inOrder();
+ assertThat(multimap.replaceValues("foo", asList(6, 7))).containsExactly(5, 3).inOrder();
+ assertThat(multimap.keySet()).containsExactly("foo", "bar", "cow").inOrder();
+ assertThat(multimap.removeAll("foo")).containsExactly(6, 7).inOrder();
+ assertThat(multimap.keySet()).containsExactly("bar", "cow").inOrder();
assertTrue(multimap.remove("bar", 4));
- assertThat(multimap.keySet()).has().exactly("bar", "cow").inOrder();
+ assertThat(multimap.keySet()).containsExactly("bar", "cow").inOrder();
assertTrue(multimap.remove("bar", 1));
- assertThat(multimap.keySet()).has().item("cow");
+ assertThat(multimap.keySet()).contains("cow");
multimap.put("bar", 9);
- assertThat(multimap.keySet()).has().exactly("cow", "bar").inOrder();
+ assertThat(multimap.keySet()).containsExactly("cow", "bar").inOrder();
}
public void testToStringNullExact() {
diff --git a/guava-tests/test/com/google/common/collect/LinkedHashMultisetTest.java b/guava-tests/test/com/google/common/collect/LinkedHashMultisetTest.java
index ca359cb..ebea3ef 100644
--- a/guava-tests/test/com/google/common/collect/LinkedHashMultisetTest.java
+++ b/guava-tests/test/com/google/common/collect/LinkedHashMultisetTest.java
@@ -121,13 +121,13 @@ public class LinkedHashMultisetTest extends TestCase {
ms.add("a");
ms.add("b", 2);
ms.add("c");
- assertThat(ms.elementSet()).has().exactly("a", "b", "c").inOrder();
+ assertThat(ms.elementSet()).containsExactly("a", "b", "c").inOrder();
ms.remove("b");
- assertThat(ms.elementSet()).has().exactly("a", "b", "c").inOrder();
+ assertThat(ms.elementSet()).containsExactly("a", "b", "c").inOrder();
ms.add("b");
- assertThat(ms.elementSet()).has().exactly("a", "b", "c").inOrder();
+ assertThat(ms.elementSet()).containsExactly("a", "b", "c").inOrder();
ms.remove("b", 2);
ms.add("b");
- assertThat(ms.elementSet()).has().exactly("a", "c", "b").inOrder();
+ assertThat(ms.elementSet()).containsExactly("a", "c", "b").inOrder();
}
}
diff --git a/guava-tests/test/com/google/common/collect/LinkedListMultimapTest.java b/guava-tests/test/com/google/common/collect/LinkedListMultimapTest.java
index bc4a2df..ea0f49f 100644
--- a/guava-tests/test/com/google/common/collect/LinkedListMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/LinkedListMultimapTest.java
@@ -98,8 +98,8 @@ public class LinkedListMultimapTest extends TestCase {
Multimap<String, Integer> multimap = create();
multimap.put("foo", 1);
multimap.put("foo", 3);
- assertFalse(multimap.get("foo") instanceof RandomAccess);
- assertFalse(multimap.get("bar") instanceof RandomAccess);
+ assertThat(multimap.get("foo")).isNotInstanceOf(RandomAccess.class);
+ assertThat(multimap.get("bar")).isNotInstanceOf(RandomAccess.class);
}
/**
@@ -136,7 +136,7 @@ public class LinkedListMultimapTest extends TestCase {
LinkedListMultimap<String, Integer> copy =
LinkedListMultimap.create(multimap);
assertEquals(multimap, copy);
- assertThat(copy.entries()).has().exactlyAs(multimap.entries()).inOrder();
+ assertThat(copy.entries()).containsExactlyElementsIn(multimap.entries()).inOrder();
}
public void testCreateFromSize() {
@@ -230,7 +230,7 @@ public class LinkedListMultimapTest extends TestCase {
List<Integer> foos = map.get("foo");
Collection<Integer> values = map.values();
assertEquals(asList(1, 2), foos);
- assertThat(values).has().exactly(1, 2, 3).inOrder();
+ assertThat(values).containsExactly(1, 2, 3).inOrder();
map.clear();
assertEquals(Collections.emptyList(), foos);
assertThat(values).isEmpty();
@@ -257,7 +257,7 @@ public class LinkedListMultimapTest extends TestCase {
map.put("bar", 4);
assertEquals("[bar=1, foo=2, bar=3, bar=4]",
map.entries().toString());
- assertThat(map.keys()).has().exactly("bar", "foo", "bar", "bar").inOrder();
+ assertThat(map.keys()).containsExactly("bar", "foo", "bar", "bar").inOrder();
map.keys().remove("bar"); // bar is no longer the first key!
assertEquals("{foo=[2], bar=[3, 4]}", map.toString());
}
@@ -303,7 +303,7 @@ public class LinkedListMultimapTest extends TestCase {
= map.asMap().entrySet().iterator();
Map.Entry<String, Collection<Integer>> entry = entries.next();
assertEquals("bar", entry.getKey());
- assertThat(entry.getValue()).has().exactly(1, 3).inOrder();
+ assertThat(entry.getValue()).containsExactly(1, 3).inOrder();
try {
entry.setValue(Arrays.<Integer>asList());
fail("UnsupportedOperationException expected");
@@ -311,7 +311,7 @@ public class LinkedListMultimapTest extends TestCase {
entries.remove(); // clear
entry = entries.next();
assertEquals("foo", entry.getKey());
- assertThat(entry.getValue()).has().item(2);
+ assertThat(entry.getValue()).contains(2);
assertFalse(entries.hasNext());
assertEquals("{foo=[2]}", map.toString());
}
diff --git a/guava-tests/test/com/google/common/collect/ListsTest.java b/guava-tests/test/com/google/common/collect/ListsTest.java
index 7c422f4..e5a2efb 100644
--- a/guava-tests/test/com/google/common/collect/ListsTest.java
+++ b/guava-tests/test/com/google/common/collect/ListsTest.java
@@ -418,7 +418,7 @@ public class ListsTest extends TestCase {
}
private void checkFooBarBazList(List<String> list) {
- assertThat(list).has().exactly("foo", "bar", "baz").inOrder();
+ assertThat(list).containsExactly("foo", "bar", "baz").inOrder();
assertEquals(3, list.size());
assertIndexIsOutOfBounds(list, -1);
assertEquals("foo", list.get(0));
@@ -429,7 +429,7 @@ public class ListsTest extends TestCase {
public void testAsList1Small() {
List<String> list = Lists.asList("foo", new String[0]);
- assertThat(list).has().item("foo");
+ assertThat(list).contains("foo");
assertEquals(1, list.size());
assertIndexIsOutOfBounds(list, -1);
assertEquals("foo", list.get(0));
@@ -460,7 +460,7 @@ public class ListsTest extends TestCase {
@GwtIncompatible("SerializableTester")
public void testAsList2Small() {
List<String> list = Lists.asList("foo", "bar", new String[0]);
- assertThat(list).has().exactly("foo", "bar").inOrder();
+ assertThat(list).containsExactly("foo", "bar").inOrder();
assertEquals(2, list.size());
assertIndexIsOutOfBounds(list, -1);
assertEquals("foo", list.get(0));
@@ -532,24 +532,24 @@ public class ListsTest extends TestCase {
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_binary1x1() {
- assertThat(Lists.cartesianProduct(list(1), list(2))).has().item(list(1, 2));
+ assertThat(Lists.cartesianProduct(list(1), list(2))).contains(list(1, 2));
}
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_binary1x2() {
assertThat(Lists.cartesianProduct(list(1), list(2, 3)))
- .has().exactly(list(1, 2), list(1, 3)).inOrder();
+ .containsExactly(list(1, 2), list(1, 3)).inOrder();
}
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_binary2x2() {
assertThat(Lists.cartesianProduct(list(1, 2), list(3, 4)))
- .has().exactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
+ .containsExactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
}
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_2x2x2() {
- assertThat(Lists.cartesianProduct(list(0, 1), list(0, 1), list(0, 1))).has().exactly(
+ assertThat(Lists.cartesianProduct(list(0, 1), list(0, 1), list(0, 1))).containsExactly(
list(0, 0, 0), list(0, 0, 1), list(0, 1, 0), list(0, 1, 1),
list(1, 0, 0), list(1, 0, 1), list(1, 1, 0), list(1, 1, 1)).inOrder();
}
@@ -575,7 +575,7 @@ public class ListsTest extends TestCase {
List<Object> exp4 = list((Object) 2, "4");
assertThat(Lists.<Object>cartesianProduct(x, y))
- .has().exactly(exp1, exp2, exp3, exp4).inOrder();
+ .containsExactly(exp1, exp2, exp3, exp4).inOrder();
}
@SuppressWarnings("unchecked") // varargs!
@@ -666,7 +666,7 @@ public class ListsTest extends TestCase {
public void testTransformSequential() {
List<String> list = Lists.transform(SOME_SEQUENTIAL_LIST, SOME_FUNCTION);
- assertFalse(list instanceof RandomAccess);
+ assertThat(list).isNotInstanceOf(RandomAccess.class);
}
public void testTransformListIteratorRandomAccess() {
@@ -861,9 +861,9 @@ public class ListsTest extends TestCase {
public void testPartitionRandomAccessFalse() {
List<Integer> source = Lists.newLinkedList(asList(1, 2, 3));
List<List<Integer>> partitions = Lists.partition(source, 2);
- assertFalse(partitions instanceof RandomAccess);
- assertFalse(partitions.get(0) instanceof RandomAccess);
- assertFalse(partitions.get(1) instanceof RandomAccess);
+ assertThat(partitions).isNotInstanceOf(RandomAccess.class);
+ assertThat(partitions.get(0)).isNotInstanceOf(RandomAccess.class);
+ assertThat(partitions.get(1)).isNotInstanceOf(RandomAccess.class);
}
// TODO: use the ListTestSuiteBuilder
diff --git a/guava-tests/test/com/google/common/collect/MapConstraintsTest.java b/guava-tests/test/com/google/common/collect/MapConstraintsTest.java
index 70ac072..006b1a8 100644
--- a/guava-tests/test/com/google/common/collect/MapConstraintsTest.java
+++ b/guava-tests/test/com/google/common/collect/MapConstraintsTest.java
@@ -112,10 +112,10 @@ public class MapConstraintsTest extends TestCase {
assertEquals(map.keySet(), constrained.keySet());
assertEquals(HashMultiset.create(map.values()),
HashMultiset.create(constrained.values()));
- assertFalse(map.values() instanceof Serializable);
+ assertThat(map.values()).isNotInstanceOf(Serializable.class);
assertEquals(map.toString(), constrained.toString());
assertEquals(map.hashCode(), constrained.hashCode());
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
Maps.immutableEntry(TEST_KEY, TEST_VALUE),
Maps.immutableEntry("foo", 1),
Maps.immutableEntry("bar", 2),
@@ -163,7 +163,7 @@ public class MapConstraintsTest extends TestCase {
assertEquals(map.values(), constrained.values());
assertEquals(map.toString(), constrained.toString());
assertEquals(map.hashCode(), constrained.hashCode());
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
Maps.immutableEntry(TEST_KEY, TEST_VALUE),
Maps.immutableEntry("foo", 1),
Maps.immutableEntry("bar", 2),
@@ -232,7 +232,7 @@ public class MapConstraintsTest extends TestCase {
assertTrue(constrained.equals(multimap));
assertThat(ImmutableList.copyOf(multimap.entries())).isEqualTo(
ImmutableList.copyOf(constrained.entries()));
- assertThat(constrained.asMap().get("foo")).has().item(1);
+ assertThat(constrained.asMap().get("foo")).contains(1);
assertNull(constrained.asMap().get("missing"));
assertEquals(multimap.asMap(), constrained.asMap());
assertEquals(multimap.values(), constrained.values());
@@ -240,7 +240,7 @@ public class MapConstraintsTest extends TestCase {
assertEquals(multimap.keySet(), constrained.keySet());
assertEquals(multimap.toString(), constrained.toString());
assertEquals(multimap.hashCode(), constrained.hashCode());
- assertThat(multimap.entries()).has().exactly(
+ assertThat(multimap.entries()).containsExactly(
Maps.immutableEntry(TEST_KEY, TEST_VALUE),
Maps.immutableEntry("foo", 1),
Maps.immutableEntry("bar", 2),
@@ -253,9 +253,8 @@ public class MapConstraintsTest extends TestCase {
Maps.immutableEntry("bop", 9),
Maps.immutableEntry("dig", 10),
Maps.immutableEntry("dag", 11)).inOrder();
- assertFalse(constrained.asMap().values() instanceof Serializable);
- Iterator<Collection<Integer>> iterator =
- constrained.asMap().values().iterator();
+ assertThat(constrained.asMap().values()).isNotInstanceOf(Serializable.class);
+ Iterator<Collection<Integer>> iterator = constrained.asMap().values().iterator();
iterator.next();
iterator.next().add(12);
assertTrue(multimap.containsEntry("foo", 12));
@@ -540,7 +539,18 @@ public class MapConstraintsTest extends TestCase {
Collection<Map.Entry<String, Integer>> entries = constrained.entries();
assertFalse(entries.remove(nefariousEntry));
assertFalse(multimap.containsValue(TEST_VALUE));
- assertFalse(entries.removeAll(Collections.singleton(nefariousEntry)));
+ /*
+ * Either the Multimap should reject the nefarious internalEntry.setValue() call that
+ * queryEntry.equals() makes, or it should arrange for internalEntry.equals(queryEntry) to be
+ * used instead of the reverse so that queryEntry.equals(internalEntry) is never invoked.
+ *
+ * Probably the other tests should be similarly tolerant of either outcome. But for now, this is
+ * the only one failing in any of our environments.
+ */
+ try {
+ assertFalse(entries.removeAll(Collections.singleton(nefariousEntry)));
+ } catch (TestValueException tolerated) {
+ }
assertFalse(multimap.containsValue(TEST_VALUE));
}
diff --git a/guava-tests/test/com/google/common/collect/MapMakerInternalMapTest.java b/guava-tests/test/com/google/common/collect/MapMakerInternalMapTest.java
index c8c4d47..ce4d2d1 100644
--- a/guava-tests/test/com/google/common/collect/MapMakerInternalMapTest.java
+++ b/guava-tests/test/com/google/common/collect/MapMakerInternalMapTest.java
@@ -21,6 +21,7 @@ import static com.google.common.collect.MapMakerInternalMap.DISCARDING_QUEUE;
import static com.google.common.collect.MapMakerInternalMap.DRAIN_THRESHOLD;
import static com.google.common.collect.MapMakerInternalMap.nullEntry;
import static com.google.common.collect.MapMakerInternalMap.unset;
+import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.base.Equivalence;
@@ -93,7 +94,7 @@ public class MapMakerInternalMapTest extends TestCase {
assertEquals(4, map.concurrencyLevel);
// concurrency level
- assertEquals(4, map.segments.length);
+ assertThat(map.segments).hasLength(4);
// initial capacity / concurrency level
assertEquals(16 / map.segments.length, map.segments[0].table.length());
@@ -138,7 +139,7 @@ public class MapMakerInternalMapTest extends TestCase {
private static void checkConcurrencyLevel(int concurrencyLevel, int segmentCount) {
MapMakerInternalMap<Object, Object> map =
makeMap(createMapMaker().concurrencyLevel(concurrencyLevel));
- assertEquals(segmentCount, map.segments.length);
+ assertThat(map.segments).hasLength(segmentCount);
}
public void testSetInitialCapacity() {
diff --git a/guava-tests/test/com/google/common/collect/MapsTest.java b/guava-tests/test/com/google/common/collect/MapsTest.java
index 226d831..6ad3caa 100644
--- a/guava-tests/test/com/google/common/collect/MapsTest.java
+++ b/guava-tests/test/com/google/common/collect/MapsTest.java
@@ -106,7 +106,7 @@ public class MapsTest extends TestCase {
try {
Maps.capacity(-1);
fail("Negative expected size must result in IllegalArgumentException");
- } catch (IllegalArgumentException ex) {
+ } catch (IllegalArgumentException expected) {
}
}
@@ -120,35 +120,58 @@ public class MapsTest extends TestCase {
* This test may fail miserably on non-OpenJDK environments...
*/
@GwtIncompatible("reflection")
+ @SuppressUnderAndroid // relies on assumptions about OpenJDK
public void testNewHashMapWithExpectedSize_wontGrow() throws Exception {
// before jdk7u40: creates one-bucket table
// after jdk7u40: creates empty table
assertTrue(bucketsOf(Maps.newHashMapWithExpectedSize(0)) <= 1);
for (int size = 1; size < 200; size++) {
- HashMap<Integer, Void> map1 = Maps.newHashMapWithExpectedSize(size);
+ assertWontGrow(size,
+ Maps.newHashMapWithExpectedSize(size),
+ Maps.newHashMapWithExpectedSize(size));
+ }
+ }
- // Only start measuring table size after the first element inserted, to
- // deal with empty-map optimization.
- map1.put(0, null);
+ /**
+ * Same test as above but for newLinkedHashMapWithExpectedSize
+ */
+ @GwtIncompatible("reflection")
+ @SuppressUnderAndroid // relies on assumptions about OpenJDK
+ public void testNewLinkedHashMapWithExpectedSize_wontGrow() throws Exception {
+ assertTrue(bucketsOf(Maps.newLinkedHashMapWithExpectedSize(0)) <= 1);
- int initialBuckets = bucketsOf(map1);
+ for (int size = 1; size < 200; size++) {
+ assertWontGrow(size,
+ Maps.newLinkedHashMapWithExpectedSize(size),
+ Maps.newLinkedHashMapWithExpectedSize(size));
+ }
+ }
- for (int i = 1; i < size; i++) {
- map1.put(i, null);
- }
- assertEquals("table size after adding " + size + " elements",
- initialBuckets, bucketsOf(map1));
+ @GwtIncompatible("reflection")
+ private static void assertWontGrow(
+ int size, HashMap<Object, Object> map1, HashMap<Object, Object> map2) throws Exception {
+ // Only start measuring table size after the first element inserted, to
+ // deal with empty-map optimization.
+ map1.put(0, null);
+
+ int initialBuckets = bucketsOf(map1);
- /*
- * Something slightly different happens when the entries are added all at
- * once; make sure that passes too.
- */
- HashMap<Integer, Void> map2 = Maps.newHashMapWithExpectedSize(size);
- map2.putAll(map1);
- assertEquals("table size after adding " + size + "elements",
- initialBuckets, bucketsOf(map2));
+ for (int i = 1; i < size; i++) {
+ map1.put(i, null);
}
+ assertThat(bucketsOf(map1))
+ .named("table size after adding " + size + " elements")
+ .isEqualTo(initialBuckets);
+
+ /*
+ * Something slightly different happens when the entries are added all at
+ * once; make sure that passes too.
+ */
+ map2.putAll(map1);
+ assertThat(bucketsOf(map1))
+ .named("table size after adding " + size + " elements")
+ .isEqualTo(initialBuckets);
}
@GwtIncompatible("reflection")
@@ -156,7 +179,8 @@ public class MapsTest extends TestCase {
Field tableField = HashMap.class.getDeclaredField("table");
tableField.setAccessible(true);
Object[] table = (Object[]) tableField.get(hashMap);
- return table.length;
+ // In JDK8, table is set lazily, so it may be null.
+ return table == null ? 0 : table.length;
}
public void testCapacityForLargeSizes() {
@@ -244,9 +268,9 @@ public class MapsTest extends TestCase {
assertEquals(Collections.emptyMap(), map);
map.put(new Derived("foo"), 1);
map.put(new Derived("bar"), 2);
- assertThat(map.keySet()).has().exactly(
+ assertThat(map.keySet()).containsExactly(
new Derived("bar"), new Derived("foo")).inOrder();
- assertThat(map.values()).has().exactly(2, 1).inOrder();
+ assertThat(map.values()).containsExactly(2, 1).inOrder();
assertNull(map.comparator());
}
@@ -255,9 +279,9 @@ public class MapsTest extends TestCase {
assertEquals(Collections.emptyMap(), map);
map.put(new LegacyComparable("foo"), 1);
map.put(new LegacyComparable("bar"), 2);
- assertThat(map.keySet()).has().exactly(
+ assertThat(map.keySet()).containsExactly(
new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
- assertThat(map.values()).has().exactly(2, 1).inOrder();
+ assertThat(map.values()).containsExactly(2, 1).inOrder();
assertNull(map.comparator());
}
@@ -526,13 +550,13 @@ public class MapsTest extends TestCase {
SortedMapDifference<Integer, String> diff1 =
Maps.difference(left, right);
assertFalse(diff1.areEqual());
- assertThat(diff1.entriesOnlyOnLeft().entrySet()).has().exactly(
+ assertThat(diff1.entriesOnlyOnLeft().entrySet()).containsExactly(
Maps.immutableEntry(4, "d"), Maps.immutableEntry(2, "b")).inOrder();
- assertThat(diff1.entriesOnlyOnRight().entrySet()).has().item(
+ assertThat(diff1.entriesOnlyOnRight().entrySet()).contains(
Maps.immutableEntry(6, "z"));
- assertThat(diff1.entriesInCommon().entrySet()).has().item(
+ assertThat(diff1.entriesInCommon().entrySet()).contains(
Maps.immutableEntry(1, "a"));
- assertThat(diff1.entriesDiffering().entrySet()).has().exactly(
+ assertThat(diff1.entriesDiffering().entrySet()).containsExactly(
Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g")),
Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f"))).inOrder();
assertEquals("not equal: only on left={4=d, 2=b}: only on right={6=z}: "
@@ -541,11 +565,11 @@ public class MapsTest extends TestCase {
SortedMapDifference<Integer, String> diff2 =
Maps.difference(right, left);
assertFalse(diff2.areEqual());
- assertThat(diff2.entriesOnlyOnLeft().entrySet()).has().item(
+ assertThat(diff2.entriesOnlyOnLeft().entrySet()).contains(
Maps.immutableEntry(6, "z"));
- assertThat(diff2.entriesOnlyOnRight().entrySet()).has().exactly(
+ assertThat(diff2.entriesOnlyOnRight().entrySet()).containsExactly(
Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder();
- assertThat(diff1.entriesInCommon().entrySet()).has().item(
+ assertThat(diff1.entriesInCommon().entrySet()).contains(
Maps.immutableEntry(1, "a"));
assertEquals(ImmutableMap.of(
3, ValueDifferenceImpl.create("f", "c"),
@@ -565,13 +589,13 @@ public class MapsTest extends TestCase {
Maps.difference(left, right);
left.put(6, "z");
assertFalse(diff1.areEqual());
- assertThat(diff1.entriesOnlyOnLeft().entrySet()).has().exactly(
+ assertThat(diff1.entriesOnlyOnLeft().entrySet()).containsExactly(
Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder();
- assertThat(diff1.entriesOnlyOnRight().entrySet()).has().item(
+ assertThat(diff1.entriesOnlyOnRight().entrySet()).contains(
Maps.immutableEntry(6, "z"));
- assertThat(diff1.entriesInCommon().entrySet()).has().item(
+ assertThat(diff1.entriesInCommon().entrySet()).contains(
Maps.immutableEntry(1, "a"));
- assertThat(diff1.entriesDiffering().entrySet()).has().exactly(
+ assertThat(diff1.entriesDiffering().entrySet()).containsExactly(
Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f")),
Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g"))).inOrder();
try {
@@ -628,7 +652,7 @@ public class MapsTest extends TestCase {
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
assertEquals(Integer.valueOf(5), map.get("three"));
assertNull(map.get("five"));
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("two", 3),
mapEntry("three", 5)).inOrder();
@@ -651,7 +675,7 @@ public class MapsTest extends TestCase {
Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
assertEquals(Integer.valueOf(3), map.remove("two"));
- assertThat(strings).has().exactly("one", "three").inOrder();
+ assertThat(strings).containsExactly("one", "three").inOrder();
}
public void testAsMapEmpty() {
@@ -684,14 +708,14 @@ public class MapsTest extends TestCase {
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
assertEquals(Integer.valueOf(5), map.get("three"));
assertNull(map.get("five"));
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("three", 5),
mapEntry("two", 3)).inOrder();
- assertThat(map.tailMap("onea").entrySet()).has().exactly(
+ assertThat(map.tailMap("onea").entrySet()).containsExactly(
mapEntry("three", 5),
mapEntry("two", 3)).inOrder();
- assertThat(map.subMap("one", "two").entrySet()).has().exactly(
+ assertThat(map.subMap("one", "two").entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("three", 5)).inOrder();
}
@@ -717,7 +741,7 @@ public class MapsTest extends TestCase {
assertEquals(
ImmutableSortedMap.of("five", 4, "four", 4, "three", 5),
headMap);
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("five", 4),
mapEntry("four", 4),
mapEntry("three", 5),
@@ -730,7 +754,7 @@ public class MapsTest extends TestCase {
SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
assertEquals(Integer.valueOf(3), map.remove("two"));
- assertThat(strings).has().exactly("one", "three").inOrder();
+ assertThat(strings).containsExactly("one", "three").inOrder();
}
public void testAsMapSortedSubViewKeySetsDoNotSupportAdd() {
@@ -780,14 +804,14 @@ public class MapsTest extends TestCase {
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
assertEquals(Integer.valueOf(5), map.get("three"));
assertNull(map.get("five"));
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("three", 5),
mapEntry("two", 3)).inOrder();
- assertThat(map.tailMap("onea").entrySet()).has().exactly(
+ assertThat(map.tailMap("onea").entrySet()).containsExactly(
mapEntry("three", 5),
mapEntry("two", 3)).inOrder();
- assertThat(map.subMap("one", "two").entrySet()).has().exactly(
+ assertThat(map.subMap("one", "two").entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("three", 5)).inOrder();
@@ -809,19 +833,19 @@ public class MapsTest extends TestCase {
assertEquals("one", map.floorKey("r"));
assertEquals("three", map.floorKey("three"));
- assertThat(map.descendingMap().entrySet()).has().exactly(
+ assertThat(map.descendingMap().entrySet()).containsExactly(
mapEntry("two", 3),
mapEntry("three", 5),
mapEntry("one", 3)).inOrder();
assertEquals(map.headMap("three", true),
map.descendingMap().tailMap("three", true));
- assertThat(map.tailMap("three", false).entrySet()).has().item(
+ assertThat(map.tailMap("three", false).entrySet()).contains(
mapEntry("two", 3));
assertNull(map.tailMap("three", true).lowerEntry("three"));
- assertThat(map.headMap("two", false).values()).has().exactly(3, 5).inOrder();
+ assertThat(map.headMap("two", false).values()).containsExactly(3, 5).inOrder();
assertThat(map.headMap("two", false).descendingMap().values())
- .has().exactly(5, 3).inOrder();
- assertThat(map.descendingKeySet()).has().exactly(
+ .containsExactly(5, 3).inOrder();
+ assertThat(map.descendingKeySet()).containsExactly(
"two", "three", "one").inOrder();
assertEquals(mapEntry("one", 3), map.pollFirstEntry());
@@ -851,7 +875,7 @@ public class MapsTest extends TestCase {
assertEquals(
ImmutableSortedMap.of("five", 4, "four", 4, "three", 5),
headMap);
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("five", 4),
mapEntry("four", 4),
mapEntry("three", 5),
@@ -862,10 +886,10 @@ public class MapsTest extends TestCase {
strings.add("six");
strings.remove("two");
- assertThat(tailMap.entrySet()).has().exactly(
+ assertThat(tailMap.entrySet()).containsExactly(
mapEntry("six", 3),
mapEntry("three", 5)).inOrder();
- assertThat(subMap.entrySet()).has().exactly(
+ assertThat(subMap.entrySet()).containsExactly(
mapEntry("five", 4),
mapEntry("four", 4),
mapEntry("six", 3)).inOrder();
@@ -878,10 +902,10 @@ public class MapsTest extends TestCase {
NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
assertEquals(Integer.valueOf(3), map.remove("two"));
- assertThat(strings).has().exactly("one", "three").inOrder();
+ assertThat(strings).containsExactly("one", "three").inOrder();
assertEquals(mapEntry("three", 5),
map.subMap("one", false, "zzz", true).pollLastEntry());
- assertThat(strings).has().item("one");
+ assertThat(strings).contains("one");
}
@GwtIncompatible("NavigableMap")
@@ -928,7 +952,7 @@ public class MapsTest extends TestCase {
Iterable<String> strings = ImmutableList.of("one", "two", "three");
ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("two", 3),
mapEntry("three", 5)).inOrder();
@@ -938,7 +962,7 @@ public class MapsTest extends TestCase {
Iterator<String> strings = ImmutableList.of("one", "two", "three").iterator();
ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("two", 3),
mapEntry("three", 5)).inOrder();
@@ -948,7 +972,7 @@ public class MapsTest extends TestCase {
Iterable<String> strings = ImmutableList.of("one", "two", "three", "two", "one");
ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
- assertThat(map.entrySet()).has().exactly(
+ assertThat(map.entrySet()).containsExactly(
mapEntry("one", 3),
mapEntry("two", 3),
mapEntry("three", 5)).inOrder();
@@ -1011,6 +1035,7 @@ public class MapsTest extends TestCase {
Maps.uniqueIndex(ImmutableSet.of("one", "uno"), Functions.constant(1));
fail();
} catch (IllegalArgumentException expected) {
+ assertThat(expected.getMessage()).contains("Multimaps.index");
}
}
diff --git a/guava-tests/test/com/google/common/collect/MinMaxPriorityQueueTest.java b/guava-tests/test/com/google/common/collect/MinMaxPriorityQueueTest.java
index 803f63f..fa1ea97 100644
--- a/guava-tests/test/com/google/common/collect/MinMaxPriorityQueueTest.java
+++ b/guava-tests/test/com/google/common/collect/MinMaxPriorityQueueTest.java
@@ -355,7 +355,7 @@ public class MinMaxPriorityQueueTest extends TestCase {
}
}
assertTrue(q.isIntact());
- assertThat(result).has().exactly(1, 15, 13, 8, 14);
+ assertThat(result).containsExactly(1, 15, 13, 8, 14);
}
/**
@@ -718,23 +718,23 @@ public class MinMaxPriorityQueueTest extends TestCase {
List<Integer> contents = Lists.newArrayList(expected);
List<Integer> elements = Lists.newArrayListWithCapacity(size);
while (!q.isEmpty()) {
- assertThat(q).has().exactlyAs(contents);
+ assertThat(q).containsExactlyElementsIn(contents);
Integer next = q.pollFirst();
contents.remove(next);
- assertThat(q).has().exactlyAs(contents);
+ assertThat(q).containsExactlyElementsIn(contents);
for (int i = 0; i <= size; i++) {
q.add(i);
contents.add(i);
- assertThat(q).has().exactlyAs(contents);
+ assertThat(q).containsExactlyElementsIn(contents);
q.add(next);
contents.add(next);
- assertThat(q).has().exactlyAs(contents);
+ assertThat(q).containsExactlyElementsIn(contents);
q.remove(i);
assertTrue(contents.remove(Integer.valueOf(i)));
- assertThat(q).has().exactlyAs(contents);
+ assertThat(q).containsExactlyElementsIn(contents);
assertEquals(next, q.poll());
contents.remove(next);
- assertThat(q).has().exactlyAs(contents);
+ assertThat(q).containsExactlyElementsIn(contents);
}
elements.add(next);
}
diff --git a/guava-tests/test/com/google/common/collect/MultimapsTest.java b/guava-tests/test/com/google/common/collect/MultimapsTest.java
index 43123ef..d4b5ec1 100644
--- a/guava-tests/test/com/google/common/collect/MultimapsTest.java
+++ b/guava-tests/test/com/google/common/collect/MultimapsTest.java
@@ -70,14 +70,6 @@ public class MultimapsTest extends TestCase {
private static final Comparator<Integer> INT_COMPARATOR =
Ordering.<Integer>natural().reverse().nullsFirst();
- private static final EntryTransformer<Object, Object, Object> ALWAYS_NULL =
- new EntryTransformer<Object, Object, Object>() {
- @Override
- public Object transformEntry(Object k, Object v1) {
- return null;
- }
- };
-
@SuppressWarnings("deprecation")
public void testUnmodifiableListMultimapShortCircuit() {
ListMultimap<String, Integer> mod = ArrayListMultimap.create();
@@ -142,10 +134,9 @@ public class MultimapsTest extends TestCase {
ListMultimap<String, Integer> delegate = LinkedListMultimap.create();
delegate.put("foo", 1);
delegate.put("foo", 3);
- ListMultimap<String, Integer> multimap
- = Multimaps.unmodifiableListMultimap(delegate);
- assertFalse(multimap.get("foo") instanceof RandomAccess);
- assertFalse(multimap.get("bar") instanceof RandomAccess);
+ ListMultimap<String, Integer> multimap = Multimaps.unmodifiableListMultimap(delegate);
+ assertThat(multimap.get("foo")).isNotInstanceOf(RandomAccess.class);
+ assertThat(multimap.get("bar")).isNotInstanceOf(RandomAccess.class);
}
@GwtIncompatible("slow (~10s)")
@@ -297,10 +288,10 @@ public class MultimapsTest extends TestCase {
assertEquals(multimap.hashCode(), unmodifiable.hashCode());
assertEquals(multimap, unmodifiable);
- assertThat(unmodifiable.asMap().get("bar")).has().exactly(5, -1);
+ assertThat(unmodifiable.asMap().get("bar")).containsExactly(5, -1);
assertNull(unmodifiable.asMap().get("missing"));
- assertFalse(unmodifiable.entries() instanceof Serializable);
+ assertThat(unmodifiable.entries()).isNotInstanceOf(Serializable.class);
}
/**
@@ -454,13 +445,11 @@ public class MultimapsTest extends TestCase {
assertFalse(map.containsKey("bar"));
assertEquals(map.keySet(), multimapView.keySet());
assertEquals(map.keySet(), multimapView.keys().elementSet());
- assertThat(multimapView.keys()).has().item("foo");
- assertThat(multimapView.values()).has().item(1);
- assertThat(multimapView.entries()).has().item(
- Maps.immutableEntry("foo", 1));
- assertThat(multimapView.asMap().entrySet()).has().item(
- Maps.immutableEntry(
- "foo", (Collection<Integer>) Collections.singleton(1)));
+ assertThat(multimapView.keys()).contains("foo");
+ assertThat(multimapView.values()).contains(1);
+ assertThat(multimapView.entries()).contains(Maps.immutableEntry("foo", 1));
+ assertThat(multimapView.asMap().entrySet())
+ .contains(Maps.immutableEntry("foo", (Collection<Integer>) Collections.singleton(1)));
multimapView.clear();
assertFalse(multimapView.containsKey("foo"));
assertFalse(map.containsKey("foo"));
@@ -615,7 +604,7 @@ public class MultimapsTest extends TestCase {
} catch (IllegalArgumentException expected) {
// expected
}
- assertThat(multimap.entries()).has().exactly(
+ assertThat(multimap.entries()).containsExactly(
Maps.immutableEntry(Color.RED, 1),
Maps.immutableEntry(Color.BLUE, 2));
}
@@ -640,8 +629,8 @@ public class MultimapsTest extends TestCase {
Collection<Integer> collection = multimap.get(Color.BLUE);
assertEquals(collection, collection);
- assertFalse(multimap.keySet() instanceof SortedSet);
- assertFalse(multimap.asMap() instanceof SortedMap);
+ assertThat(multimap.keySet()).isNotInstanceOf(SortedSet.class);
+ assertThat(multimap.asMap()).isNotInstanceOf(SortedMap.class);
}
@GwtIncompatible("SerializableTester")
@@ -673,7 +662,7 @@ public class MultimapsTest extends TestCase {
multimap.putAll(Color.RED, asList(2, 7, 1, 8));
assertEquals(2, factory.count);
assertEquals("{BLUE=[3, 1, 4, 1], RED=[2, 7, 1, 8]}", multimap.toString());
- assertFalse(multimap.get(Color.BLUE) instanceof RandomAccess);
+ assertThat(multimap.get(Color.BLUE)).isNotInstanceOf(RandomAccess.class);
assertTrue(multimap.keySet() instanceof SortedSet);
assertTrue(multimap.asMap() instanceof SortedMap);
@@ -838,7 +827,7 @@ public class MultimapsTest extends TestCase {
}
};
Multimap<String, Integer> transformed = Multimaps.transformValues(multimap, square);
- assertThat(transformed.entries()).has().exactly(immutableEntry("a", 4),
+ assertThat(transformed.entries()).containsExactly(immutableEntry("a", 4),
immutableEntry("a", 16), immutableEntry("b", 9), immutableEntry("b", 9),
immutableEntry("c", 36)).inOrder();
}
@@ -856,7 +845,7 @@ public class MultimapsTest extends TestCase {
});
Entry<String, String> entry = multimap.entries().iterator().next();
entry.setValue("bbb");
- assertThat(transformed.entries()).has().exactly(immutableEntry("a", 3)).inOrder();
+ assertThat(transformed.entries()).containsExactly(immutableEntry("a", 3));
}
@GwtIncompatible(value = "untested")
@@ -871,7 +860,7 @@ public class MultimapsTest extends TestCase {
};
ListMultimap<String, Integer> transformed =
Multimaps.transformValues(multimap, square);
- assertThat(transformed.entries()).has().exactly(immutableEntry("a", 4),
+ assertThat(transformed.entries()).containsExactly(immutableEntry("a", 4),
immutableEntry("a", 16), immutableEntry("b", 9), immutableEntry("b", 9),
immutableEntry("c", 36)).inOrder();
}
@@ -889,7 +878,7 @@ public class MultimapsTest extends TestCase {
};
Multimap<String, String> transformed =
Multimaps.transformEntries(multimap, transformer);
- assertThat(transformed.entries()).has().exactly(immutableEntry("a", "a"),
+ assertThat(transformed.entries()).containsExactly(immutableEntry("a", "a"),
immutableEntry("a", "a"), immutableEntry("b", "nob")).inOrder();
}
diff --git a/guava-tests/test/com/google/common/collect/MultisetsTest.java b/guava-tests/test/com/google/common/collect/MultisetsTest.java
index 6623e15..1ca6ccc 100644
--- a/guava-tests/test/com/google/common/collect/MultisetsTest.java
+++ b/guava-tests/test/com/google/common/collect/MultisetsTest.java
@@ -46,7 +46,7 @@ public class MultisetsTest extends TestCase {
assertTrue(set.isEmpty());
set.add(new DerivedComparable("foo"), 2);
set.add(new DerivedComparable("bar"), 3);
- assertThat(set).has().exactly(
+ assertThat(set).containsExactly(
new DerivedComparable("bar"), new DerivedComparable("bar"), new DerivedComparable("bar"),
new DerivedComparable("foo"), new DerivedComparable("foo")).inOrder();
}
@@ -56,7 +56,7 @@ public class MultisetsTest extends TestCase {
assertTrue(set.isEmpty());
set.add(new LegacyComparable("foo"), 2);
set.add(new LegacyComparable("bar"), 3);
- assertThat(set).has().exactly(new LegacyComparable("bar"),
+ assertThat(set).containsExactly(new LegacyComparable("bar"),
new LegacyComparable("bar"), new LegacyComparable("bar"),
new LegacyComparable("foo"), new LegacyComparable("foo")).inOrder();
}
@@ -66,7 +66,7 @@ public class MultisetsTest extends TestCase {
= TreeMultiset.create(Collections.reverseOrder());
multiset.add("bar", 3);
multiset.add("foo", 2);
- assertThat(multiset).has().exactly("foo", "foo", "bar", "bar", "bar").inOrder();
+ assertThat(multiset).containsExactly("foo", "foo", "bar", "bar", "bar").inOrder();
}
public void testRetainOccurrencesEmpty() {
@@ -88,7 +88,7 @@ public class MultisetsTest extends TestCase {
Multiset<String> multiset = HashMultiset.create();
Multiset<String> toRemove =
HashMultiset.create(Arrays.asList("a", "b", "a"));
- assertFalse(Multisets.retainOccurrences(multiset, toRemove));
+ assertFalse(Multisets.removeOccurrences(multiset, toRemove));
assertTrue(multiset.isEmpty());
}
@@ -96,7 +96,7 @@ public class MultisetsTest extends TestCase {
Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> ms2 = HashMultiset.create(
Arrays.asList("a", "b", "b", "c"));
- assertThat(Multisets.union(ms1, ms2)).has().exactly("a", "a", "b", "b", "c");
+ assertThat(Multisets.union(ms1, ms2)).containsExactly("a", "a", "b", "b", "c");
}
public void testUnionEqualMultisets() {
@@ -132,38 +132,38 @@ public class MultisetsTest extends TestCase {
public void testSum() {
Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> ms2 = HashMultiset.create(Arrays.asList("b", "c"));
- assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "a", "b", "b", "c");
+ assertThat(Multisets.sum(ms1, ms2)).containsExactly("a", "a", "b", "b", "c");
}
public void testSumEmptyNonempty() {
Multiset<String> ms1 = HashMultiset.create();
Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
- assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "b", "a");
+ assertThat(Multisets.sum(ms1, ms2)).containsExactly("a", "b", "a");
}
public void testSumNonemptyEmpty() {
Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> ms2 = HashMultiset.create();
- assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "b", "a");
+ assertThat(Multisets.sum(ms1, ms2)).containsExactly("a", "b", "a");
}
public void testDifferenceWithNoRemovedElements() {
Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a"));
- assertThat(Multisets.difference(ms1, ms2)).has().exactly("a", "b");
+ assertThat(Multisets.difference(ms1, ms2)).containsExactly("a", "b");
}
public void testDifferenceWithRemovedElement() {
Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> ms2 = HashMultiset.create(Arrays.asList("b"));
- assertThat(Multisets.difference(ms1, ms2)).has().exactly("a", "a");
+ assertThat(Multisets.difference(ms1, ms2)).containsExactly("a", "a");
}
public void testDifferenceWithMoreElementsInSecondMultiset() {
Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "b", "b"));
Multiset<String> diff = Multisets.difference(ms1, ms2);
- assertThat(diff).has().item("a");
+ assertThat(diff).contains("a");
assertEquals(0, diff.count("b"));
assertEquals(1, diff.count("a"));
assertFalse(diff.contains("b"));
@@ -213,7 +213,7 @@ public class MultisetsTest extends TestCase {
Multiset<String> toRetain =
HashMultiset.create(Arrays.asList("a", "b", "b"));
assertTrue(Multisets.retainOccurrences(multiset, toRetain));
- assertThat(multiset).has().exactly("a", "b").inOrder();
+ assertThat(multiset).containsExactly("a", "b").inOrder();
}
public void testRemoveEmptyOccurrencesMultiset() {
@@ -221,7 +221,7 @@ public class MultisetsTest extends TestCase {
TreeMultiset.create(Arrays.asList("a", "b", "a"));
Multiset<String> toRemove = HashMultiset.create();
assertFalse(Multisets.removeOccurrences(multiset, toRemove));
- assertThat(multiset).has().exactly("a", "a", "b").inOrder();
+ assertThat(multiset).containsExactly("a", "a", "b").inOrder();
}
public void testRemoveOccurrencesMultiset() {
@@ -230,7 +230,7 @@ public class MultisetsTest extends TestCase {
Multiset<String> toRemove =
HashMultiset.create(Arrays.asList("a", "b", "b"));
assertTrue(Multisets.removeOccurrences(multiset, toRemove));
- assertThat(multiset).has().exactly("a", "c").inOrder();
+ assertThat(multiset).containsExactly("a", "c").inOrder();
}
public void testRemoveEmptyOccurrencesIterable() {
@@ -238,7 +238,7 @@ public class MultisetsTest extends TestCase {
TreeMultiset.create(Arrays.asList("a", "b", "a"));
Iterable<String> toRemove = ImmutableList.of();
assertFalse(Multisets.removeOccurrences(multiset, toRemove));
- assertThat(multiset).has().exactly("a", "a", "b").inOrder();
+ assertThat(multiset).containsExactly("a", "a", "b").inOrder();
}
public void testRemoveOccurrencesMultisetIterable() {
@@ -246,7 +246,7 @@ public class MultisetsTest extends TestCase {
TreeMultiset.create(Arrays.asList("a", "b", "a", "c"));
List<String> toRemove = Arrays.asList("a", "b", "b");
assertTrue(Multisets.removeOccurrences(multiset, toRemove));
- assertThat(multiset).has().exactly("a", "c").inOrder();
+ assertThat(multiset).containsExactly("a", "c").inOrder();
}
@SuppressWarnings("deprecation")
@@ -266,11 +266,11 @@ public class MultisetsTest extends TestCase {
ImmutableMultiset<String> sortedMultiset =
Multisets.copyHighestCountFirst(multiset);
- assertThat(sortedMultiset.entrySet()).has().exactly(
+ assertThat(sortedMultiset.entrySet()).containsExactly(
Multisets.immutableEntry("a", 3), Multisets.immutableEntry("c", 2),
Multisets.immutableEntry("b", 1)).inOrder();
- assertThat(sortedMultiset).has().exactly(
+ assertThat(sortedMultiset).containsExactly(
"a",
"a",
"a",
diff --git a/guava-tests/test/com/google/common/collect/NewCustomTableTest.java b/guava-tests/test/com/google/common/collect/NewCustomTableTest.java
index 9355aad..64522b8 100644
--- a/guava-tests/test/com/google/common/collect/NewCustomTableTest.java
+++ b/guava-tests/test/com/google/common/collect/NewCustomTableTest.java
@@ -51,11 +51,11 @@ public class NewCustomTableTest extends AbstractTableTest {
public void testRowKeySetOrdering() {
table = create("foo", 3, 'a', "bar", 1, 'b', "foo", 2, 'c');
- assertThat(table.rowKeySet()).has().exactly("foo", "bar").inOrder();
+ assertThat(table.rowKeySet()).containsExactly("foo", "bar").inOrder();
}
public void testRowOrdering() {
table = create("foo", 3, 'a', "bar", 1, 'b', "foo", 2, 'c');
- assertThat(table.row("foo").keySet()).has().exactly(2, 3).inOrder();
+ assertThat(table.row("foo").keySet()).containsExactly(2, 3).inOrder();
}
}
diff --git a/guava-tests/test/com/google/common/collect/ObjectArraysTest.java b/guava-tests/test/com/google/common/collect/ObjectArraysTest.java
index c379857..b8dba1a 100644
--- a/guava-tests/test/com/google/common/collect/ObjectArraysTest.java
+++ b/guava-tests/test/com/google/common/collect/ObjectArraysTest.java
@@ -46,14 +46,14 @@ public class ObjectArraysTest extends TestCase {
public void testNewArray_fromClass_Empty() {
String[] empty = ObjectArrays.newArray(String.class, 0);
assertEquals(String[].class, empty.getClass());
- assertEquals(0, empty.length);
+ assertThat(empty).isEmpty();
}
@GwtIncompatible("ObjectArrays.newArray(Class, int)")
public void testNewArray_fromClass_Nonempty() {
String[] array = ObjectArrays.newArray(String.class, 2);
assertEquals(String[].class, array.getClass());
- assertEquals(2, array.length);
+ assertThat(array).hasLength(2);
assertNull(array[0]);
}
@@ -61,27 +61,27 @@ public class ObjectArraysTest extends TestCase {
public void testNewArray_fromClass_OfArray() {
String[][] array = ObjectArrays.newArray(String[].class, 1);
assertEquals(String[][].class, array.getClass());
- assertEquals(1, array.length);
+ assertThat(array).hasLength(1);
assertNull(array[0]);
}
public void testNewArray_fromArray_Empty() {
String[] in = new String[0];
String[] empty = ObjectArrays.newArray(in, 0);
- assertEquals(0, empty.length);
+ assertThat(empty).isEmpty();
}
public void testNewArray_fromArray_Nonempty() {
String[] array = ObjectArrays.newArray(new String[0], 2);
assertEquals(String[].class, array.getClass());
- assertEquals(2, array.length);
+ assertThat(array).hasLength(2);
assertNull(array[0]);
}
public void testNewArray_fromArray_OfArray() {
String[][] array = ObjectArrays.newArray(new String[0][0], 1);
assertEquals(String[][].class, array.getClass());
- assertEquals(1, array.length);
+ assertThat(array).hasLength(1);
assertNull(array[0]);
}
@@ -90,7 +90,7 @@ public class ObjectArraysTest extends TestCase {
String[] result
= ObjectArrays.concat(new String[0], new String[0], String.class);
assertEquals(String[].class, result.getClass());
- assertEquals(0, result.length);
+ assertThat(result).isEmpty();
}
@GwtIncompatible("ObjectArrays.concat(Object[], Object[], Class)")
@@ -98,7 +98,7 @@ public class ObjectArraysTest extends TestCase {
String[] result = ObjectArrays.concat(
new String[0], new String[] { "a", "b" }, String.class);
assertEquals(String[].class, result.getClass());
- assertThat(result).asList().has().exactly("a", "b").inOrder();
+ assertThat(result).asList().containsExactly("a", "b").inOrder();
}
@GwtIncompatible("ObjectArrays.concat(Object[], Object[], Class)")
@@ -106,7 +106,7 @@ public class ObjectArraysTest extends TestCase {
String[] result = ObjectArrays.concat(
new String[] { "a", "b" }, new String[0], String.class);
assertEquals(String[].class, result.getClass());
- assertThat(result).asList().has().exactly("a", "b").inOrder();
+ assertThat(result).asList().containsExactly("a", "b").inOrder();
}
@GwtIncompatible("ObjectArrays.concat(Object[], Object[], Class)")
@@ -114,7 +114,7 @@ public class ObjectArraysTest extends TestCase {
String[] result = ObjectArrays.concat(
new String[] { "a", "b" }, new String[] { "c", "d" }, String.class);
assertEquals(String[].class, result.getClass());
- assertThat(result).asList().has().exactly("a", "b", "c", "d").inOrder();
+ assertThat(result).asList().containsExactly("a", "b", "c", "d").inOrder();
}
@GwtIncompatible("ObjectArrays.concat(Object[], Object[], Class)")
@@ -170,32 +170,32 @@ public class ObjectArraysTest extends TestCase {
public void testPrependZeroElements() {
String[] result = ObjectArrays.concat("foo", new String[] {});
- assertThat(result).asList().has().item("foo");
+ assertThat(result).asList().contains("foo");
}
public void testPrependOneElement() {
String[] result = ObjectArrays.concat("foo", new String[] { "bar" });
- assertThat(result).asList().has().exactly("foo", "bar").inOrder();
+ assertThat(result).asList().containsExactly("foo", "bar").inOrder();
}
public void testPrependTwoElements() {
String[] result = ObjectArrays.concat("foo", new String[] { "bar", "baz" });
- assertThat(result).asList().has().exactly("foo", "bar", "baz").inOrder();
+ assertThat(result).asList().containsExactly("foo", "bar", "baz").inOrder();
}
public void testAppendZeroElements() {
String[] result = ObjectArrays.concat(new String[] {}, "foo");
- assertThat(result).asList().has().item("foo");
+ assertThat(result).asList().contains("foo");
}
public void testAppendOneElement() {
String[] result = ObjectArrays.concat(new String[] { "foo" }, "bar");
- assertThat(result).asList().has().exactly("foo", "bar").inOrder();
+ assertThat(result).asList().containsExactly("foo", "bar").inOrder();
}
public void testAppendTwoElements() {
String[] result = ObjectArrays.concat(new String[] { "foo", "bar" }, "baz");
- assertThat(result).asList().has().exactly("foo", "bar", "baz").inOrder();
+ assertThat(result).asList().containsExactly("foo", "bar", "baz").inOrder();
}
public void testEmptyArrayToEmpty() {
diff --git a/guava-tests/test/com/google/common/collect/OrderingTest.java b/guava-tests/test/com/google/common/collect/OrderingTest.java
index 8054740..8cc4cb7 100644
--- a/guava-tests/test/com/google/common/collect/OrderingTest.java
+++ b/guava-tests/test/com/google/common/collect/OrderingTest.java
@@ -72,6 +72,38 @@ public class OrderingTest extends TestCase {
assertEquals(strings, comparator.immutableSortedCopy(strings));
}
+ // From https://github.com/google/guava/issues/1342
+ public void testComplicatedOrderingExample() {
+ Integer nullInt = (Integer) null;
+ Ordering<Iterable<Integer>> example =
+ Ordering.<Integer>natural().nullsFirst().reverse().lexicographical().reverse().nullsLast();
+ List<Integer> list1 = Lists.newArrayList();
+ List<Integer> list2 = Lists.newArrayList(1);
+ List<Integer> list3 = Lists.newArrayList(1, 1);
+ List<Integer> list4 = Lists.newArrayList(1, 2);
+ List<Integer> list5 = Lists.newArrayList(1, null, 2);
+ List<Integer> list6 = Lists.newArrayList(2);
+ List<Integer> list7 = Lists.newArrayList(nullInt);
+ List<Integer> list8 = Lists.newArrayList(nullInt, nullInt);
+ List<List<Integer>> list =
+ Lists.newArrayList(list1, list2, list3, list4, list5, list6, list7, list8, null);
+ List<List<Integer>> sorted = example.sortedCopy(list);
+
+ // [[null, null], [null], [1, null, 2], [1, 1], [1, 2], [1], [2], [], null]
+ assertThat(sorted)
+ .containsExactly(
+ Lists.newArrayList(nullInt, nullInt),
+ Lists.newArrayList(nullInt),
+ Lists.newArrayList(1, null, 2),
+ Lists.newArrayList(1, 1),
+ Lists.newArrayList(1, 2),
+ Lists.newArrayList(1),
+ Lists.newArrayList(2),
+ Lists.newArrayList(),
+ null)
+ .inOrder();
+ }
+
public void testNatural() {
Ordering<Integer> comparator = Ordering.natural();
Helpers.testComparator(comparator,
@@ -157,7 +189,7 @@ public class OrderingTest extends TestCase {
= Ordering.explicit(2, 8, 6, 1, 7, 5, 3, 4, 0, 9);
List<Integer> list = Arrays.asList(0, 3, 5, 6, 7, 8, 9);
Collections.sort(list, c);
- assertThat(list).has().exactly(8, 6, 7, 5, 3, 0, 9).inOrder();
+ assertThat(list).containsExactly(8, 6, 7, 5, 3, 0, 9).inOrder();
reserializeAndAssert(c);
}
diff --git a/guava-tests/test/com/google/common/collect/RegularImmutableTableTest.java b/guava-tests/test/com/google/common/collect/RegularImmutableTableTest.java
index d1f97f5..c501baf 100644
--- a/guava-tests/test/com/google/common/collect/RegularImmutableTableTest.java
+++ b/guava-tests/test/com/google/common/collect/RegularImmutableTableTest.java
@@ -63,7 +63,7 @@ public class RegularImmutableTableTest extends AbstractImmutableTableTest {
for (ImmutableTable<Character, Integer, String> testInstance :
getTestInstances()) {
assertThat(testInstance.values())
- .has().exactly("foo", "bar", "baz")
+ .containsExactly("foo", "bar", "baz")
.inOrder();
}
}
diff --git a/guava-tests/test/com/google/common/collect/SetsTest.java b/guava-tests/test/com/google/common/collect/SetsTest.java
index 68a76c6..4b33d42 100644
--- a/guava-tests/test/com/google/common/collect/SetsTest.java
+++ b/guava-tests/test/com/google/common/collect/SetsTest.java
@@ -148,9 +148,9 @@ public class SetsTest extends TestCase {
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Set<String> set1 = Sets.newHashSet(elements);
- set1.add(samples().e3);
+ set1.add(samples().e3());
Set<String> set2 = Sets.newHashSet(elements);
- set2.add(samples().e4);
+ set2.add(samples().e4());
return Sets.intersection(set1, set2);
}
})
@@ -161,8 +161,8 @@ public class SetsTest extends TestCase {
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Set<String> set1 = Sets.newHashSet(elements);
- set1.add(samples().e3);
- Set<String> set2 = Sets.newHashSet(samples().e3);
+ set1.add(samples().e3());
+ Set<String> set2 = Sets.newHashSet(samples().e3());
return Sets.difference(set1, set2);
}
})
@@ -301,7 +301,7 @@ public class SetsTest extends TestCase {
public void testImmutableEnumSet() {
Set<SomeEnum> units = Sets.immutableEnumSet(SomeEnum.D, SomeEnum.B);
- assertThat(units).has().exactly(SomeEnum.B, SomeEnum.D).inOrder();
+ assertThat(units).containsExactly(SomeEnum.B, SomeEnum.D).inOrder();
try {
units.remove(SomeEnum.B);
fail("ImmutableEnumSet should throw an exception on remove()");
@@ -316,7 +316,7 @@ public class SetsTest extends TestCase {
public void testImmutableEnumSet_serialized() {
Set<SomeEnum> units = Sets.immutableEnumSet(SomeEnum.D, SomeEnum.B);
- assertThat(units).has().exactly(SomeEnum.B, SomeEnum.D).inOrder();
+ assertThat(units).containsExactly(SomeEnum.B, SomeEnum.D).inOrder();
Set<SomeEnum> copy = SerializableTester.reserializeAndAssert(units);
assertTrue(copy instanceof ImmutableEnumSet);
@@ -329,11 +329,10 @@ public class SetsTest extends TestCase {
ImmutableSet<SomeEnum> one
= Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.B));
- assertThat(one).has().item(SomeEnum.B);
+ assertThat(one).contains(SomeEnum.B);
- ImmutableSet<SomeEnum> two
- = Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.D, SomeEnum.B));
- assertThat(two).has().exactly(SomeEnum.B, SomeEnum.D).inOrder();
+ ImmutableSet<SomeEnum> two = Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.D, SomeEnum.B));
+ assertThat(two).containsExactly(SomeEnum.B, SomeEnum.D).inOrder();
}
@GwtIncompatible("java serialization not supported in GWT.")
@@ -488,7 +487,7 @@ public class SetsTest extends TestCase {
assertTrue(set.isEmpty());
set.add(new Derived("foo"));
set.add(new Derived("bar"));
- assertThat(set).has().exactly(new Derived("bar"), new Derived("foo")).inOrder();
+ assertThat(set).containsExactly(new Derived("bar"), new Derived("foo")).inOrder();
}
public void testNewTreeSetEmptyNonGeneric() {
@@ -496,8 +495,8 @@ public class SetsTest extends TestCase {
assertTrue(set.isEmpty());
set.add(new LegacyComparable("foo"));
set.add(new LegacyComparable("bar"));
- assertThat(set).has()
- .exactly(new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
+ assertThat(set).containsExactly(
+ new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
}
public void testNewTreeSetFromCollection() {
@@ -514,7 +513,7 @@ public class SetsTest extends TestCase {
Iterable<Derived> iterable =
Arrays.asList(new Derived("foo"), new Derived("bar"));
TreeSet<Derived> set = Sets.newTreeSet(iterable);
- assertThat(set).has().exactly(
+ assertThat(set).containsExactly(
new Derived("bar"), new Derived("foo")).inOrder();
}
@@ -522,7 +521,7 @@ public class SetsTest extends TestCase {
Iterable<LegacyComparable> iterable =
Arrays.asList(new LegacyComparable("foo"), new LegacyComparable("bar"));
TreeSet<LegacyComparable> set = Sets.newTreeSet(iterable);
- assertThat(set).has().exactly(
+ assertThat(set).containsExactly(
new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
}
@@ -624,7 +623,7 @@ public class SetsTest extends TestCase {
Sets.newSetFromMap(new LinkedHashMap<Integer, Boolean>());
set.addAll(SOME_COLLECTION);
Set<Integer> copy = SerializableTester.reserializeAndAssert(set);
- assertThat(copy).has().exactly(0, 1).inOrder();
+ assertThat(copy).containsExactly(0, 1).inOrder();
}
public void testNewSetFromMapIllegal() {
@@ -644,7 +643,7 @@ public class SetsTest extends TestCase {
*/
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_zeroary() {
- assertThat(Sets.cartesianProduct()).has().exactly(list());
+ assertThat(Sets.cartesianProduct()).containsExactly(list());
}
/**
@@ -653,7 +652,7 @@ public class SetsTest extends TestCase {
*/
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_unary() {
- assertThat(Sets.cartesianProduct(set(1, 2))).has().exactly(list(1), list(2));
+ assertThat(Sets.cartesianProduct(set(1, 2))).containsExactly(list(1), list(2));
}
@SuppressWarnings("unchecked") // varargs!
@@ -682,24 +681,24 @@ public class SetsTest extends TestCase {
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_binary1x1() {
- assertThat(Sets.cartesianProduct(set(1), set(2))).has().item(list(1, 2));
+ assertThat(Sets.cartesianProduct(set(1), set(2))).contains(list(1, 2));
}
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_binary1x2() {
assertThat(Sets.cartesianProduct(set(1), set(2, 3)))
- .has().exactly(list(1, 2), list(1, 3)).inOrder();
+ .containsExactly(list(1, 2), list(1, 3)).inOrder();
}
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_binary2x2() {
assertThat(Sets.cartesianProduct(set(1, 2), set(3, 4)))
- .has().exactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
+ .containsExactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder();
}
@SuppressWarnings("unchecked") // varargs!
public void testCartesianProduct_2x2x2() {
- assertThat(Sets.cartesianProduct(set(0, 1), set(0, 1), set(0, 1))).has().exactly(
+ assertThat(Sets.cartesianProduct(set(0, 1), set(0, 1), set(0, 1))).containsExactly(
list(0, 0, 0), list(0, 0, 1), list(0, 1, 0), list(0, 1, 1),
list(1, 0, 0), list(1, 0, 1), list(1, 1, 0), list(1, 1, 1)).inOrder();
}
@@ -725,7 +724,7 @@ public class SetsTest extends TestCase {
List<Object> exp4 = list((Object) 2, "4");
assertThat(Sets.<Object>cartesianProduct(x, y))
- .has().exactly(exp1, exp2, exp3, exp4).inOrder();
+ .containsExactly(exp1, exp2, exp3, exp4).inOrder();
}
@SuppressWarnings("unchecked") // varargs!
diff --git a/guava-tests/test/com/google/common/collect/SingletonImmutableTableTest.java b/guava-tests/test/com/google/common/collect/SingletonImmutableTableTest.java
index f16498b..27eeb1a 100644
--- a/guava-tests/test/com/google/common/collect/SingletonImmutableTableTest.java
+++ b/guava-tests/test/com/google/common/collect/SingletonImmutableTableTest.java
@@ -126,7 +126,7 @@ public class SingletonImmutableTableTest extends AbstractImmutableTableTest {
}
public void testValues() {
- assertThat(testTable.values()).has().item("blah");
+ assertThat(testTable.values()).contains("blah");
}
@Override Iterable<ImmutableTable<Character, Integer, String>> getTestInstances() {
diff --git a/guava-tests/test/com/google/common/collect/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/collect/SuppressUnderAndroid.java
new file mode 100644
index 0000000..907cfd2
--- /dev/null
+++ b/guava-tests/test/com/google/common/collect/SuppressUnderAndroid.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.collect;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>For more discussion, see {@linkplain com.google.common.base.SuppressUnderAndroid the
+ * documentation on another copy of this annotation}.
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/collect/SynchronizedMultimapTest.java b/guava-tests/test/com/google/common/collect/SynchronizedMultimapTest.java
index e7a6aac..559eaf0 100644
--- a/guava-tests/test/com/google/common/collect/SynchronizedMultimapTest.java
+++ b/guava-tests/test/com/google/common/collect/SynchronizedMultimapTest.java
@@ -204,11 +204,11 @@ public class SynchronizedMultimapTest extends TestCase {
ArrayListMultimap.<String, Integer>create());
multimap.putAll("foo", Arrays.asList(3, -1, 2, 4, 1));
multimap.putAll("bar", Arrays.asList(1, 2, 3, 1));
- assertThat(multimap.removeAll("foo")).has().exactly(3, -1, 2, 4, 1).inOrder();
+ assertThat(multimap.removeAll("foo")).containsExactly(3, -1, 2, 4, 1).inOrder();
assertFalse(multimap.containsKey("foo"));
assertThat(multimap.replaceValues("bar", Arrays.asList(6, 5)))
- .has().exactly(1, 2, 3, 1).inOrder();
- assertThat(multimap.get("bar")).has().exactly(6, 5).inOrder();
+ .containsExactly(1, 2, 3, 1).inOrder();
+ assertThat(multimap.get("bar")).containsExactly(6, 5).inOrder();
}
public void testSynchronizedSortedSetMultimap() {
@@ -217,11 +217,11 @@ public class SynchronizedMultimapTest extends TestCase {
TreeMultimap.<String, Integer>create());
multimap.putAll("foo", Arrays.asList(3, -1, 2, 4, 1));
multimap.putAll("bar", Arrays.asList(1, 2, 3, 1));
- assertThat(multimap.removeAll("foo")).has().exactly(-1, 1, 2, 3, 4).inOrder();
+ assertThat(multimap.removeAll("foo")).containsExactly(-1, 1, 2, 3, 4).inOrder();
assertFalse(multimap.containsKey("foo"));
assertThat(multimap.replaceValues("bar", Arrays.asList(6, 5)))
- .has().exactly(1, 2, 3).inOrder();
- assertThat(multimap.get("bar")).has().exactly(5, 6).inOrder();
+ .containsExactly(1, 2, 3).inOrder();
+ assertThat(multimap.get("bar")).containsExactly(5, 6).inOrder();
}
public void testSynchronizedArrayListMultimapRandomAccess() {
@@ -238,9 +238,8 @@ public class SynchronizedMultimapTest extends TestCase {
ListMultimap<String, Integer> delegate = LinkedListMultimap.create();
delegate.put("foo", 1);
delegate.put("foo", 3);
- ListMultimap<String, Integer> multimap
- = Multimaps.synchronizedListMultimap(delegate);
- assertFalse(multimap.get("foo") instanceof RandomAccess);
- assertFalse(multimap.get("bar") instanceof RandomAccess);
+ ListMultimap<String, Integer> multimap = Multimaps.synchronizedListMultimap(delegate);
+ assertThat(multimap.get("foo")).isNotInstanceOf(RandomAccess.class);
+ assertThat(multimap.get("bar")).isNotInstanceOf(RandomAccess.class);
}
}
diff --git a/guava-tests/test/com/google/common/collect/TreeBasedTableTest.java b/guava-tests/test/com/google/common/collect/TreeBasedTableTest.java
index 292a3b7..8a80d5a 100644
--- a/guava-tests/test/com/google/common/collect/TreeBasedTableTest.java
+++ b/guava-tests/test/com/google/common/collect/TreeBasedTableTest.java
@@ -154,8 +154,8 @@ public class TreeBasedTableTest extends AbstractTableTest {
table.put("foo", 12, 'b');
table.put("bar", 5, 'c');
table.put("cat", 8, 'd');
- assertThat(table.rowKeySet()).has().exactly("foo", "cat", "bar").inOrder();
- assertThat(table.row("foo").keySet()).has().exactly(12, 3).inOrder();
+ assertThat(table.rowKeySet()).containsExactly("foo", "cat", "bar").inOrder();
+ assertThat(table.row("foo").keySet()).containsExactly(12, 3).inOrder();
}
public void testCreateCopy() {
@@ -166,8 +166,8 @@ public class TreeBasedTableTest extends AbstractTableTest {
original.put("bar", 5, 'c');
original.put("cat", 8, 'd');
table = TreeBasedTable.create(original);
- assertThat(table.rowKeySet()).has().exactly("foo", "cat", "bar").inOrder();
- assertThat(table.row("foo").keySet()).has().exactly(12, 3).inOrder();
+ assertThat(table.rowKeySet()).containsExactly("foo", "cat", "bar").inOrder();
+ assertThat(table.row("foo").keySet()).containsExactly(12, 3).inOrder();
assertEquals(original, table);
}
diff --git a/guava-tests/test/com/google/common/collect/TreeMultimapExplicitTest.java b/guava-tests/test/com/google/common/collect/TreeMultimapExplicitTest.java
index c6ec282..c679b6d 100644
--- a/guava-tests/test/com/google/common/collect/TreeMultimapExplicitTest.java
+++ b/guava-tests/test/com/google/common/collect/TreeMultimapExplicitTest.java
@@ -99,13 +99,13 @@ public class TreeMultimapExplicitTest extends TestCase {
tree.put("google", 6);
tree.put("tree", 0);
tree.put("tree", 3);
- assertThat(tree.keySet()).has().exactly("tree", "google").inOrder();
- assertThat(tree.get("google")).has().exactly(6, 2).inOrder();
+ assertThat(tree.keySet()).containsExactly("tree", "google").inOrder();
+ assertThat(tree.get("google")).containsExactly(6, 2).inOrder();
TreeMultimap<String, Integer> copy = TreeMultimap.create(tree);
assertEquals(tree, copy);
- assertThat(copy.keySet()).has().exactly("google", "tree").inOrder();
- assertThat(copy.get("google")).has().exactly(2, 6).inOrder();
+ assertThat(copy.keySet()).containsExactly("google", "tree").inOrder();
+ assertThat(copy.get("google")).containsExactly(2, 6).inOrder();
assertEquals(Ordering.natural(), copy.keyComparator());
assertEquals(Ordering.natural(), copy.valueComparator());
assertEquals(Ordering.natural(), copy.get("google").comparator());
@@ -130,14 +130,14 @@ public class TreeMultimapExplicitTest extends TestCase {
public void testOrderedGet() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.get(null)).has().exactly(7, 3, 1).inOrder();
- assertThat(multimap.get("google")).has().exactly(6, 2).inOrder();
- assertThat(multimap.get("tree")).has().exactly(null, 0).inOrder();
+ assertThat(multimap.get(null)).containsExactly(7, 3, 1).inOrder();
+ assertThat(multimap.get("google")).containsExactly(6, 2).inOrder();
+ assertThat(multimap.get("tree")).containsExactly(null, 0).inOrder();
}
public void testOrderedKeySet() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.keySet()).has().exactly(null, "tree", "google").inOrder();
+ assertThat(multimap.keySet()).containsExactly(null, "tree", "google").inOrder();
}
public void testOrderedAsMapEntries() {
@@ -146,18 +146,18 @@ public class TreeMultimapExplicitTest extends TestCase {
multimap.asMap().entrySet().iterator();
Map.Entry<String, Collection<Integer>> entry = iterator.next();
assertEquals(null, entry.getKey());
- assertThat(entry.getValue()).has().exactly(7, 3, 1);
+ assertThat(entry.getValue()).containsExactly(7, 3, 1);
entry = iterator.next();
assertEquals("tree", entry.getKey());
- assertThat(entry.getValue()).has().exactly(null, 0);
+ assertThat(entry.getValue()).containsExactly(null, 0);
entry = iterator.next();
assertEquals("google", entry.getKey());
- assertThat(entry.getValue()).has().exactly(6, 2);
+ assertThat(entry.getValue()).containsExactly(6, 2);
}
public void testOrderedEntries() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.entries()).has().exactly(
+ assertThat(multimap.entries()).containsExactly(
Maps.immutableEntry((String) null, 7),
Maps.immutableEntry((String) null, 3),
Maps.immutableEntry((String) null, 1),
@@ -169,7 +169,7 @@ public class TreeMultimapExplicitTest extends TestCase {
public void testOrderedValues() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.values()).has().exactly(7, 3, 1, null, 0, 6, 2).inOrder();
+ assertThat(multimap.values()).containsExactly(7, 3, 1, null, 0, 6, 2).inOrder();
}
public void testComparator() {
@@ -211,8 +211,8 @@ public class TreeMultimapExplicitTest extends TestCase {
TreeMultimap<String, Integer> multimap = createPopulate();
TreeMultimap<String, Integer> copy
= SerializableTester.reserializeAndAssert(multimap);
- assertThat(copy.values()).has().exactly(7, 3, 1, null, 0, 6, 2).inOrder();
- assertThat(copy.keySet()).has().exactly(null, "tree", "google").inOrder();
+ assertThat(copy.values()).containsExactly(7, 3, 1, null, 0, 6, 2).inOrder();
+ assertThat(copy.keySet()).containsExactly(null, "tree", "google").inOrder();
assertEquals(multimap.keyComparator(), copy.keyComparator());
assertEquals(multimap.valueComparator(), copy.valueComparator());
}
diff --git a/guava-tests/test/com/google/common/collect/TreeMultimapNaturalTest.java b/guava-tests/test/com/google/common/collect/TreeMultimapNaturalTest.java
index b0edc71..b96c207 100644
--- a/guava-tests/test/com/google/common/collect/TreeMultimapNaturalTest.java
+++ b/guava-tests/test/com/google/common/collect/TreeMultimapNaturalTest.java
@@ -65,7 +65,7 @@ public class TreeMultimapNaturalTest extends TestCase {
@GwtIncompatible("suite")
public static Test suite() {
TestSuite suite = new TestSuite();
- // TODO(user): should we force TreeMultimap to be more thorough about checking nulls?
+ // TODO(lowasser): should we force TreeMultimap to be more thorough about checking nulls?
suite.addTest(SortedSetMultimapTestSuiteBuilder.using(new TestStringSetMultimapGenerator() {
@Override
protected SetMultimap<String, String> create(Entry<String, String>[] entries) {
@@ -283,14 +283,14 @@ public class TreeMultimapNaturalTest extends TestCase {
public void testOrderedGet() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.get("foo")).has().exactly(1, 3, 7).inOrder();
- assertThat(multimap.get("google")).has().exactly(2, 6).inOrder();
- assertThat(multimap.get("tree")).has().exactly(0, 4).inOrder();
+ assertThat(multimap.get("foo")).containsExactly(1, 3, 7).inOrder();
+ assertThat(multimap.get("google")).containsExactly(2, 6).inOrder();
+ assertThat(multimap.get("tree")).containsExactly(0, 4).inOrder();
}
public void testOrderedKeySet() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.keySet()).has().exactly("foo", "google", "tree").inOrder();
+ assertThat(multimap.keySet()).containsExactly("foo", "google", "tree").inOrder();
}
public void testOrderedAsMapEntries() {
@@ -299,18 +299,18 @@ public class TreeMultimapNaturalTest extends TestCase {
multimap.asMap().entrySet().iterator();
Map.Entry<String, Collection<Integer>> entry = iterator.next();
assertEquals("foo", entry.getKey());
- assertThat(entry.getValue()).has().exactly(1, 3, 7);
+ assertThat(entry.getValue()).containsExactly(1, 3, 7);
entry = iterator.next();
assertEquals("google", entry.getKey());
- assertThat(entry.getValue()).has().exactly(2, 6);
+ assertThat(entry.getValue()).containsExactly(2, 6);
entry = iterator.next();
assertEquals("tree", entry.getKey());
- assertThat(entry.getValue()).has().exactly(0, 4);
+ assertThat(entry.getValue()).containsExactly(0, 4);
}
public void testOrderedEntries() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.entries()).has().exactly(
+ assertThat(multimap.entries()).containsExactly(
Maps.immutableEntry("foo", 1),
Maps.immutableEntry("foo", 3),
Maps.immutableEntry("foo", 7),
@@ -322,7 +322,7 @@ public class TreeMultimapNaturalTest extends TestCase {
public void testOrderedValues() {
TreeMultimap<String, Integer> multimap = createPopulate();
- assertThat(multimap.values()).has().exactly(
+ assertThat(multimap.values()).containsExactly(
1, 3, 7, 2, 6, 0, 4).inOrder();
}
@@ -405,8 +405,8 @@ public class TreeMultimapNaturalTest extends TestCase {
TreeMultimap<String, Integer> multimap = createPopulate();
TreeMultimap<String, Integer> copy
= SerializableTester.reserializeAndAssert(multimap);
- assertThat(copy.values()).has().exactly(1, 3, 7, 2, 6, 0, 4).inOrder();
- assertThat(copy.keySet()).has().exactly("foo", "google", "tree").inOrder();
+ assertThat(copy.values()).containsExactly(1, 3, 7, 2, 6, 0, 4).inOrder();
+ assertThat(copy.keySet()).containsExactly("foo", "google", "tree").inOrder();
assertEquals(multimap.keyComparator(), copy.keyComparator());
assertEquals(multimap.valueComparator(), copy.valueComparator());
}
@@ -421,9 +421,9 @@ public class TreeMultimapNaturalTest extends TestCase {
multimap.put(new DerivedComparable("bar"), new DerivedComparable("b"));
multimap.put(new DerivedComparable("bar"), new DerivedComparable("a"));
multimap.put(new DerivedComparable("bar"), new DerivedComparable("r"));
- assertThat(multimap.keySet()).has().exactly(
+ assertThat(multimap.keySet()).containsExactly(
new DerivedComparable("bar"), new DerivedComparable("foo")).inOrder();
- assertThat(multimap.values()).has().exactly(
+ assertThat(multimap.values()).containsExactly(
new DerivedComparable("a"), new DerivedComparable("b"), new DerivedComparable("r"),
new DerivedComparable("f"), new DerivedComparable("o")).inOrder();
assertEquals(Ordering.natural(), multimap.keyComparator());
@@ -442,9 +442,9 @@ public class TreeMultimapNaturalTest extends TestCase {
multimap.put(new LegacyComparable("bar"), new LegacyComparable("b"));
multimap.put(new LegacyComparable("bar"), new LegacyComparable("a"));
multimap.put(new LegacyComparable("bar"), new LegacyComparable("r"));
- assertThat(multimap.keySet()).has().exactly(
+ assertThat(multimap.keySet()).containsExactly(
new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
- assertThat(multimap.values()).has().exactly(
+ assertThat(multimap.values()).containsExactly(
new LegacyComparable("a"),
new LegacyComparable("b"),
new LegacyComparable("r"),
diff --git a/guava-tests/test/com/google/common/collect/TreeMultisetTest.java b/guava-tests/test/com/google/common/collect/TreeMultisetTest.java
index 86a2197..52db060 100644
--- a/guava-tests/test/com/google/common/collect/TreeMultisetTest.java
+++ b/guava-tests/test/com/google/common/collect/TreeMultisetTest.java
@@ -163,9 +163,9 @@ public class TreeMultisetTest extends TestCase {
assertEquals("c", elementSet.last());
assertEquals(Ordering.natural(), elementSet.comparator());
- assertThat(elementSet.headSet("b")).has().exactly("a").inOrder();
- assertThat(elementSet.tailSet("b")).has().exactly("b", "c").inOrder();
- assertThat(elementSet.subSet("a", "c")).has().exactly("a", "b").inOrder();
+ assertThat(elementSet.headSet("b")).containsExactly("a");
+ assertThat(elementSet.tailSet("b")).containsExactly("b", "c").inOrder();
+ assertThat(elementSet.subSet("a", "c")).containsExactly("a", "b").inOrder();
}
public void testElementSetSubsetRemove() {
@@ -178,18 +178,18 @@ public class TreeMultisetTest extends TestCase {
ms.add("f", 2);
SortedSet<String> elementSet = ms.elementSet();
- assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
SortedSet<String> subset = elementSet.subSet("b", "f");
- assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+ assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
assertTrue(subset.remove("c"));
- assertThat(elementSet).has().exactly("a", "b", "d", "e", "f").inOrder();
- assertThat(subset).has().exactly("b", "d", "e").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
+ assertThat(subset).containsExactly("b", "d", "e").inOrder();
assertEquals(10, ms.size());
assertFalse(subset.remove("a"));
- assertThat(elementSet).has().exactly("a", "b", "d", "e", "f").inOrder();
- assertThat(subset).has().exactly("b", "d", "e").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
+ assertThat(subset).containsExactly("b", "d", "e").inOrder();
assertEquals(10, ms.size());
}
@@ -203,13 +203,13 @@ public class TreeMultisetTest extends TestCase {
ms.add("f", 2);
SortedSet<String> elementSet = ms.elementSet();
- assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
SortedSet<String> subset = elementSet.subSet("b", "f");
- assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+ assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
assertTrue(subset.removeAll(Arrays.asList("a", "c")));
- assertThat(elementSet).has().exactly("a", "b", "d", "e", "f").inOrder();
- assertThat(subset).has().exactly("b", "d", "e").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
+ assertThat(subset).containsExactly("b", "d", "e").inOrder();
assertEquals(10, ms.size());
}
@@ -223,13 +223,13 @@ public class TreeMultisetTest extends TestCase {
ms.add("f", 2);
SortedSet<String> elementSet = ms.elementSet();
- assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
SortedSet<String> subset = elementSet.subSet("b", "f");
- assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+ assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
assertTrue(subset.retainAll(Arrays.asList("a", "c")));
- assertThat(elementSet).has().exactly("a", "c", "f").inOrder();
- assertThat(subset).has().exactly("c").inOrder();
+ assertThat(elementSet).containsExactly("a", "c", "f").inOrder();
+ assertThat(subset).containsExactly("c");
assertEquals(5, ms.size());
}
@@ -243,12 +243,12 @@ public class TreeMultisetTest extends TestCase {
ms.add("f", 2);
SortedSet<String> elementSet = ms.elementSet();
- assertThat(elementSet).has().exactly("a", "b", "c", "d", "e", "f").inOrder();
+ assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
SortedSet<String> subset = elementSet.subSet("b", "f");
- assertThat(subset).has().exactly("b", "c", "d", "e").inOrder();
+ assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
subset.clear();
- assertThat(elementSet).has().exactly("a", "f").inOrder();
+ assertThat(elementSet).containsExactly("a", "f").inOrder();
assertThat(subset).isEmpty();
assertEquals(3, ms.size());
}
@@ -268,7 +268,7 @@ public class TreeMultisetTest extends TestCase {
ms.add("b");
ms.add("d");
- assertThat(ms).has().exactly("d", "c", "b", "b", "a").inOrder();
+ assertThat(ms).containsExactly("d", "c", "b", "b", "a").inOrder();
SortedSet<String> elementSet = ms.elementSet();
assertEquals("d", elementSet.first());
@@ -286,7 +286,7 @@ public class TreeMultisetTest extends TestCase {
ms.add("b");
ms.add(null, 2);
- assertThat(ms).has().exactly(null, null, null, "a", "b", "b").inOrder();
+ assertThat(ms).containsExactly(null, null, null, "a", "b", "b").inOrder();
assertEquals(3, ms.count(null));
SortedSet<String> elementSet = ms.elementSet();
@@ -353,6 +353,7 @@ public class TreeMultisetTest extends TestCase {
}
@GwtIncompatible("reflection")
+ @SuppressUnderAndroid // Reflection bug, or actual binary compatibility problem?
public void testElementSetBridgeMethods() {
for (Method m : TreeMultiset.class.getMethods()) {
if (m.getName().equals("elementSet") && m.getReturnType().equals(SortedSet.class)) {
diff --git a/guava-tests/test/com/google/common/collect/TreeRangeMapTest.java b/guava-tests/test/com/google/common/collect/TreeRangeMapTest.java
index 02dbbc4..d1b77ab 100644
--- a/guava-tests/test/com/google/common/collect/TreeRangeMapTest.java
+++ b/guava-tests/test/com/google/common/collect/TreeRangeMapTest.java
@@ -152,6 +152,115 @@ public class TreeRangeMapTest extends TestCase {
MapFeature.ALLOWS_ANY_NULL_QUERIES,
CollectionFeature.KNOWN_ORDER)
.createTestSuite());
+
+ suite.addTest(MapTestSuiteBuilder.using(new TestMapGenerator<Range<Integer>, String>() {
+ @Override
+ public SampleElements<Entry<Range<Integer>, String>> samples() {
+ return new SampleElements<Entry<Range<Integer>, String>>(
+ mapEntry(Range.singleton(0), "banana"),
+ mapEntry(Range.closedOpen(3, 5), "frisbee"),
+ mapEntry(Range.atMost(-1), "fruitcake"),
+ mapEntry(Range.open(10, 15), "elephant"),
+ mapEntry(Range.closed(20, 22), "umbrella"));
+ }
+
+ @Override
+ public Map<Range<Integer>, String> create(Object... elements) {
+ RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
+ for (Object o : elements) {
+ @SuppressWarnings("unchecked")
+ Entry<Range<Integer>, String> entry = (Entry<Range<Integer>, String>) o;
+ rangeMap.put(entry.getKey(), entry.getValue());
+ }
+ return rangeMap.asDescendingMapOfRanges();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Entry<Range<Integer>, String>[] createArray(int length) {
+ return new Entry[length];
+ }
+
+ @Override
+ public Iterable<Entry<Range<Integer>, String>> order(
+ List<Entry<Range<Integer>, String>> insertionOrder) {
+ return Range.RANGE_LEX_ORDERING.reverse().<Range<Integer>>onKeys()
+ .sortedCopy(insertionOrder);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Range<Integer>[] createKeyArray(int length) {
+ return new Range[length];
+ }
+
+ @Override
+ public String[] createValueArray(int length) {
+ return new String[length];
+ }
+ })
+ .named("TreeRangeMap.asDescendingMapOfRanges")
+ .withFeatures(
+ CollectionSize.ANY,
+ MapFeature.SUPPORTS_REMOVE,
+ MapFeature.ALLOWS_ANY_NULL_QUERIES,
+ CollectionFeature.KNOWN_ORDER,
+ CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
+ .createTestSuite());
+
+ suite.addTest(MapTestSuiteBuilder.using(new TestMapGenerator<Range<Integer>, String>() {
+ @Override
+ public SampleElements<Entry<Range<Integer>, String>> samples() {
+ return new SampleElements<Entry<Range<Integer>, String>>(
+ mapEntry(Range.singleton(0), "banana"),
+ mapEntry(Range.closedOpen(3, 5), "frisbee"),
+ mapEntry(Range.atMost(-1), "fruitcake"),
+ mapEntry(Range.open(10, 15), "elephant"),
+ mapEntry(Range.closed(20, 22), "umbrella"));
+ }
+
+ @Override
+ public Map<Range<Integer>, String> create(Object... elements) {
+ RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
+ for (Object o : elements) {
+ @SuppressWarnings("unchecked")
+ Entry<Range<Integer>, String> entry = (Entry<Range<Integer>, String>) o;
+ rangeMap.put(entry.getKey(), entry.getValue());
+ }
+ return rangeMap.subRangeMap(Range.atMost(22)).asDescendingMapOfRanges();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Entry<Range<Integer>, String>[] createArray(int length) {
+ return new Entry[length];
+ }
+
+ @Override
+ public Iterable<Entry<Range<Integer>, String>> order(
+ List<Entry<Range<Integer>, String>> insertionOrder) {
+ return Range.RANGE_LEX_ORDERING.reverse().<Range<Integer>>onKeys()
+ .sortedCopy(insertionOrder);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Range<Integer>[] createKeyArray(int length) {
+ return new Range[length];
+ }
+
+ @Override
+ public String[] createValueArray(int length) {
+ return new String[length];
+ }
+ })
+ .named("TreeRangeMap.subRangeMap.asDescendingMapOfRanges")
+ .withFeatures(
+ CollectionSize.ANY,
+ MapFeature.SUPPORTS_REMOVE,
+ MapFeature.ALLOWS_ANY_NULL_QUERIES,
+ CollectionFeature.KNOWN_ORDER)
+ .createTestSuite());
return suite;
}
@@ -345,6 +454,9 @@ public class TreeRangeMapTest extends TestCase {
RangeMap<Integer, Integer> subRangeMap = rangeMap.subRangeMap(subRange);
assertEquals(expected, subRangeMap);
assertEquals(expected.asMapOfRanges(), subRangeMap.asMapOfRanges());
+ assertEquals(expected.asDescendingMapOfRanges(), subRangeMap.asDescendingMapOfRanges());
+ assertEquals(ImmutableList.copyOf(subRangeMap.asMapOfRanges().entrySet()).reverse(),
+ ImmutableList.copyOf(subRangeMap.asDescendingMapOfRanges().entrySet()));
if (!expected.asMapOfRanges().isEmpty()) {
assertEquals(expected.span(), subRangeMap.span());
diff --git a/guava-tests/test/com/google/common/collect/TreeRangeSetTest.java b/guava-tests/test/com/google/common/collect/TreeRangeSetTest.java
index 55a618e..2d45e87 100644
--- a/guava-tests/test/com/google/common/collect/TreeRangeSetTest.java
+++ b/guava-tests/test/com/google/common/collect/TreeRangeSetTest.java
@@ -115,13 +115,17 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
assertEquals(expected.higherEntry(key), navigableMap.higherEntry(key));
for (boolean inclusive : new boolean[] {false, true}) {
assertThat(navigableMap.headMap(key, inclusive).entrySet())
- .has().exactlyAs(expected.headMap(key, inclusive).entrySet()).inOrder();
+ .containsExactlyElementsIn(expected.headMap(key, inclusive).entrySet())
+ .inOrder();
assertThat(navigableMap.tailMap(key, inclusive).entrySet())
- .has().exactlyAs(expected.tailMap(key, inclusive).entrySet()).inOrder();
+ .containsExactlyElementsIn(expected.tailMap(key, inclusive).entrySet())
+ .inOrder();
assertThat(navigableMap.headMap(key, inclusive).descendingMap().entrySet())
- .has().exactlyAs(expected.headMap(key, inclusive).descendingMap().entrySet()).inOrder();
+ .containsExactlyElementsIn(expected.headMap(key, inclusive).descendingMap().entrySet())
+ .inOrder();
assertThat(navigableMap.tailMap(key, inclusive).descendingMap().entrySet())
- .has().exactlyAs(expected.tailMap(key, inclusive).descendingMap().entrySet()).inOrder();
+ .containsExactlyElementsIn(expected.tailMap(key, inclusive).descendingMap().entrySet())
+ .inOrder();
}
}
}
@@ -152,7 +156,8 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
assertEquals(complement, rangeSet.complement());
assertThat(rangeSet.complement().asRanges())
- .has().exactlyAs(complement.asRanges()).inOrder();
+ .containsExactlyElementsIn(complement.asRanges())
+ .inOrder();
}
}
@@ -289,9 +294,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(1, 4));
rangeSet.add(Range.open(2, 6));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.closedOpen(1, 6));
+ assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 6));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(1), Range.atLeast(6)).inOrder();
+ .containsExactly(Range.lessThan(1), Range.atLeast(6))
+ .inOrder();
}
public void testMergesConnectedDisjoint() {
@@ -299,9 +305,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(1, 4));
rangeSet.add(Range.open(4, 6));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.closedOpen(1, 6));
+ assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 6));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(1), Range.atLeast(6)).inOrder();
+ .containsExactly(Range.lessThan(1), Range.atLeast(6))
+ .inOrder();
}
public void testIgnoresSmallerSharingNoBound() {
@@ -309,9 +316,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(1, 6));
rangeSet.add(Range.open(2, 4));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+ assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+ .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+ .inOrder();
}
public void testIgnoresSmallerSharingLowerBound() {
@@ -319,9 +327,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(1, 6));
rangeSet.add(Range.closed(1, 4));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+ assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+ .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+ .inOrder();
}
public void testIgnoresSmallerSharingUpperBound() {
@@ -329,9 +338,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(1, 6));
rangeSet.add(Range.closed(3, 6));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+ assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+ .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+ .inOrder();
}
public void testIgnoresEqual() {
@@ -339,9 +349,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(1, 6));
rangeSet.add(Range.closed(1, 6));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+ assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+ .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+ .inOrder();
}
public void testExtendSameLowerBound() {
@@ -349,9 +360,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(1, 4));
rangeSet.add(Range.closed(1, 6));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+ assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+ .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+ .inOrder();
}
public void testExtendSameUpperBound() {
@@ -359,9 +371,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(3, 6));
rangeSet.add(Range.closed(1, 6));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+ assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+ .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+ .inOrder();
}
public void testExtendBothDirections() {
@@ -369,9 +382,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(3, 4));
rangeSet.add(Range.closed(1, 6));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+ assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+ .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+ .inOrder();
}
public void testAddEmpty() {
@@ -379,7 +393,7 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closedOpen(3, 3));
testInvariants(rangeSet);
assertThat(rangeSet.asRanges()).isEmpty();
- assertThat(rangeSet.complement().asRanges()).has().exactly(Range.<Integer>all()).inOrder();
+ assertThat(rangeSet.complement().asRanges()).containsExactly(Range.<Integer>all());
}
public void testFillHoleExactly() {
@@ -388,9 +402,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closedOpen(4, 6));
rangeSet.add(Range.closedOpen(3, 4));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.closedOpen(1, 6));
+ assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 6));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(1), Range.atLeast(6)).inOrder();
+ .containsExactly(Range.lessThan(1), Range.atLeast(6))
+ .inOrder();
}
public void testFillHoleWithOverlap() {
@@ -399,9 +414,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closedOpen(4, 6));
rangeSet.add(Range.closedOpen(2, 5));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.closedOpen(1, 6));
+ assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 6));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(1), Range.atLeast(6)).inOrder();
+ .containsExactly(Range.lessThan(1), Range.atLeast(6))
+ .inOrder();
}
public void testAddManyPairs() {
@@ -438,16 +454,16 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
if (a.isEmpty() && b.isEmpty()) {
assertThat(rangeSet.asRanges()).isEmpty();
} else if (a.isEmpty()) {
- assertThat(rangeSet.asRanges()).has().item(b);
+ assertThat(rangeSet.asRanges()).contains(b);
} else if (b.isEmpty()) {
- assertThat(rangeSet.asRanges()).has().item(a);
+ assertThat(rangeSet.asRanges()).contains(a);
} else if (a.isConnected(b)) {
- assertThat(rangeSet.asRanges()).has().exactly(a.span(b)).inOrder();
+ assertThat(rangeSet.asRanges()).containsExactly(a.span(b));
} else {
if (a.lowerEndpoint() < b.lowerEndpoint()) {
- assertThat(rangeSet.asRanges()).has().exactly(a, b).inOrder();
+ assertThat(rangeSet.asRanges()).containsExactly(a, b).inOrder();
} else {
- assertThat(rangeSet.asRanges()).has().exactly(b, a).inOrder();
+ assertThat(rangeSet.asRanges()).containsExactly(b, a).inOrder();
}
}
}
@@ -457,9 +473,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(1, 6));
rangeSet.remove(Range.closedOpen(3, 3));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.closed(1, 6));
+ assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(1), Range.greaterThan(6)).inOrder();
+ .containsExactly(Range.lessThan(1), Range.greaterThan(6))
+ .inOrder();
}
public void testRemovePartSharingLowerBound() {
@@ -467,9 +484,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(3, 5));
rangeSet.remove(Range.closedOpen(3, 5));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.singleton(5));
+ assertThat(rangeSet.asRanges()).contains(Range.singleton(5));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(5), Range.greaterThan(5)).inOrder();
+ .containsExactly(Range.lessThan(5), Range.greaterThan(5))
+ .inOrder();
}
public void testRemovePartSharingUpperBound() {
@@ -477,9 +495,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(3, 5));
rangeSet.remove(Range.openClosed(3, 5));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().item(Range.singleton(3));
+ assertThat(rangeSet.asRanges()).contains(Range.singleton(3));
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.lessThan(3), Range.greaterThan(3)).inOrder();
+ .containsExactly(Range.lessThan(3), Range.greaterThan(3))
+ .inOrder();
}
public void testRemoveMiddle() {
@@ -487,9 +506,10 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.atMost(6));
rangeSet.remove(Range.closedOpen(3, 4));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().exactly(Range.lessThan(3), Range.closed(4, 6)).inOrder();
+ assertThat(rangeSet.asRanges())
+ .containsExactly(Range.lessThan(3), Range.closed(4, 6)).inOrder();
assertThat(rangeSet.complement().asRanges())
- .has().exactly(Range.closedOpen(3, 4), Range.greaterThan(6)).inOrder();
+ .containsExactly(Range.closedOpen(3, 4), Range.greaterThan(6)).inOrder();
}
public void testRemoveNoOverlap() {
@@ -497,7 +517,7 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(3, 6));
rangeSet.remove(Range.closedOpen(1, 3));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().exactly(Range.closed(3, 6)).inOrder();
+ assertThat(rangeSet.asRanges()).containsExactly(Range.closed(3, 6));
}
public void testRemovePartFromBelowLowerBound() {
@@ -505,7 +525,7 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(3, 6));
rangeSet.remove(Range.closed(1, 3));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().exactly(Range.openClosed(3, 6)).inOrder();
+ assertThat(rangeSet.asRanges()).containsExactly(Range.openClosed(3, 6));
}
public void testRemovePartFromAboveUpperBound() {
@@ -513,7 +533,7 @@ public class TreeRangeSetTest extends AbstractRangeSetTest {
rangeSet.add(Range.closed(3, 6));
rangeSet.remove(Range.closed(6, 9));
testInvariants(rangeSet);
- assertThat(rangeSet.asRanges()).has().exactly(Range.closedOpen(3, 6)).inOrder();
+ assertThat(rangeSet.asRanges()).containsExactly(Range.closedOpen(3, 6));
}
public void testRemoveExact() {
diff --git a/guava-tests/test/com/google/common/escape/EscapersTest.java b/guava-tests/test/com/google/common/escape/EscapersTest.java
index c8df0a2..9f33368 100644
--- a/guava-tests/test/com/google/common/escape/EscapersTest.java
+++ b/guava-tests/test/com/google/common/escape/EscapersTest.java
@@ -115,7 +115,7 @@ public class EscapersTest extends TestCase {
}
// A trival non-optimized escaper for testing.
- private CharEscaper createSimpleCharEscaper(
+ static CharEscaper createSimpleCharEscaper(
final ImmutableMap<Character, char[]> replacementMap) {
return new CharEscaper() {
@Override protected char[] escape(char c) {
@@ -125,7 +125,7 @@ public class EscapersTest extends TestCase {
}
// A trival non-optimized escaper for testing.
- private UnicodeEscaper createSimpleUnicodeEscaper(
+ static UnicodeEscaper createSimpleUnicodeEscaper(
final ImmutableMap<Integer, char[]> replacementMap) {
return new UnicodeEscaper() {
@Override protected char[] escape(int cp) {
diff --git a/guava-tests/test/com/google/common/eventbus/DispatcherTest.java b/guava-tests/test/com/google/common/eventbus/DispatcherTest.java
new file mode 100644
index 0000000..a55f191
--- /dev/null
+++ b/guava-tests/test/com/google/common/eventbus/DispatcherTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.eventbus;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Queues;
+import com.google.common.util.concurrent.Uninterruptibles;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+
+/**
+ * Tests for {@link Dispatcher} implementations.
+ *
+ * @author Colin Decker
+ */
+
+public class DispatcherTest extends TestCase {
+
+ private final EventBus bus = new EventBus();
+
+ private final IntegerSubscriber i1 = new IntegerSubscriber("i1");
+ private final IntegerSubscriber i2 = new IntegerSubscriber("i2");
+ private final IntegerSubscriber i3 = new IntegerSubscriber("i3");
+ private final ImmutableList<Subscriber> integerSubscribers = ImmutableList.of(
+ subscriber(bus, i1, "handleInteger", Integer.class),
+ subscriber(bus, i2, "handleInteger", Integer.class),
+ subscriber(bus, i3, "handleInteger", Integer.class));
+
+ private final StringSubscriber s1 = new StringSubscriber("s1");
+ private final StringSubscriber s2 = new StringSubscriber("s2");
+ private final ImmutableList<Subscriber> stringSubscribers = ImmutableList.of(
+ subscriber(bus, s1, "handleString", String.class),
+ subscriber(bus, s2, "handleString", String.class));
+
+ private final ConcurrentLinkedQueue<Object> dispatchedSubscribers
+ = Queues.newConcurrentLinkedQueue();
+
+ private Dispatcher dispatcher;
+
+ public void testPerThreadQueuedDispatcher() {
+ dispatcher = Dispatcher.perThreadDispatchQueue();
+ dispatcher.dispatch(1, integerSubscribers.iterator());
+
+ assertThat(dispatchedSubscribers)
+ .containsExactly(
+ i1, i2, i3, // Integer subscribers are dispatched to first.
+ s1, s2, // Though each integer subscriber dispatches to all string subscribers,
+ s1, s2, // those string subscribers aren't actually dispatched to until all integer
+ s1, s2 // subscribers have finished.
+ ).inOrder();
+ }
+
+ public void testLegacyAsyncDispatcher() {
+ dispatcher = Dispatcher.legacyAsync();
+
+ final CyclicBarrier barrier = new CyclicBarrier(2);
+ final CountDownLatch latch = new CountDownLatch(2);
+
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ barrier.await();
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+
+ dispatcher.dispatch(2, integerSubscribers.iterator());
+ latch.countDown();
+ }
+ }).start();
+
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ barrier.await();
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+
+ dispatcher.dispatch("foo", stringSubscribers.iterator());
+ latch.countDown();
+ }
+ }).start();
+
+ Uninterruptibles.awaitUninterruptibly(latch);
+
+ // See Dispatcher.LegacyAsyncDispatcher for an explanation of why there aren't really any
+ // useful testable guarantees about the behavior of that dispatcher in a multithreaded
+ // environment. Here we simply test that all the expected dispatches happened in some order.
+ assertThat(dispatchedSubscribers)
+ .containsExactly(
+ i1, i2, i3,
+ s1, s1, s1, s1,
+ s2, s2, s2, s2);
+ }
+
+ public void testImmediateDispatcher() {
+ dispatcher = Dispatcher.immediate();
+ dispatcher.dispatch(1, integerSubscribers.iterator());
+
+ assertThat(dispatchedSubscribers)
+ .containsExactly(
+ i1, s1, s2, // Each integer subscriber immediately dispatches to 2 string subscribers.
+ i2, s1, s2,
+ i3, s1, s2
+ ).inOrder();
+ }
+
+ private static Subscriber subscriber(
+ EventBus bus, Object target,
+ String methodName, Class<?> eventType) {
+ try {
+ return Subscriber.create(bus, target, target.getClass().getMethod(methodName, eventType));
+ } catch (NoSuchMethodException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public final class IntegerSubscriber {
+ private final String name;
+
+ public IntegerSubscriber(String name) {
+ this.name = name;
+ }
+
+ @Subscribe
+ public void handleInteger(Integer integer) {
+ dispatchedSubscribers.add(this);
+ dispatcher.dispatch("hello", stringSubscribers.iterator());
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ public final class StringSubscriber {
+ private final String name;
+
+ public StringSubscriber(String name) {
+ this.name = name;
+ }
+
+ @Subscribe
+ public void handleString(String string) {
+ dispatchedSubscribers.add(this);
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+}
diff --git a/guava-tests/test/com/google/common/eventbus/EventBusTest.java b/guava-tests/test/com/google/common/eventbus/EventBusTest.java
index 35cb2f1..82371f2 100644
--- a/guava-tests/test/com/google/common/eventbus/EventBusTest.java
+++ b/guava-tests/test/com/google/common/eventbus/EventBusTest.java
@@ -21,9 +21,7 @@ import com.google.common.collect.Lists;
import junit.framework.TestCase;
-import java.util.Collection;
import java.util.List;
-import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@@ -88,12 +86,12 @@ public class EventBusTest extends TestCase {
bus.register(compCatcher);
// Two additional event types: Object and Comparable<?> (played by Integer)
- final Object OBJ_EVENT = new Object();
- final Object COMP_EVENT = new Integer(6);
+ Object objEvent = new Object();
+ Object compEvent = new Integer(6);
bus.post(EVENT);
- bus.post(OBJ_EVENT);
- bus.post(COMP_EVENT);
+ bus.post(objEvent);
+ bus.post(compEvent);
// Check the StringCatcher...
List<String> stringEvents = stringCatcher.getEvents();
@@ -108,9 +106,9 @@ public class EventBusTest extends TestCase {
assertEquals("String fixture must be first object delivered.",
EVENT, objectEvents.get(0));
assertEquals("Object fixture must be second object delivered.",
- OBJ_EVENT, objectEvents.get(1));
+ objEvent, objectEvents.get(1));
assertEquals("Comparable fixture must be thirdobject delivered.",
- COMP_EVENT, objectEvents.get(2));
+ compEvent, objectEvents.get(2));
// Check the Catcher<Comparable<?>>...
assertEquals("Two Comparable<?>s should be delivered.",
@@ -118,7 +116,7 @@ public class EventBusTest extends TestCase {
assertEquals("String fixture must be first comparable delivered.",
EVENT, compEvents.get(0));
assertEquals("Comparable fixture must be second comparable delivered.",
- COMP_EVENT, compEvents.get(1));
+ compEvent, compEvents.get(1));
}
public void testSubscriberThrowsException() throws Exception{
@@ -198,18 +196,6 @@ public class EventBusTest extends TestCase {
EVENT, events.get(0).getEvent());
}
- public void testFlattenHierarchy() {
- HierarchyFixture fixture = new HierarchyFixture();
- Set<Class<?>> hierarchy = bus.flattenHierarchy(fixture.getClass());
-
- assertEquals(5, hierarchy.size());
- assertContains(Object.class, hierarchy);
- assertContains(HierarchyFixtureInterface.class, hierarchy);
- assertContains(HierarchyFixtureSubinterface.class, hierarchy);
- assertContains(HierarchyFixtureParent.class, hierarchy);
- assertContains(HierarchyFixture.class, hierarchy);
- }
-
public void testMissingSubscribe() {
bus.register(new Object());
}
@@ -308,11 +294,6 @@ public class EventBusTest extends TestCase {
assertEquals(1, calls.get());
}
- private <T> void assertContains(T element, Collection<T> collection) {
- assertTrue("Collection must contain " + element,
- collection.contains(element));
- }
-
/**
* Records thrown exception information.
*/
@@ -370,24 +351,6 @@ public class EventBusTest extends TestCase {
}
}
- private interface HierarchyFixtureInterface {
- // Exists only for hierarchy mapping; no members.
- }
-
- private interface HierarchyFixtureSubinterface
- extends HierarchyFixtureInterface {
- // Exists only for hierarchy mapping; no members.
- }
-
- private static class HierarchyFixtureParent
- implements HierarchyFixtureSubinterface {
- // Exists only for hierarchy mapping; no members.
- }
-
- private static class HierarchyFixture extends HierarchyFixtureParent {
- // Exists only for hierarchy mapping; no members.
- }
-
private interface Callback<T> {
void call(T t);
}
diff --git a/guava-tests/test/com/google/common/eventbus/EventSubscriberTest.java b/guava-tests/test/com/google/common/eventbus/EventSubscriberTest.java
deleted file mode 100644
index b0a332a..0000000
--- a/guava-tests/test/com/google/common/eventbus/EventSubscriberTest.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2007 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.eventbus;
-
-import com.google.common.testing.EqualsTester;
-
-import junit.framework.TestCase;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Test case for {@link EventSubscriber}.
- *
- * @author Cliff Biffle
- */
-public class EventSubscriberTest extends TestCase {
-
- private static final Object FIXTURE_ARGUMENT = new Object();
-
- private boolean methodCalled;
- private Object methodArgument;
-
- @Override protected void setUp() throws Exception {
- super.setUp();
-
- methodCalled = false;
- methodArgument = null;
- }
-
- /**
- * Checks that a no-frills, no-issues method call is properly executed.
- *
- * @throws Exception if the aforementioned proper execution is not to be had.
- */
- public void testBasicMethodCall() throws Exception {
- Method method = getRecordingMethod();
-
- EventSubscriber subscriber = new EventSubscriber(this, method);
-
- subscriber.handleEvent(FIXTURE_ARGUMENT);
-
- assertTrue("Subscriber must call provided method.", methodCalled);
- assertTrue("Subscriber argument must be *exactly* the provided object.",
- methodArgument == FIXTURE_ARGUMENT);
- }
-
- public void testExceptionWrapping() {
- Method method = getExceptionThrowingMethod();
- EventSubscriber subscriber = new EventSubscriber(this, method);
-
- try {
- subscriber.handleEvent(new Object());
- fail("Subscribers whose methods throw must throw InvocationTargetException");
- } catch (InvocationTargetException e) {
- assertTrue("Expected exception must be wrapped.",
- e.getCause() instanceof IntentionalException);
- }
- }
-
- public void testErrorPassthrough() throws InvocationTargetException {
- Method method = getErrorThrowingMethod();
- EventSubscriber subscriber = new EventSubscriber(this, method);
-
- try {
- subscriber.handleEvent(new Object());
- fail("Subscribers whose methods throw Errors must rethrow them");
- } catch (JudgmentError e) {
- // Expected.
- }
- }
-
- public void testEquals() throws Exception {
- Method charAt = String.class.getMethod("charAt", int.class);
- Method concat = String.class.getMethod("concat", String.class);
- new EqualsTester()
- .addEqualityGroup(
- new EventSubscriber("foo", charAt), new EventSubscriber("foo", charAt))
- .addEqualityGroup(new EventSubscriber("bar", charAt))
- .addEqualityGroup(new EventSubscriber("foo", concat))
- .testEquals();
- }
-
- /**
- * Gets a reference to {@link #recordingMethod(Object)}.
- *
- * @return a Method wrapping {@link #recordingMethod(Object)}.
- * @throws IllegalStateException if executed in a context where reflection is
- * unavailable.
- * @throws AssertionError if something odd has happened to
- * {@link #recordingMethod(Object)}.
- */
- private Method getRecordingMethod() {
- Method method;
- try {
- method = getClass().getMethod("recordingMethod", Object.class);
- } catch (SecurityException e) {
- throw new IllegalStateException("This test needs access to reflection.");
- } catch (NoSuchMethodException e) {
- throw new AssertionError(
- "Someone changed EventSubscriberTest#recordingMethod's visibility, " +
- "signature, or removed it entirely. (Must be public.)");
- }
- return method;
- }
-
- /**
- * Gets a reference to {@link #exceptionThrowingMethod(Object)}.
- *
- * @return a Method wrapping {@link #exceptionThrowingMethod(Object)}.
- * @throws IllegalStateException if executed in a context where reflection is
- * unavailable.
- * @throws AssertionError if something odd has happened to
- * {@link #exceptionThrowingMethod(Object)}.
- */
- private Method getExceptionThrowingMethod() {
- Method method;
- try {
- method = getClass().getMethod("exceptionThrowingMethod", Object.class);
- } catch (SecurityException e) {
- throw new IllegalStateException("This test needs access to reflection.");
- } catch (NoSuchMethodException e) {
- throw new AssertionError(
- "Someone changed EventSubscriberTest#exceptionThrowingMethod's " +
- "visibility, signature, or removed it entirely. (Must be public.)");
- }
- return method;
- }
-
- /**
- * Gets a reference to {@link #errorThrowingMethod(Object)}.
- *
- * @return a Method wrapping {@link #errorThrowingMethod(Object)}.
- * @throws IllegalStateException if executed in a context where reflection is
- * unavailable.
- * @throws AssertionError if something odd has happened to
- * {@link #errorThrowingMethod(Object)}.
- */
- private Method getErrorThrowingMethod() {
- Method method;
- try {
- method = getClass().getMethod("errorThrowingMethod", Object.class);
- } catch (SecurityException e) {
- throw new IllegalStateException("This test needs access to reflection.");
- } catch (NoSuchMethodException e) {
- throw new AssertionError(
- "Someone changed EventSubscriberTest#errorThrowingMethod's " +
- "visibility, signature, or removed it entirely. (Must be public.)");
- }
- return method;
- }
-
- /**
- * Records the provided object in {@link #methodArgument} and sets
- * {@link #methodCalled}. This method is called reflectively by EventSubscriber
- * during tests, and must remain public.
- *
- * @param arg argument to record.
- */
- public void recordingMethod(Object arg) {
- assertFalse(methodCalled);
- methodCalled = true;
- methodArgument = arg;
- }
-
- public void exceptionThrowingMethod(Object arg) throws Exception {
- throw new IntentionalException();
- }
- /** Local exception subclass to check variety of exception thrown. */
- class IntentionalException extends Exception {
- private static final long serialVersionUID = -2500191180248181379L;
- }
-
- public void errorThrowingMethod(Object arg) {
- throw new JudgmentError();
- }
- /** Local Error subclass to check variety of error thrown. */
- class JudgmentError extends Error {
- private static final long serialVersionUID = 634248373797713373L;
- }
-}
diff --git a/guava-tests/test/com/google/common/eventbus/PackageSanityTests.java b/guava-tests/test/com/google/common/eventbus/PackageSanityTests.java
index 5f984b0..424e594 100644
--- a/guava-tests/test/com/google/common/eventbus/PackageSanityTests.java
+++ b/guava-tests/test/com/google/common/eventbus/PackageSanityTests.java
@@ -31,21 +31,35 @@ import javax.annotation.Nullable;
public class PackageSanityTests extends AbstractPackageSanityTests {
public PackageSanityTests() throws Exception {
- setDefault(EventSubscriber.class, new DummySubscriber().toEventSubscriber());
+ DummySubscriber dummySubscriber = new DummySubscriber();
+ setDefault(Subscriber.class, dummySubscriber.toSubscriber());
setDefault(Method.class, DummySubscriber.subscriberMethod());
+ setDefault(SubscriberExceptionContext.class, dummySubscriber.toContext());
+ setDefault(Dispatcher.class, Dispatcher.immediate());
}
private static class DummySubscriber {
- @SuppressWarnings("unused") // Used by reflection
- public void handle(@Nullable Object anything) {}
+ private final EventBus eventBus = new EventBus();
- EventSubscriber toEventSubscriber() throws Exception {
- return new EventSubscriber(this, subscriberMethod());
+ @Subscribe
+ public void handle(@Nullable Object anything) {
}
- private static Method subscriberMethod() throws NoSuchMethodException {
- return DummySubscriber.class.getMethod("handle", Object.class);
+ Subscriber toSubscriber() throws Exception {
+ return Subscriber.create(eventBus, this, subscriberMethod());
+ }
+
+ SubscriberExceptionContext toContext() {
+ return new SubscriberExceptionContext(eventBus, new Object(), this, subscriberMethod());
+ }
+
+ private static Method subscriberMethod() {
+ try {
+ return DummySubscriber.class.getMethod("handle", Object.class);
+ } catch (NoSuchMethodException e) {
+ throw new AssertionError(e);
+ }
}
}
}
diff --git a/guava-tests/test/com/google/common/eventbus/SubscriberRegistryTest.java b/guava-tests/test/com/google/common/eventbus/SubscriberRegistryTest.java
new file mode 100644
index 0000000..f3dc30b
--- /dev/null
+++ b/guava-tests/test/com/google/common/eventbus/SubscriberRegistryTest.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.eventbus;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterators;
+
+import junit.framework.TestCase;
+
+import java.util.Iterator;
+
+/**
+ * Tests for {@link SubscriberRegistry}.
+ *
+ * @author Colin Decker
+ */
+public class SubscriberRegistryTest extends TestCase {
+
+ private final SubscriberRegistry registry = new SubscriberRegistry(new EventBus());
+
+ public void testRegister() {
+ assertEquals(0, registry.getSubscribersForTesting(String.class).size());
+
+ registry.register(new StringSubscriber());
+ assertEquals(1, registry.getSubscribersForTesting(String.class).size());
+
+ registry.register(new StringSubscriber());
+ assertEquals(2, registry.getSubscribersForTesting(String.class).size());
+
+ registry.register(new ObjectSubscriber());
+ assertEquals(2, registry.getSubscribersForTesting(String.class).size());
+ assertEquals(1, registry.getSubscribersForTesting(Object.class).size());
+ }
+
+ public void testUnregister() {
+ StringSubscriber s1 = new StringSubscriber();
+ StringSubscriber s2 = new StringSubscriber();
+
+ registry.register(s1);
+ registry.register(s2);
+
+ registry.unregister(s1);
+ assertEquals(1, registry.getSubscribersForTesting(String.class).size());
+
+ registry.unregister(s2);
+ assertTrue(registry.getSubscribersForTesting(String.class).isEmpty());
+ }
+
+ public void testUnregister_notRegistered() {
+ try {
+ registry.unregister(new StringSubscriber());
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ StringSubscriber s1 = new StringSubscriber();
+ registry.register(s1);
+ try {
+ registry.unregister(new StringSubscriber());
+ fail();
+ } catch (IllegalArgumentException expected) {
+ // a StringSubscriber was registered, but not the same one we tried to unregister
+ }
+
+ registry.unregister(s1);
+
+ try {
+ registry.unregister(s1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testGetSubscribers() {
+ assertEquals(0, Iterators.size(registry.getSubscribers("")));
+
+ registry.register(new StringSubscriber());
+ assertEquals(1, Iterators.size(registry.getSubscribers("")));
+
+ registry.register(new StringSubscriber());
+ assertEquals(2, Iterators.size(registry.getSubscribers("")));
+
+ registry.register(new ObjectSubscriber());
+ assertEquals(3, Iterators.size(registry.getSubscribers("")));
+ assertEquals(1, Iterators.size(registry.getSubscribers(new Object())));
+ assertEquals(1, Iterators.size(registry.getSubscribers(1)));
+
+ registry.register(new IntegerSubscriber());
+ assertEquals(3, Iterators.size(registry.getSubscribers("")));
+ assertEquals(1, Iterators.size(registry.getSubscribers(new Object())));
+ assertEquals(2, Iterators.size(registry.getSubscribers(1)));
+ }
+
+ public void testGetSubscribers_returnsImmutableSnapshot() {
+ StringSubscriber s1 = new StringSubscriber();
+ StringSubscriber s2 = new StringSubscriber();
+ ObjectSubscriber o1 = new ObjectSubscriber();
+
+ Iterator<Subscriber> empty = registry.getSubscribers("");
+ assertFalse(empty.hasNext());
+
+ empty = registry.getSubscribers("");
+
+ registry.register(s1);
+ assertFalse(empty.hasNext());
+
+ Iterator<Subscriber> one = registry.getSubscribers("");
+ assertEquals(s1, one.next().target);
+ assertFalse(one.hasNext());
+
+ one = registry.getSubscribers("");
+
+ registry.register(s2);
+ registry.register(o1);
+
+ Iterator<Subscriber> three = registry.getSubscribers("");
+ assertEquals(s1, one.next().target);
+ assertFalse(one.hasNext());
+
+ assertEquals(s1, three.next().target);
+ assertEquals(s2, three.next().target);
+ assertEquals(o1, three.next().target);
+ assertFalse(three.hasNext());
+
+ three = registry.getSubscribers("");
+
+ registry.unregister(s2);
+
+ assertEquals(s1, three.next().target);
+ assertEquals(s2, three.next().target);
+ assertEquals(o1, three.next().target);
+ assertFalse(three.hasNext());
+
+ Iterator<Subscriber> two = registry.getSubscribers("");
+ assertEquals(s1, two.next().target);
+ assertEquals(o1, two.next().target);
+ assertFalse(two.hasNext());
+ }
+
+ public static class StringSubscriber {
+
+ @Subscribe
+ public void handle(String s) {
+ }
+ }
+
+ public static class IntegerSubscriber {
+
+ @Subscribe
+ public void handle(Integer i) {
+ }
+ }
+
+ public static class ObjectSubscriber {
+
+ @Subscribe
+ public void handle(Object o) {
+ }
+ }
+
+ public void testFlattenHierarchy() {
+ assertEquals(
+ ImmutableSet.of(
+ Object.class,
+ HierarchyFixtureInterface.class,
+ HierarchyFixtureSubinterface.class,
+ HierarchyFixtureParent.class,
+ HierarchyFixture.class),
+ SubscriberRegistry.flattenHierarchy(HierarchyFixture.class));
+ }
+
+ private interface HierarchyFixtureInterface {
+ // Exists only for hierarchy mapping; no members.
+ }
+
+ private interface HierarchyFixtureSubinterface
+ extends HierarchyFixtureInterface {
+ // Exists only for hierarchy mapping; no members.
+ }
+
+ private static class HierarchyFixtureParent
+ implements HierarchyFixtureSubinterface {
+ // Exists only for hierarchy mapping; no members.
+ }
+
+ private static class HierarchyFixture extends HierarchyFixtureParent {
+ // Exists only for hierarchy mapping; no members.
+ }
+}
diff --git a/guava-tests/test/com/google/common/eventbus/SubscriberTest.java b/guava-tests/test/com/google/common/eventbus/SubscriberTest.java
new file mode 100644
index 0000000..3860d56
--- /dev/null
+++ b/guava-tests/test/com/google/common/eventbus/SubscriberTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.eventbus;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Tests for {@link Subscriber}.
+ *
+ * @author Cliff Biffle
+ * @author Colin Decker
+ */
+public class SubscriberTest extends TestCase {
+
+ private static final Object FIXTURE_ARGUMENT = new Object();
+
+ private EventBus bus;
+ private boolean methodCalled;
+ private Object methodArgument;
+
+ @Override
+ protected void setUp() throws Exception {
+ bus = new EventBus();
+ methodCalled = false;
+ methodArgument = null;
+ }
+
+ public void testCreate() {
+ Subscriber s1 = Subscriber.create(bus, this, getTestSubscriberMethod("recordingMethod"));
+ assertThat(s1).isInstanceOf(Subscriber.SynchronizedSubscriber.class);
+
+ // a thread-safe method should not create a synchronized subscriber
+ Subscriber s2 = Subscriber.create(bus, this, getTestSubscriberMethod("threadSafeMethod"));
+ assertThat(s2).isNotInstanceOf(Subscriber.SynchronizedSubscriber.class);
+ }
+
+ public void testInvokeSubscriberMethod_basicMethodCall() throws Throwable {
+ Method method = getTestSubscriberMethod("recordingMethod");
+ Subscriber subscriber = Subscriber.create(bus, this, method);
+
+ subscriber.invokeSubscriberMethod(FIXTURE_ARGUMENT);
+
+ assertTrue("Subscriber must call provided method", methodCalled);
+ assertTrue("Subscriber argument must be exactly the provided object.",
+ methodArgument == FIXTURE_ARGUMENT);
+ }
+
+ public void testInvokeSubscriberMethod_exceptionWrapping() throws Throwable {
+ Method method = getTestSubscriberMethod("exceptionThrowingMethod");
+ Subscriber subscriber = Subscriber.create(bus, this, method);
+
+ try {
+ subscriber.invokeSubscriberMethod(FIXTURE_ARGUMENT);
+ fail("Subscribers whose methods throw must throw InvocationTargetException");
+ } catch (InvocationTargetException expected) {
+ assertThat(expected.getCause()).isInstanceOf(IntentionalException.class);
+ }
+ }
+
+ public void testInvokeSubscriberMethod_errorPassthrough() throws Throwable {
+ Method method = getTestSubscriberMethod("errorThrowingMethod");
+ Subscriber subscriber = Subscriber.create(bus, this, method);
+
+ try {
+ subscriber.invokeSubscriberMethod(FIXTURE_ARGUMENT);
+ fail("Subscribers whose methods throw Errors must rethrow them");
+ } catch (JudgmentError expected) {
+ }
+ }
+
+ public void testEquals() throws Exception {
+ Method charAt = String.class.getMethod("charAt", int.class);
+ Method concat = String.class.getMethod("concat", String.class);
+ new EqualsTester()
+ .addEqualityGroup(
+ Subscriber.create(bus, "foo", charAt), Subscriber.create(bus, "foo", charAt))
+ .addEqualityGroup(Subscriber.create(bus, "bar", charAt))
+ .addEqualityGroup(Subscriber.create(bus, "foo", concat))
+ .testEquals();
+ }
+
+ private Method getTestSubscriberMethod(String name) {
+ try {
+ return getClass().getDeclaredMethod(name, Object.class);
+ } catch (NoSuchMethodException e) {
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * Records the provided object in {@link #methodArgument} and sets {@link #methodCalled}. This
+ * method is called reflectively by Subscriber during tests, and must remain public.
+ *
+ * @param arg argument to record.
+ */
+ @Subscribe
+ public void recordingMethod(Object arg) {
+ assertFalse(methodCalled);
+ methodCalled = true;
+ methodArgument = arg;
+ }
+
+ @Subscribe
+ public void exceptionThrowingMethod(Object arg) throws Exception {
+ throw new IntentionalException();
+ }
+
+ /**
+ * Local exception subclass to check variety of exception thrown.
+ */
+ class IntentionalException extends Exception {
+
+ private static final long serialVersionUID = -2500191180248181379L;
+ }
+
+ @Subscribe
+ public void errorThrowingMethod(Object arg) {
+ throw new JudgmentError();
+ }
+
+ @Subscribe @AllowConcurrentEvents
+ public void threadSafeMethod(Object arg) {
+ }
+
+ /**
+ * Local Error subclass to check variety of error thrown.
+ */
+ class JudgmentError extends Error {
+
+ private static final long serialVersionUID = 634248373797713373L;
+ }
+}
diff --git a/guava-tests/test/com/google/common/eventbus/outside/AnnotatedSubscriberFinderTests.java b/guava-tests/test/com/google/common/eventbus/outside/AnnotatedSubscriberFinderTests.java
index b22eefd..ab3f401 100644
--- a/guava-tests/test/com/google/common/eventbus/outside/AnnotatedSubscriberFinderTests.java
+++ b/guava-tests/test/com/google/common/eventbus/outside/AnnotatedSubscriberFinderTests.java
@@ -30,6 +30,7 @@ import java.util.List;
* Test that EventBus finds the correct subscribers.
*
* This test must be outside the c.g.c.eventbus package to test correctly.
+ *
* @author Louis Wasserman
*/
public class AnnotatedSubscriberFinderTests {
@@ -62,8 +63,8 @@ public class AnnotatedSubscriberFinderTests {
/*
* We break the tests up based on whether they are annotated or abstract in the superclass.
*/
- public static class BaseSubscriberFinderTest extends
- AbstractEventBusTest<BaseSubscriberFinderTest.Subscriber> {
+ public static class BaseSubscriberFinderTest
+ extends AbstractEventBusTest<BaseSubscriberFinderTest.Subscriber> {
static class Subscriber {
final List<Object> nonSubscriberEvents = Lists.newArrayList();
final List<Object> subscriberEvents = Lists.newArrayList();
@@ -83,7 +84,7 @@ public class AnnotatedSubscriberFinderTests {
}
public void testSubscriber() {
- assertThat(getSubscriber().subscriberEvents).has().item(EVENT);
+ assertThat(getSubscriber().subscriberEvents).contains(EVENT);
}
@Override
@@ -92,8 +93,8 @@ public class AnnotatedSubscriberFinderTests {
}
}
- public static class AnnotatedAndAbstractInSuperclassTest extends
- AbstractEventBusTest<AnnotatedAndAbstractInSuperclassTest.SubClass> {
+ public static class AnnotatedAndAbstractInSuperclassTest
+ extends AbstractEventBusTest<AnnotatedAndAbstractInSuperclassTest.SubClass> {
abstract static class SuperClass {
@Subscribe
public abstract void overriddenAndAnnotatedInSubclass(Object o);
@@ -119,11 +120,11 @@ public class AnnotatedSubscriberFinderTests {
}
public void testOverriddenAndAnnotatedInSubclass() {
- assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).has().item(EVENT);
+ assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).contains(EVENT);
}
public void testOverriddenNotAnnotatedInSubclass() {
- assertThat(getSubscriber().overriddenInSubclassEvents).has().item(EVENT);
+ assertThat(getSubscriber().overriddenInSubclassEvents).contains(EVENT);
}
@Override
@@ -132,8 +133,8 @@ public class AnnotatedSubscriberFinderTests {
}
}
- public static class AnnotatedNotAbstractInSuperclassTest extends
- AbstractEventBusTest<AnnotatedNotAbstractInSuperclassTest.SubClass> {
+ public static class AnnotatedNotAbstractInSuperclassTest
+ extends AbstractEventBusTest<AnnotatedNotAbstractInSuperclassTest.SubClass> {
static class SuperClass {
final List<Object> notOverriddenInSubclassEvents = Lists.newArrayList();
final List<Object> overriddenNotAnnotatedInSubclassEvents = Lists.newArrayList();
@@ -199,26 +200,26 @@ public class AnnotatedSubscriberFinderTests {
}
public void testNotOverriddenInSubclass() {
- assertThat(getSubscriber().notOverriddenInSubclassEvents).has().item(EVENT);
+ assertThat(getSubscriber().notOverriddenInSubclassEvents).contains(EVENT);
}
public void testOverriddenNotAnnotatedInSubclass() {
- assertThat(getSubscriber().overriddenNotAnnotatedInSubclassEvents).has().item(EVENT);
+ assertThat(getSubscriber().overriddenNotAnnotatedInSubclassEvents).contains(EVENT);
}
public void testDifferentlyOverriddenNotAnnotatedInSubclass() {
assertThat(getSubscriber().differentlyOverriddenNotAnnotatedInSubclassGoodEvents)
- .has().item(EVENT);
+ .contains(EVENT);
assertThat(getSubscriber().differentlyOverriddenNotAnnotatedInSubclassBadEvents).isEmpty();
}
public void testOverriddenAndAnnotatedInSubclass() {
- assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).has().item(EVENT);
+ assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).contains(EVENT);
}
public void testDifferentlyOverriddenAndAnnotatedInSubclass() {
assertThat(getSubscriber().differentlyOverriddenAnnotatedInSubclassGoodEvents)
- .has().item(EVENT);
+ .contains(EVENT);
assertThat(getSubscriber().differentlyOverriddenAnnotatedInSubclassBadEvents).isEmpty();
}
@@ -228,8 +229,8 @@ public class AnnotatedSubscriberFinderTests {
}
}
- public static class AbstractNotAnnotatedInSuperclassTest extends
- AbstractEventBusTest<AbstractNotAnnotatedInSuperclassTest.SubClass> {
+ public static class AbstractNotAnnotatedInSuperclassTest
+ extends AbstractEventBusTest<AbstractNotAnnotatedInSuperclassTest.SubClass> {
abstract static class SuperClass {
public abstract void overriddenInSubclassNowhereAnnotated(Object o);
@@ -253,7 +254,7 @@ public class AnnotatedSubscriberFinderTests {
}
public void testOverriddenAndAnnotatedInSubclass() {
- assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).has().item(EVENT);
+ assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).contains(EVENT);
}
public void testOverriddenInSubclassNowhereAnnotated() {
@@ -266,8 +267,8 @@ public class AnnotatedSubscriberFinderTests {
}
}
- public static class NeitherAbstractNorAnnotatedInSuperclassTest extends
- AbstractEventBusTest<NeitherAbstractNorAnnotatedInSuperclassTest.SubClass> {
+ public static class NeitherAbstractNorAnnotatedInSuperclassTest
+ extends AbstractEventBusTest<NeitherAbstractNorAnnotatedInSuperclassTest.SubClass> {
static class SuperClass {
final List<Object> neitherOverriddenNorAnnotatedEvents = Lists.newArrayList();
final List<Object> overriddenInSubclassNowhereAnnotatedEvents = Lists.newArrayList();
@@ -308,7 +309,7 @@ public class AnnotatedSubscriberFinderTests {
}
public void testOverriddenAndAnnotatedInSubclass() {
- assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).has().item(EVENT);
+ assertThat(getSubscriber().overriddenAndAnnotatedInSubclassEvents).contains(EVENT);
}
@Override
@@ -317,8 +318,8 @@ public class AnnotatedSubscriberFinderTests {
}
}
- public static class DeepInterfaceTest extends
- AbstractEventBusTest<DeepInterfaceTest.SubscriberClass> {
+ public static class DeepInterfaceTest
+ extends AbstractEventBusTest<DeepInterfaceTest.SubscriberClass> {
interface Interface1 {
@Subscribe
void annotatedIn1(Object o);
@@ -410,31 +411,31 @@ public class AnnotatedSubscriberFinderTests {
}
public void testAnnotatedIn1() {
- assertThat(getSubscriber().annotatedIn1Events).has().item(EVENT);
+ assertThat(getSubscriber().annotatedIn1Events).contains(EVENT);
}
public void testAnnotatedIn2() {
- assertThat(getSubscriber().annotatedIn2Events).has().item(EVENT);
+ assertThat(getSubscriber().annotatedIn2Events).contains(EVENT);
}
public void testAnnotatedIn1And2() {
- assertThat(getSubscriber().annotatedIn1And2Events).has().item(EVENT);
+ assertThat(getSubscriber().annotatedIn1And2Events).contains(EVENT);
}
public void testAnnotatedIn1And2AndClass() {
- assertThat(getSubscriber().annotatedIn1And2AndClassEvents).has().item(EVENT);
+ assertThat(getSubscriber().annotatedIn1And2AndClassEvents).contains(EVENT);
}
public void testDeclaredIn1AnnotatedIn2() {
- assertThat(getSubscriber().declaredIn1AnnotatedIn2Events).has().item(EVENT);
+ assertThat(getSubscriber().declaredIn1AnnotatedIn2Events).contains(EVENT);
}
public void testDeclaredIn1AnnotatedInClass() {
- assertThat(getSubscriber().declaredIn1AnnotatedInClassEvents).has().item(EVENT);
+ assertThat(getSubscriber().declaredIn1AnnotatedInClassEvents).contains(EVENT);
}
public void testDeclaredIn2AnnotatedInClass() {
- assertThat(getSubscriber().declaredIn2AnnotatedInClassEvents).has().item(EVENT);
+ assertThat(getSubscriber().declaredIn2AnnotatedInClassEvents).contains(EVENT);
}
public void testNowhereAnnotated() {
diff --git a/guava-tests/test/com/google/common/hash/BloomFilterTest.java b/guava-tests/test/com/google/common/hash/BloomFilterTest.java
index 4f54d10..594bcf8 100644
--- a/guava-tests/test/com/google/common/hash/BloomFilterTest.java
+++ b/guava-tests/test/com/google/common/hash/BloomFilterTest.java
@@ -18,6 +18,7 @@ package com.google.common.hash;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.hash.BloomFilterStrategies.BitArray;
+import static com.google.common.truth.Truth.assertThat;
import com.google.common.collect.ImmutableSet;
import com.google.common.math.LongMath;
@@ -41,6 +42,7 @@ import javax.annotation.Nullable;
* @author Dimitris Andreou
*/
public class BloomFilterTest extends TestCase {
+ @SuppressUnderAndroid // OutOfMemoryError
public void testLargeBloomFilterDoesntOverflow() {
long numBits = Integer.MAX_VALUE;
numBits++;
@@ -188,6 +190,7 @@ public class BloomFilterTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testPreconditions() {
try {
BloomFilter.create(Funnels.unencodedCharsFunnel(), -1);
@@ -207,6 +210,7 @@ public class BloomFilterTest extends TestCase {
} catch (IllegalArgumentException expected) {}
}
+ @SuppressWarnings("CheckReturnValue")
public void testFailureWhenMoreThan255HashFunctionsAreNeeded() {
try {
int n = 1000;
@@ -241,6 +245,7 @@ public class BloomFilterTest extends TestCase {
/**
* Tests that we always get a non-negative optimal size.
*/
+ @SuppressWarnings("CheckReturnValue")
public void testOptimalSize() {
for (int n = 1; n < 1000; n++) {
for (double fpp = Double.MIN_VALUE; fpp < 1.0; fpp += 0.001) {
@@ -261,10 +266,18 @@ public class BloomFilterTest extends TestCase {
BloomFilter.create(HashTestUtils.BAD_FUNNEL, Integer.MAX_VALUE, Double.MIN_VALUE);
fail("we can't represent such a large BF!");
} catch (IllegalArgumentException expected) {
- assertEquals("Could not create BloomFilter of 3327428144502 bits", expected.getMessage());
+ assertThat(expected).hasMessage("Could not create BloomFilter of 3327428144502 bits");
}
}
+ @SuppressWarnings("CheckReturnValue")
+ @SuppressUnderAndroid // OutOfMemoryError
+ public void testLargeNumberOfInsertions() {
+ // We use horrible FPPs here to keep Java from OOM'ing
+ BloomFilter.create(Funnels.unencodedCharsFunnel(), 42L + Integer.MAX_VALUE, 0.28);
+ BloomFilter.create(Funnels.unencodedCharsFunnel(), 50L * Integer.MAX_VALUE, 0.99);
+ }
+
private void checkSanity(BloomFilter<Object> bf) {
assertFalse(bf.mightContain(new Object()));
assertFalse(bf.apply(new Object()));
@@ -463,7 +476,7 @@ public class BloomFilterTest extends TestCase {
* Only appending a new constant is allowed.
*/
public void testBloomFilterStrategies() {
- assertEquals(2, BloomFilterStrategies.values().length);
+ assertThat(BloomFilterStrategies.values()).hasLength(2);
assertEquals(BloomFilterStrategies.MURMUR128_MITZ_32, BloomFilterStrategies.values()[0]);
assertEquals(BloomFilterStrategies.MURMUR128_MITZ_64, BloomFilterStrategies.values()[1]);
}
diff --git a/guava-tests/test/com/google/common/hash/HashCodeTest.java b/guava-tests/test/com/google/common/hash/HashCodeTest.java
index a15a57b..ae1fed8 100644
--- a/guava-tests/test/com/google/common/hash/HashCodeTest.java
+++ b/guava-tests/test/com/google/common/hash/HashCodeTest.java
@@ -219,6 +219,7 @@ public class HashCodeTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testFromStringFailsWithInvalidHexChar() {
try {
HashCode.fromString("7f8005ff0z");
@@ -227,6 +228,7 @@ public class HashCodeTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testFromStringFailsWithUpperCaseString() {
String string = Hashing.sha1().hashString("foo", Charsets.US_ASCII).toString().toUpperCase();
try {
@@ -236,6 +238,7 @@ public class HashCodeTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testFromStringFailsWithShortInputs() {
try {
HashCode.fromString("");
@@ -250,6 +253,7 @@ public class HashCodeTest extends TestCase {
HashCode.fromString("7f");
}
+ @SuppressWarnings("CheckReturnValue")
public void testFromStringFailsWithOddLengthInput() {
try {
HashCode.fromString("7f8");
@@ -343,6 +347,7 @@ public class HashCodeTest extends TestCase {
.forAllPublicStaticMethods(HashCode.class);
}
+ @SuppressWarnings("CheckReturnValue")
private static void assertExpectedHashCode(ExpectedHashCode expectedHashCode, HashCode hash) {
assertTrue(Arrays.equals(expectedHashCode.bytes, hash.asBytes()));
byte[] bb = new byte[hash.bits() / 8];
diff --git a/guava-tests/test/com/google/common/hash/HashFunctionEnum.java b/guava-tests/test/com/google/common/hash/HashFunctionEnum.java
index 7a2d390..6927094 100644
--- a/guava-tests/test/com/google/common/hash/HashFunctionEnum.java
+++ b/guava-tests/test/com/google/common/hash/HashFunctionEnum.java
@@ -33,6 +33,7 @@ enum HashFunctionEnum {
MURMUR3_32(Hashing.murmur3_32()),
SHA1(Hashing.sha1()),
SHA256(Hashing.sha256()),
+ SHA384(Hashing.sha384()),
SHA512(Hashing.sha512()),
SIP_HASH24(Hashing.sipHash24()),
diff --git a/guava-tests/test/com/google/common/hash/HashingTest.java b/guava-tests/test/com/google/common/hash/HashingTest.java
index 74b43c9..09d427c 100644
--- a/guava-tests/test/com/google/common/hash/HashingTest.java
+++ b/guava-tests/test/com/google/common/hash/HashingTest.java
@@ -16,10 +16,9 @@
package com.google.common.hash;
-import static com.google.common.hash.Hashing.ConcatenatedHashFunction;
-import static com.google.common.hash.Hashing.goodFastHash;
+import static com.google.common.base.Charsets.UTF_8;
+import static java.util.Arrays.asList;
-import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Lists;
@@ -36,6 +35,7 @@ import java.lang.reflect.Modifier;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
import java.util.Random;
/**
@@ -69,6 +69,14 @@ public class HashingTest extends TestCase {
assertEquals("Hashing.sha256()", Hashing.sha256().toString());
}
+ public void testSha384() {
+ HashTestUtils.checkAvalanche(Hashing.sha384(), 100, 0.4);
+ HashTestUtils.checkNo2BitCharacteristics(Hashing.sha384());
+ HashTestUtils.checkNoFunnels(Hashing.sha384());
+ HashTestUtils.assertInvariants(Hashing.sha384());
+ assertEquals("Hashing.sha384()", Hashing.sha384().toString());
+ }
+
public void testSha512() {
HashTestUtils.checkAvalanche(Hashing.sha512(), 100, 0.4);
HashTestUtils.checkNo2BitCharacteristics(Hashing.sha512());
@@ -198,6 +206,7 @@ public class HashingTest extends TestCase {
private static final int ITERS = 10000;
private static final int MAX_SHARDS = 500;
+ @SuppressWarnings("CheckReturnValue")
public void testConsistentHash_outOfRange() {
try {
Hashing.consistentHash(5L, 0);
@@ -238,6 +247,7 @@ public class HashingTest extends TestCase {
private static final double MAX_PERCENT_SPREAD = 0.5;
private static final long RANDOM_SEED = 177L;
+ @SuppressWarnings("CheckReturnValue")
public void testCombineOrdered_empty() {
try {
Hashing.combineOrdered(Collections.<HashCode>emptySet());
@@ -246,6 +256,7 @@ public class HashingTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testCombineOrdered_differentBitLengths() {
try {
Hashing.combineOrdered(ImmutableList.of(HashCode.fromInt(32), HashCode.fromLong(32L)));
@@ -280,6 +291,7 @@ public class HashingTest extends TestCase {
assertFalse(hashCode1.equals(hashCode2));
}
+ @SuppressWarnings("CheckReturnValue")
public void testCombineUnordered_empty() {
try {
Hashing.combineUnordered(Collections.<HashCode>emptySet());
@@ -288,6 +300,7 @@ public class HashingTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testCombineUnordered_differentBitLengths() {
try {
Hashing.combineUnordered(ImmutableList.of(HashCode.fromInt(32), HashCode.fromLong(32L)));
@@ -321,35 +334,61 @@ public class HashingTest extends TestCase {
assertEquals(hashCode1, hashCode2);
}
- public void testConcatenatedHashFunction_equals() {
+ // This isn't specified by contract, but it'll still be nice to know if this behavior changes.
+ public void testConcatenating_equals() {
+ new EqualsTester()
+ .addEqualityGroup(Hashing.concatenating(asList(Hashing.md5())))
+ .addEqualityGroup(Hashing.concatenating(asList(Hashing.murmur3_32())))
+ .addEqualityGroup(
+ Hashing.concatenating(Hashing.md5(), Hashing.md5()),
+ Hashing.concatenating(asList(Hashing.md5(), Hashing.md5())))
+ .addEqualityGroup(
+ Hashing.concatenating(Hashing.murmur3_32(), Hashing.md5()),
+ Hashing.concatenating(asList(Hashing.murmur3_32(), Hashing.md5())))
+ .addEqualityGroup(
+ Hashing.concatenating(Hashing.md5(), Hashing.murmur3_32()),
+ Hashing.concatenating(asList(Hashing.md5(), Hashing.murmur3_32())))
+ .testEquals();
+ }
+
+ public void testConcatenatingIterable_bits() {
+ assertEquals(
+ Hashing.md5().bits() + Hashing.md5().bits(),
+ Hashing.concatenating(asList(Hashing.md5(), Hashing.md5())).bits());
assertEquals(
- new ConcatenatedHashFunction(Hashing.md5()),
- new ConcatenatedHashFunction(Hashing.md5()));
+ Hashing.md5().bits() + Hashing.murmur3_32().bits(),
+ Hashing.concatenating(asList(Hashing.md5(), Hashing.murmur3_32())).bits());
assertEquals(
- new ConcatenatedHashFunction(Hashing.md5(), Hashing.murmur3_32()),
- new ConcatenatedHashFunction(Hashing.md5(), Hashing.murmur3_32()));
+ Hashing.md5().bits() + Hashing.murmur3_32().bits() + Hashing.murmur3_128().bits(),
+ Hashing.concatenating(
+ asList(Hashing.md5(), Hashing.murmur3_32(), Hashing.murmur3_128())).bits());
}
- public void testConcatenatedHashFunction_bits() {
- assertEquals(Hashing.md5().bits(),
- new ConcatenatedHashFunction(Hashing.md5()).bits());
- assertEquals(Hashing.md5().bits() + Hashing.murmur3_32().bits(),
- new ConcatenatedHashFunction(Hashing.md5(), Hashing.murmur3_32()).bits());
- assertEquals(Hashing.md5().bits() + Hashing.murmur3_32().bits() + Hashing.murmur3_128().bits(),
- new ConcatenatedHashFunction(
- Hashing.md5(), Hashing.murmur3_32(), Hashing.murmur3_128()).bits());
+ public void testConcatenatingVarArgs_bits() {
+ assertEquals(
+ Hashing.md5().bits() + Hashing.md5().bits(),
+ Hashing.concatenating(Hashing.md5(), Hashing.md5()).bits());
+ assertEquals(
+ Hashing.md5().bits() + Hashing.murmur3_32().bits(),
+ Hashing.concatenating(Hashing.md5(), Hashing.murmur3_32()).bits());
+ assertEquals(
+ Hashing.md5().bits() + Hashing.murmur3_32().bits() + Hashing.murmur3_128().bits(),
+ Hashing.concatenating(Hashing.md5(), Hashing.murmur3_32(), Hashing.murmur3_128()).bits());
}
- public void testConcatenatedHashFunction_makeHash() {
+ public void testConcatenatingHashFunction_makeHash() {
byte[] md5Hash = Hashing.md5().hashLong(42L).asBytes();
byte[] murmur3Hash = Hashing.murmur3_32().hashLong(42L).asBytes();
byte[] combined = new byte[md5Hash.length + murmur3Hash.length];
ByteBuffer buffer = ByteBuffer.wrap(combined);
buffer.put(md5Hash);
buffer.put(murmur3Hash);
+ HashCode expected = HashCode.fromBytes(combined);
- assertEquals(HashCode.fromBytes(combined),
- new ConcatenatedHashFunction(Hashing.md5(), Hashing.murmur3_32()).hashLong(42L));
+ assertEquals(expected,
+ Hashing.concatenating(Hashing.md5(), Hashing.murmur3_32()).hashLong(42L));
+ assertEquals(expected,
+ Hashing.concatenating(asList(Hashing.md5(), Hashing.murmur3_32())).hashLong(42L));
}
public void testHashIntReverseBytesVsHashBytesIntsToByteArray() {
@@ -399,15 +438,24 @@ public class HashingTest extends TestCase {
"d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592")
.put(Hashing.sha256(), TQBFJOTLDP,
"ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c")
+ .put(Hashing.sha384(), EMPTY_STRING,
+ "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da2"
+ + "74edebfe76f65fbd51ad2f14898b95b")
+ .put(Hashing.sha384(), TQBFJOTLD,
+ "ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509"
+ + "cb1e5dc1e85a941bbee3d7f2afbc9b1")
+ .put(Hashing.sha384(), TQBFJOTLDP,
+ "ed892481d8272ca6df370bf706e4d7bc1b5739fa2177aae6c50e946678718fc67"
+ + "a7af2819a021c2fc34e91bdb63409d7")
.put(Hashing.sha512(), EMPTY_STRING,
- "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce" +
- "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e")
+ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce"
+ + "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e")
.put(Hashing.sha512(), TQBFJOTLD,
- "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb64" +
- "2e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6")
+ "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb64"
+ + "2e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6")
.put(Hashing.sha512(), TQBFJOTLDP,
- "91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bb" +
- "c6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed")
+ "91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bb"
+ + "c6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed")
.put(Hashing.crc32(), EMPTY_STRING, "00000000")
.put(Hashing.crc32(), TQBFJOTLD, "39a34f41")
.put(Hashing.crc32(), TQBFJOTLDP, "e9259051")
@@ -437,14 +485,15 @@ public class HashingTest extends TestCase {
String input = cell.getColumnKey();
String expected = cell.getValue();
assertEquals(
- String.format("Known hash for hash(%s, UTF_8) failed", input),
+ String.format(Locale.ROOT, "Known hash for hash(%s, UTF_8) failed", input),
expected,
- func.hashString(input, Charsets.UTF_8).toString());
+ func.hashString(input, UTF_8).toString());
}
}
public void testNullPointers() {
NullPointerTester tester = new NullPointerTester()
+ .setDefault(byte[].class, "secret key".getBytes(UTF_8))
.setDefault(HashCode.class, HashCode.fromLong(0));
tester.testAllPublicStaticMethods(Hashing.class);
}
@@ -465,14 +514,14 @@ public class HashingTest extends TestCase {
* testSeededHashFunctionEquals}.
*/
public void testGoodFastHashEquals() throws Exception {
- HashFunction hashFunction1a = goodFastHash(1);
- HashFunction hashFunction1b = goodFastHash(32);
- HashFunction hashFunction2a = goodFastHash(33);
- HashFunction hashFunction2b = goodFastHash(128);
- HashFunction hashFunction3a = goodFastHash(129);
- HashFunction hashFunction3b = goodFastHash(256);
- HashFunction hashFunction4a = goodFastHash(257);
- HashFunction hashFunction4b = goodFastHash(384);
+ HashFunction hashFunction1a = Hashing.goodFastHash(1);
+ HashFunction hashFunction1b = Hashing.goodFastHash(32);
+ HashFunction hashFunction2a = Hashing.goodFastHash(33);
+ HashFunction hashFunction2b = Hashing.goodFastHash(128);
+ HashFunction hashFunction3a = Hashing.goodFastHash(129);
+ HashFunction hashFunction3b = Hashing.goodFastHash(256);
+ HashFunction hashFunction4a = Hashing.goodFastHash(257);
+ HashFunction hashFunction4b = Hashing.goodFastHash(384);
new EqualsTester()
.addEqualityGroup(hashFunction1a, hashFunction1b)
@@ -513,7 +562,9 @@ public class HashingTest extends TestCase {
if (method.getReturnType().equals(HashFunction.class) // must return HashFunction
&& Modifier.isPublic(method.getModifiers()) // only the public methods
&& method.getParameterTypes().length != 0 // only the seeded hash functions
- && !method.getName().equals("goodFastHash")) { // tested in testGoodFastHashEquals
+ && !method.getName().equals("concatenating") // don't test Hashing.concatenating()
+ && !method.getName().equals("goodFastHash") // tested in testGoodFastHashEquals
+ && !method.getName().startsWith("hmac")) { // skip hmac functions
Object[] params1 = new Object[method.getParameterTypes().length];
Object[] params2 = new Object[method.getParameterTypes().length];
for (int i = 0; i < params1.length; i++) {
diff --git a/guava-tests/test/com/google/common/hash/MessageDigestHashFunctionTest.java b/guava-tests/test/com/google/common/hash/MessageDigestHashFunctionTest.java
index 4ff932a..c86c5b1 100644
--- a/guava-tests/test/com/google/common/hash/MessageDigestHashFunctionTest.java
+++ b/guava-tests/test/com/google/common/hash/MessageDigestHashFunctionTest.java
@@ -47,6 +47,7 @@ public class MessageDigestHashFunctionTest extends TestCase {
.put("sHa-1", Hashing.sha1()) // Not the official name, but still works
.put("SHA-1", Hashing.sha1())
.put("SHA-256", Hashing.sha256())
+ .put("SHA-384", Hashing.sha384())
.put("SHA-512", Hashing.sha512())
.build();
@@ -72,6 +73,7 @@ public class MessageDigestHashFunctionTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testHashTwice() {
Hasher sha1 = Hashing.sha1().newHasher();
diff --git a/guava-tests/test/com/google/common/hash/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/hash/SuppressUnderAndroid.java
new file mode 100644
index 0000000..ae3ac8c
--- /dev/null
+++ b/guava-tests/test/com/google/common/hash/SuppressUnderAndroid.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.hash;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>For more discussion, see {@linkplain com.google.common.base.SuppressUnderAndroid the
+ * documentation on another copy of this annotation}.
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/io/BaseEncodingTest.java b/guava-tests/test/com/google/common/io/BaseEncodingTest.java
index 9580185..44db12e 100644
--- a/guava-tests/test/com/google/common/io/BaseEncodingTest.java
+++ b/guava-tests/test/com/google/common/io/BaseEncodingTest.java
@@ -18,6 +18,7 @@ import static com.google.common.io.BaseEncoding.base16;
import static com.google.common.io.BaseEncoding.base32;
import static com.google.common.io.BaseEncoding.base32Hex;
import static com.google.common.io.BaseEncoding.base64;
+import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
@@ -36,6 +37,8 @@ import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
+import javax.annotation.Nullable;
+
/**
* Tests for {@code BaseEncoding}.
*
@@ -111,12 +114,16 @@ public class BaseEncodingTest extends TestCase {
public void testBase64InvalidDecodings() {
// These contain bytes not in the decodabet.
- assertFailsToDecode(base64(), "\u007f");
- assertFailsToDecode(base64(), "Wf2!");
+ assertFailsToDecode(base64(), "A\u007f", "Unrecognized character: 0x7f");
+ assertFailsToDecode(base64(), "Wf2!", "Unrecognized character: !");
// This sentence just isn't base64() encoded.
assertFailsToDecode(base64(), "let's not talk of love or chains!");
// A 4n+1 length string is never legal base64().
- assertFailsToDecode(base64(), "12345");
+ assertFailsToDecode(base64(), "12345", "Invalid input length 5");
+ // These have a combination of invalid length, unrecognized characters and wrong padding.
+ assertFailsToDecode(base64(), "AB=C", "Unrecognized character: =");
+ assertFailsToDecode(base64(), "A=BCD", "Invalid input length 5");
+ assertFailsToDecode(base64(), "?", "Invalid input length 1");
}
@SuppressWarnings("ReturnValueIgnored")
@@ -185,6 +192,14 @@ public class BaseEncodingTest extends TestCase {
testStreamingEncodingWithSeparators(enc, "foobar", "Zm9vYmFy");
}
+ public void testBase64Offset() {
+ testEncodesWithOffset(base64(), "foobar", 0, 6, "Zm9vYmFy");
+ testEncodesWithOffset(base64(), "foobar", 1, 5, "b29iYXI=");
+ testEncodesWithOffset(base64(), "foobar", 2, 3, "b2Jh");
+ testEncodesWithOffset(base64(), "foobar", 3, 1, "Yg==");
+ testEncodesWithOffset(base64(), "foobar", 4, 0, "");
+ }
+
public void testBase32() {
// The following test vectors are specified in RFC 4648 itself
testEncodingWithCasing(base32(), "", "");
@@ -230,20 +245,32 @@ public class BaseEncodingTest extends TestCase {
public void testBase32InvalidDecodings() {
// These contain bytes not in the decodabet.
- assertFailsToDecode(base32(), "\u007f");
- assertFailsToDecode(base32(), "Wf2!");
+ assertFailsToDecode(base32(), "A ", "Unrecognized character: 0x20");
+ assertFailsToDecode(base32(), "Wf2!", "Unrecognized character: f");
// This sentence just isn't base32() encoded.
assertFailsToDecode(base32(), "let's not talk of love or chains!");
// An 8n+{1,3,6} length string is never legal base32.
- assertFailsToDecode(base32(), "A");
+ assertFailsToDecode(base32(), "A", "Invalid input length 1");
assertFailsToDecode(base32(), "ABC");
assertFailsToDecode(base32(), "ABCDEF");
+ // These have a combination of invalid length, unrecognized characters and wrong padding.
+ assertFailsToDecode(base32(), "AB=C", "Unrecognized character: =");
+ assertFailsToDecode(base32(), "A=BCDE", "Invalid input length 6");
+ assertFailsToDecode(base32(), "?", "Invalid input length 1");
}
public void testBase32UpperCaseIsNoOp() {
assertSame(base32(), base32().upperCase());
}
+ public void testBase32Offset() {
+ testEncodesWithOffset(base32(), "foobar", 0, 6, "MZXW6YTBOI======");
+ testEncodesWithOffset(base32(), "foobar", 1, 5, "N5XWEYLS");
+ testEncodesWithOffset(base32(), "foobar", 2, 3, "N5RGC===");
+ testEncodesWithOffset(base32(), "foobar", 3, 1, "MI======");
+ testEncodesWithOffset(base32(), "foobar", 4, 0, "");
+ }
+
public void testBase32Hex() {
// The following test vectors are specified in RFC 4648 itself
testEncodingWithCasing(base32Hex(), "", "");
@@ -278,8 +305,8 @@ public class BaseEncodingTest extends TestCase {
public void testBase32HexInvalidDecodings() {
// These contain bytes not in the decodabet.
- assertFailsToDecode(base32Hex(), "\u007f");
- assertFailsToDecode(base32Hex(), "Wf2!");
+ assertFailsToDecode(base32Hex(), "A\u007f", "Unrecognized character: 0x7f");
+ assertFailsToDecode(base32Hex(), "Wf2!", "Unrecognized character: W");
// This sentence just isn't base32 encoded.
assertFailsToDecode(base32Hex(), "let's not talk of love or chains!");
// An 8n+{1,3,6} length string is never legal base32.
@@ -306,6 +333,25 @@ public class BaseEncodingTest extends TestCase {
assertSame(base16(), base16().upperCase());
}
+ public void testBase16InvalidDecodings() {
+ // These contain bytes not in the decodabet.
+ assertFailsToDecode(base16(), "\n\n", "Unrecognized character: 0xa");
+ assertFailsToDecode(base16(), "EFGH", "Unrecognized character: G");
+ // Valid base16 strings always have an even length.
+ assertFailsToDecode(base16(), "A", "Invalid input length 1");
+ assertFailsToDecode(base16(), "ABC");
+ // These have a combination of invalid length and unrecognized characters.
+ assertFailsToDecode(base16(), "?", "Invalid input length 1");
+ }
+
+ public void testBase16Offset() {
+ testEncodesWithOffset(base16(), "foobar", 0, 6, "666F6F626172");
+ testEncodesWithOffset(base16(), "foobar", 1, 5, "6F6F626172");
+ testEncodesWithOffset(base16(), "foobar", 2, 3, "6F6261");
+ testEncodesWithOffset(base16(), "foobar", 3, 1, "62");
+ testEncodesWithOffset(base16(), "foobar", 4, 0, "");
+ }
+
private static void testEncodingWithCasing(
BaseEncoding encoding, String decoded, String encoded) {
testEncodingWithSeparators(encoding, decoded, encoded);
@@ -332,39 +378,39 @@ public class BaseEncodingTest extends TestCase {
}
private static void testEncodes(BaseEncoding encoding, String decoded, String encoded) {
- byte[] bytes;
- try {
- // GWT does not support String.getBytes(Charset)
- bytes = decoded.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError();
- }
- assertEquals(encoded, encoding.encode(bytes));
+ assertEquals(encoded, encoding.encode(getBytes(decoded)));
+ }
+
+ private static void testEncodesWithOffset(
+ BaseEncoding encoding, String decoded, int offset, int len, String encoded) {
+ assertEquals(encoded, encoding.encode(getBytes(decoded), offset, len));
}
private static void testDecodes(BaseEncoding encoding, String encoded, String decoded) {
- byte[] bytes;
- try {
- // GWT does not support String.getBytes(Charset)
- bytes = decoded.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError();
- }
- assertEquals(bytes, encoding.decode(encoded));
+ assertEquals(getBytes(decoded), encoding.decode(encoded));
}
private static void assertFailsToDecode(BaseEncoding encoding, String cannotDecode) {
+ assertFailsToDecode(encoding, cannotDecode, null);
+ }
+
+ private static void assertFailsToDecode(
+ BaseEncoding encoding, String cannotDecode, @Nullable String expectedMessage) {
try {
encoding.decode(cannotDecode);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {
- // success
+ if (expectedMessage != null) {
+ assertThat(expected.getCause()).hasMessage(expectedMessage);
+ }
}
try {
encoding.decodeChecked(cannotDecode);
fail("Expected DecodingException");
} catch (DecodingException expected) {
- // success
+ if (expectedMessage != null) {
+ assertThat(expected).hasMessage(expectedMessage);
+ }
}
}
@@ -400,16 +446,9 @@ public class BaseEncodingTest extends TestCase {
@GwtIncompatible("Writer")
private static void testStreamingEncodes(BaseEncoding encoding, String decoded, String encoded)
throws IOException {
- byte[] bytes;
- try {
- // GWT does not support String.getBytes(Charset)
- bytes = decoded.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError();
- }
StringWriter writer = new StringWriter();
OutputStream encodingStream = encoding.encodingStream(writer);
- encodingStream.write(bytes);
+ encodingStream.write(getBytes(decoded));
encodingStream.close();
assertEquals(encoded, writer.toString());
}
@@ -417,13 +456,7 @@ public class BaseEncodingTest extends TestCase {
@GwtIncompatible("Reader")
private static void testStreamingDecodes(BaseEncoding encoding, String encoded, String decoded)
throws IOException {
- byte[] bytes;
- try {
- // GWT does not support String.getBytes(Charset)
- bytes = decoded.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError();
- }
+ byte[] bytes = getBytes(decoded);
InputStream decodingStream = encoding.decodingStream(new StringReader(encoded));
for (int i = 0; i < bytes.length; i++) {
assertEquals(bytes[i] & 0xFF, decodingStream.read());
@@ -432,6 +465,15 @@ public class BaseEncodingTest extends TestCase {
decodingStream.close();
}
+ private static byte[] getBytes(String decoded) {
+ try {
+ // GWT does not support String.getBytes(Charset)
+ return decoded.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new AssertionError();
+ }
+ }
+
public void testToString() {
assertEquals("BaseEncoding.base64().withPadChar(=)", BaseEncoding.base64().toString());
assertEquals("BaseEncoding.base32Hex().omitPadding()",
diff --git a/guava-tests/test/com/google/common/io/ByteSinkTester.java b/guava-tests/test/com/google/common/io/ByteSinkTester.java
index a743be5..47b64bc 100644
--- a/guava-tests/test/com/google/common/io/ByteSinkTester.java
+++ b/guava-tests/test/com/google/common/io/ByteSinkTester.java
@@ -38,6 +38,7 @@ import java.util.Map;
*
* @author Colin Decker
*/
+ at SuppressUnderAndroid // Android doesn't understand tests that lack default constructors.
public class ByteSinkTester extends SourceSinkTester<ByteSink, byte[], ByteSinkFactory> {
private static final ImmutableList<Method> testMethods
diff --git a/guava-tests/test/com/google/common/io/ByteSourceTest.java b/guava-tests/test/com/google/common/io/ByteSourceTest.java
index 24aaeed..2f12ced 100644
--- a/guava-tests/test/com/google/common/io/ByteSourceTest.java
+++ b/guava-tests/test/com/google/common/io/ByteSourceTest.java
@@ -30,15 +30,16 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.hash.Hashing;
+import com.google.common.primitives.UnsignedBytes;
import com.google.common.testing.TestLogHandler;
import junit.framework.TestSuite;
import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.Arrays;
import java.util.EnumSet;
/**
@@ -48,6 +49,7 @@ import java.util.EnumSet;
*/
public class ByteSourceTest extends IoTestCase {
+ @SuppressUnderAndroid // Android doesn't understand suites whose tests lack default constructors.
public static TestSuite suite() {
TestSuite suite = new TestSuite();
suite.addTest(ByteSourceTester.tests("ByteSource.wrap[byte[]]",
@@ -209,11 +211,78 @@ public class ByteSourceTest extends IoTestCase {
assertCorrectSlice(100, 5, 100, 95);
assertCorrectSlice(100, 100, 0, 0);
assertCorrectSlice(100, 100, 10, 0);
+ assertCorrectSlice(100, 101, 10, 0);
+ }
- try {
- assertCorrectSlice(100, 101, 10, 0);
- fail();
- } catch (EOFException expected) {
+ /**
+ * Tests that the default slice() behavior is correct when the source is sliced starting at an
+ * offset that is greater than the current length of the source, a stream is then opened to that
+ * source, and finally additional bytes are appended to the source before the stream is read.
+ *
+ * <p>Without special handling, it's possible to have reads of the open stream start <i>before</i>
+ * the offset at which the slice is supposed to start.
+ */
+ // TODO(cgdecker): Maybe add a test for this to ByteSourceTester
+ public void testSlice_appendingAfterSlicing() throws IOException {
+ // Source of length 5
+ AppendableByteSource source = new AppendableByteSource(newPreFilledByteArray(5));
+
+ // Slice it starting at offset 10.
+ ByteSource slice = source.slice(10, 5);
+
+ // Open a stream to the slice.
+ InputStream in = slice.openStream();
+
+ // Append 10 more bytes to the source.
+ source.append(newPreFilledByteArray(5, 10));
+
+ // The stream reports no bytes... importantly, it doesn't read the byte at index 5 when it
+ // should be reading the byte at index 10.
+ // We could use a custom InputStream instead to make the read start at index 10, but since this
+ // is a racy situation anyway, this behavior seems reasonable.
+ assertEquals(-1, in.read());
+ }
+
+ private static class AppendableByteSource extends ByteSource {
+ private byte[] bytes;
+
+ public AppendableByteSource(byte[] initialBytes) {
+ this.bytes = initialBytes.clone();
+ }
+
+ @Override
+ public InputStream openStream() {
+ return new In();
+ }
+
+ public void append(byte[] b) {
+ byte[] newBytes = Arrays.copyOf(bytes, bytes.length + b.length);
+ System.arraycopy(b, 0, newBytes, bytes.length, b.length);
+ bytes = newBytes;
+ }
+
+ private class In extends InputStream {
+ private int pos;
+
+ @Override
+ public int read() throws IOException {
+ byte[] b = new byte[1];
+ return read(b) == -1
+ ? -1
+ : UnsignedBytes.toInt(b[0]);
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) {
+ if (pos >= bytes.length) {
+ return -1;
+ }
+
+ int lenToRead = Math.min(len, bytes.length - pos);
+ System.arraycopy(bytes, pos, b, off, lenToRead);
+ pos += lenToRead;
+ return lenToRead;
+ }
}
}
diff --git a/guava-tests/test/com/google/common/io/ByteSourceTester.java b/guava-tests/test/com/google/common/io/ByteSourceTester.java
index f9a735e..6b4833a 100644
--- a/guava-tests/test/com/google/common/io/ByteSourceTester.java
+++ b/guava-tests/test/com/google/common/io/ByteSourceTester.java
@@ -21,6 +21,7 @@ import static com.google.common.io.SourceSinkFactory.CharSourceFactory;
import static org.junit.Assert.assertArrayEquals;
import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
@@ -44,6 +45,7 @@ import java.util.Random;
*
* @author Colin Decker
*/
+ at SuppressUnderAndroid // Android doesn't understand tests that lack default constructors.
public class ByteSourceTester extends SourceSinkTester<ByteSource, byte[], ByteSourceFactory> {
private static final ImmutableList<Method> testMethods
@@ -85,8 +87,22 @@ public class ByteSourceTester extends SourceSinkTester<ByteSource, byte[], ByteS
// if expected.length == 0, off has to be 0 but length doesn't matter--result will be empty
int off = expected.length == 0 ? 0 : random.nextInt(expected.length);
int len = expected.length == 0 ? 4 : random.nextInt(expected.length - off);
+
ByteSourceFactory sliced = SourceSinkFactories.asSlicedByteSourceFactory(factory, off, len);
- suite.addTest(suiteForBytes(sliced, bytes, name + ".slice[int, int]",
+ suite.addTest(suiteForBytes(sliced, bytes, name + ".slice[long, long]",
+ desc, false));
+
+ // test a slice() of the ByteSource starting at a random offset with a length of
+ // Long.MAX_VALUE
+ ByteSourceFactory slicedLongMaxValue = SourceSinkFactories.asSlicedByteSourceFactory(
+ factory, off, Long.MAX_VALUE);
+ suite.addTest(suiteForBytes(slicedLongMaxValue, bytes, name + ".slice[long, Long.MAX_VALUE]",
+ desc, false));
+
+ // test a slice() of the ByteSource starting at an offset greater than its size
+ ByteSourceFactory slicedOffsetPastEnd = SourceSinkFactories.asSlicedByteSourceFactory(
+ factory, expected.length + 2, expected.length + 10);
+ suite.addTest(suiteForBytes(slicedOffsetPastEnd, bytes, name + ".slice[size + 2, long]",
desc, false));
}
@@ -156,6 +172,13 @@ public class ByteSourceTester extends SourceSinkTester<ByteSource, byte[], ByteS
assertEquals(expected.length, source.size());
}
+ public void testSizeIfKnown() throws IOException {
+ Optional<Long> sizeIfKnown = source.sizeIfKnown();
+ if (sizeIfKnown.isPresent()) {
+ assertEquals(expected.length, (long) sizeIfKnown.get());
+ }
+ }
+
public void testContentEquals() throws IOException {
assertTrue(source.contentEquals(new ByteSource() {
@Override
@@ -204,6 +227,17 @@ public class ByteSourceTester extends SourceSinkTester<ByteSource, byte[], ByteS
}
}
+ // Test that you can not expand the readable data in a previously sliced ByteSource.
+ public void testSlice_constrainedRange() throws IOException {
+ long size = source.read().length;
+ if (size >= 2) {
+ ByteSource sliced = source.slice(1, size - 2);
+ assertEquals(size - 2, sliced.read().length);
+ ByteSource resliced = sliced.slice(0, size - 1);
+ assertTrue(sliced.contentEquals(resliced));
+ }
+ }
+
private void assertExpectedBytes(byte[] readBytes) {
assertArrayEquals(expected, readBytes);
}
diff --git a/guava-tests/test/com/google/common/io/ByteStreamsTest.java b/guava-tests/test/com/google/common/io/ByteStreamsTest.java
index 484b48d..40df0ea 100644
--- a/guava-tests/test/com/google/common/io/ByteStreamsTest.java
+++ b/guava-tests/test/com/google/common/io/ByteStreamsTest.java
@@ -16,15 +16,20 @@
package com.google.common.io;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.base.Charsets;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
+import java.io.File;
+import java.io.FileOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.RandomAccessFile;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
@@ -48,6 +53,33 @@ public class ByteStreamsTest extends IoTestCase {
assertEquals(expected, out.toByteArray());
}
+ public void testCopyFileChannel() throws IOException {
+ final int chunkSize = 14407; // Random prime, unlikely to match any internal chunk size
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ WritableByteChannel outChannel = Channels.newChannel(out);
+
+ File testFile = createTempFile();
+ FileOutputStream fos = new FileOutputStream(testFile);
+ byte[] dummyData = newPreFilledByteArray(chunkSize);
+ try {
+ for (int i = 0; i < 500; i++) {
+ fos.write(dummyData);
+ }
+ } finally {
+ fos.close();
+ }
+ ReadableByteChannel inChannel = new RandomAccessFile(testFile, "r").getChannel();
+ try {
+ ByteStreams.copy(inChannel, outChannel);
+ } finally {
+ inChannel.close();
+ }
+ byte[] actual = out.toByteArray();
+ for (int i = 0; i < 500 * chunkSize; i += chunkSize) {
+ assertEquals(dummyData, Arrays.copyOfRange(actual, i, i + chunkSize));
+ }
+ }
+
public void testReadFully() throws IOException {
byte[] b = new byte[10];
@@ -157,7 +189,7 @@ public class ByteStreamsTest extends IoTestCase {
in.readFully(actual);
assertEquals(bytes, actual);
}
-
+
public void testNewDataInput_readFullyAndThenSome() {
ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
byte[] actual = new byte[bytes.length * 2];
@@ -165,10 +197,10 @@ public class ByteStreamsTest extends IoTestCase {
in.readFully(actual);
fail("expected exception");
} catch (IllegalStateException ex) {
- assertTrue(ex.getCause() instanceof EOFException);
+ assertThat(ex.getCause()).isInstanceOf(EOFException.class);
}
}
-
+
public void testNewDataInput_readFullyWithOffset() {
ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
byte[] actual = new byte[4];
@@ -178,7 +210,7 @@ public class ByteStreamsTest extends IoTestCase {
assertEquals(bytes[0], actual[2]);
assertEquals(bytes[1], actual[3]);
}
-
+
public void testNewDataInput_readLine() {
ByteArrayDataInput in = ByteStreams.newDataInput(
"This is a line\r\nThis too\rand this\nand also this".getBytes(Charsets.UTF_8));
@@ -194,7 +226,7 @@ public class ByteStreamsTest extends IoTestCase {
assertEquals(Float.intBitsToFloat(0x12345678), in.readFloat(), 0.0);
assertEquals(Float.intBitsToFloat(0x76543210), in.readFloat(), 0.0);
}
-
+
public void testNewDataInput_readDouble() {
byte[] data = {0x12, 0x34, 0x56, 0x78, 0x76, 0x54, 0x32, 0x10};
ByteArrayDataInput in = ByteStreams.newDataInput(data);
@@ -216,7 +248,7 @@ public class ByteStreamsTest extends IoTestCase {
assertEquals('e', in.readChar());
assertEquals('d', in.readChar());
}
-
+
public void testNewDataInput_readUnsignedShort() {
byte[] data = {0, 0, 0, 1, (byte) 0xFF, (byte) 0xFF, 0x12, 0x34};
ByteArrayDataInput in = ByteStreams.newDataInput(data);
@@ -225,7 +257,7 @@ public class ByteStreamsTest extends IoTestCase {
assertEquals(65535, in.readUnsignedShort());
assertEquals(0x1234, in.readUnsignedShort());
}
-
+
public void testNewDataInput_readLong() {
byte[] data = {0x12, 0x34, 0x56, 0x78, 0x76, 0x54, 0x32, 0x10};
ByteArrayDataInput in = ByteStreams.newDataInput(data);
@@ -236,7 +268,7 @@ public class ByteStreamsTest extends IoTestCase {
ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
assertTrue(in.readBoolean());
}
-
+
public void testNewDataInput_readByte() {
ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
for (int i = 0; i < bytes.length; i++) {
@@ -246,7 +278,7 @@ public class ByteStreamsTest extends IoTestCase {
in.readByte();
fail("expected exception");
} catch (IllegalStateException ex) {
- assertTrue(ex.getCause() instanceof EOFException);
+ assertThat(ex.getCause()).isInstanceOf(EOFException.class);
}
}
@@ -259,7 +291,7 @@ public class ByteStreamsTest extends IoTestCase {
in.readUnsignedByte();
fail("expected exception");
} catch (IllegalStateException ex) {
- assertTrue(ex.getCause() instanceof EOFException);
+ assertThat(ex.getCause()).isInstanceOf(EOFException.class);
}
}
@@ -344,6 +376,7 @@ public class ByteStreamsTest extends IoTestCase {
assertEquals(new byte[] {0, 97}, out.toByteArray());
}
+ @SuppressUnderAndroid // TODO(cpovirk): Zero is found at beginning instead of end. Why?
public void testNewDataOutput_writeChars() {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeChars("r\u00C9sum\u00C9");
@@ -455,7 +488,7 @@ public class ByteStreamsTest extends IoTestCase {
}
public void testByteProcessorStopEarly() throws IOException {
- byte[] array = newPreFilledByteArray(6000);
+ byte[] array = newPreFilledByteArray(10000);
assertEquals((Integer) 42,
ByteStreams.readBytes(new ByteArrayInputStream(array),
new ByteProcessor<Integer>() {
@@ -463,7 +496,7 @@ public class ByteStreamsTest extends IoTestCase {
public boolean processBytes(byte[] buf, int off, int len) {
assertEquals(
copyOfRange(buf, off, off + len),
- newPreFilledByteArray(4096));
+ newPreFilledByteArray(8192));
return false;
}
@@ -554,7 +587,7 @@ public class ByteStreamsTest extends IoTestCase {
lin.skip(3);
assertEquals(0, lin.available());
}
-
+
public void testLimit_markNotSet() {
byte[] big = newPreFilledByteArray(5);
InputStream bin = new ByteArrayInputStream(big);
@@ -564,10 +597,10 @@ public class ByteStreamsTest extends IoTestCase {
lin.reset();
fail();
} catch (IOException expected) {
- assertEquals("Mark not set", expected.getMessage());
+ assertThat(expected).hasMessage("Mark not set");
}
}
-
+
public void testLimit_markNotSupported() {
InputStream lin = ByteStreams.limit(new UnmarkableInputStream(), 2);
@@ -575,7 +608,7 @@ public class ByteStreamsTest extends IoTestCase {
lin.reset();
fail();
} catch (IOException expected) {
- assertEquals("Mark not supported", expected.getMessage());
+ assertThat(expected).hasMessage("Mark not supported");
}
}
@@ -599,7 +632,8 @@ public class ByteStreamsTest extends IoTestCase {
return out;
}
+ // TODO(cpovirk): Inline this.
private static void assertEquals(byte[] expected, byte[] actual) {
- assertTrue(Arrays.equals(expected, actual));
+ assertThat(actual).isEqualTo(expected);
}
}
diff --git a/guava-tests/test/com/google/common/io/CharSinkTester.java b/guava-tests/test/com/google/common/io/CharSinkTester.java
index 9ad4175..754db61 100644
--- a/guava-tests/test/com/google/common/io/CharSinkTester.java
+++ b/guava-tests/test/com/google/common/io/CharSinkTester.java
@@ -34,6 +34,7 @@ import java.util.Map;
*
* @author Colin Decker
*/
+ at SuppressUnderAndroid // Android doesn't understand tests that lack default constructors.
public class CharSinkTester extends SourceSinkTester<CharSink, String, CharSinkFactory> {
private static final ImmutableList<Method> testMethods
diff --git a/guava-tests/test/com/google/common/io/CharSourceTest.java b/guava-tests/test/com/google/common/io/CharSourceTest.java
index 4fa5b86..804dcdf 100644
--- a/guava-tests/test/com/google/common/io/CharSourceTest.java
+++ b/guava-tests/test/com/google/common/io/CharSourceTest.java
@@ -44,13 +44,14 @@ import java.util.List;
*/
public class CharSourceTest extends IoTestCase {
+ @SuppressUnderAndroid // Android doesn't understand suites whose tests lack default constructors.
public static TestSuite suite() {
TestSuite suite = new TestSuite();
suite.addTest(CharSourceTester.tests("CharSource.wrap[CharSequence]",
SourceSinkFactories.stringCharSourceFactory()));
suite.addTest(CharSourceTester.tests("CharSource.empty[]",
SourceSinkFactories.emptyCharSourceFactory()));
- suite.addTestSuite(CharStreamsTest.class);
+ suite.addTestSuite(CharSourceTest.class);
return suite;
}
@@ -229,7 +230,7 @@ public class CharSourceTest extends IoTestCase {
String expected = "abcdabcd";
// read the first 8 chars manually, since there's no equivalent to ByteSource.slice
- // TODO(user): Add CharSource.slice?
+ // TODO(cgdecker): Add CharSource.slice?
StringBuilder builder = new StringBuilder();
Reader reader = concatenated.openStream(); // no need to worry about closing
for (int i = 0; i < 8; i++) {
diff --git a/guava-tests/test/com/google/common/io/CharSourceTester.java b/guava-tests/test/com/google/common/io/CharSourceTester.java
index f2882cd..cf83389 100644
--- a/guava-tests/test/com/google/common/io/CharSourceTester.java
+++ b/guava-tests/test/com/google/common/io/CharSourceTester.java
@@ -18,6 +18,7 @@ package com.google.common.io;
import static com.google.common.io.SourceSinkFactory.CharSourceFactory;
+import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@@ -38,6 +39,7 @@ import java.util.Map;
*
* @author Colin Decker
*/
+ at SuppressUnderAndroid // Android doesn't understand tests that lack default constructors.
public class CharSourceTester extends SourceSinkTester<CharSource, String, CharSourceFactory> {
private static final ImmutableList<Method> testMethods
@@ -142,6 +144,17 @@ public class CharSourceTester extends SourceSinkTester<CharSource, String, CharS
assertEquals(expected.isEmpty(), source.isEmpty());
}
+ public void testLength() throws IOException {
+ assertEquals(expected.length(), source.length());
+ }
+
+ public void testLengthIfKnown() throws IOException {
+ Optional<Long> lengthIfKnown = source.lengthIfKnown();
+ if (lengthIfKnown.isPresent()) {
+ assertEquals(expected.length(), (long) lengthIfKnown.get());
+ }
+ }
+
public void testReadLines_withProcessor() throws IOException {
List<String> list = source.readLines(new LineProcessor<List<String>>() {
List<String> list = Lists.newArrayList();
diff --git a/guava-tests/test/com/google/common/io/CharStreamsTest.java b/guava-tests/test/com/google/common/io/CharStreamsTest.java
index f47ce8a..3dde28a 100644
--- a/guava-tests/test/com/google/common/io/CharStreamsTest.java
+++ b/guava-tests/test/com/google/common/io/CharStreamsTest.java
@@ -42,23 +42,6 @@ public class CharStreamsTest extends IoTestCase {
assertEquals(TEXT, CharStreams.toString(new StringReader(TEXT)));
}
- public void testSkipFully_blockingRead() throws IOException {
- Reader reader = new NonSkippingReader("abcdef");
- CharStreams.skipFully(reader, 6);
- assertEquals(-1, reader.read());
- }
-
- private static class NonSkippingReader extends StringReader {
- NonSkippingReader(String s) {
- super(s);
- }
-
- @Override
- public long skip(long n) {
- return 0;
- }
- }
-
public void testReadLines() throws IOException {
List<String> lines = CharStreams.readLines(
new StringReader("a\nb\nc"));
diff --git a/guava-tests/test/com/google/common/io/CloserTest.java b/guava-tests/test/com/google/common/io/CloserTest.java
index c33a4b8..ee5ef76 100644
--- a/guava-tests/test/com/google/common/io/CloserTest.java
+++ b/guava-tests/test/com/google/common/io/CloserTest.java
@@ -16,6 +16,8 @@
package com.google.common.io;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Splitter;
@@ -50,15 +52,16 @@ public class CloserTest extends TestCase {
suppressor = new TestSuppressor();
}
+ @SuppressUnderAndroid // TODO(cpovirk): Look up Build.VERSION.SDK_INT reflectively.
public void testCreate() {
Closer closer = Closer.create();
String javaVersion = System.getProperty("java.version");
String secondPart = Iterables.get(Splitter.on('.').split(javaVersion), 1);
int versionNumber = Integer.parseInt(secondPart);
if (versionNumber < 7) {
- assertTrue(closer.suppressor instanceof Closer.LoggingSuppressor);
+ assertThat(closer.suppressor).isInstanceOf(Closer.LoggingSuppressor.class);
} else {
- assertTrue(closer.suppressor instanceof Closer.SuppressingSuppressor);
+ assertThat(closer.suppressor).isInstanceOf(Closer.SuppressingSuppressor.class);
}
}
@@ -125,7 +128,7 @@ public class CloserTest extends TestCase {
closer.close();
}
} catch (Throwable expected) {
- assertTrue(expected instanceof IOException);
+ assertThat(expected).isInstanceOf(IOException.class);
}
assertTrue(c1.isClosed());
@@ -339,7 +342,7 @@ public class CloserTest extends TestCase {
} catch (Throwable e) {
throw closer.rethrow(thrownException, IOException.class);
} finally {
- assertEquals(0, getSuppressed(thrownException).length);
+ assertThat(getSuppressed(thrownException)).isEmpty();
closer.close();
}
} catch (IOException expected) {
diff --git a/guava-tests/test/com/google/common/io/CountingInputStreamTest.java b/guava-tests/test/com/google/common/io/CountingInputStreamTest.java
index 9e06fef..e6341a6 100644
--- a/guava-tests/test/com/google/common/io/CountingInputStreamTest.java
+++ b/guava-tests/test/com/google/common/io/CountingInputStreamTest.java
@@ -16,6 +16,8 @@
package com.google.common.io;
+import static com.google.common.truth.Truth.assertThat;
+
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -90,7 +92,7 @@ public class CountingInputStreamTest extends IoTestCase {
counter.reset();
fail();
} catch (IOException expected) {
- assertEquals("Mark not set", expected.getMessage());
+ assertThat(expected).hasMessage("Mark not set");
}
}
@@ -101,7 +103,7 @@ public class CountingInputStreamTest extends IoTestCase {
counter.reset();
fail();
} catch (IOException expected) {
- assertEquals("Mark not supported", expected.getMessage());
+ assertThat(expected).hasMessage("Mark not supported");
}
}
diff --git a/guava-tests/test/com/google/common/io/FilesTest.java b/guava-tests/test/com/google/common/io/FilesTest.java
index 5a4dd68..c9055e5 100644
--- a/guava-tests/test/com/google/common/io/FilesTest.java
+++ b/guava-tests/test/com/google/common/io/FilesTest.java
@@ -50,6 +50,7 @@ import java.util.Random;
*
* @author Chris Nokleberg
*/
+
public class FilesTest extends IoTestCase {
public static TestSuite suite() {
@@ -142,7 +143,7 @@ public class FilesTest extends IoTestCase {
}
/**
- * A {@link File} that provides a specialized value for {link File#length()}.
+ * A {@link File} that provides a specialized value for {@link File#length()}.
*/
private static class BadLengthFile extends File {
@@ -416,7 +417,7 @@ public class FilesTest extends IoTestCase {
File temp = Files.createTempDir();
assertTrue(temp.exists());
assertTrue(temp.isDirectory());
- assertEquals(0, temp.listFiles().length);
+ assertThat(temp.listFiles()).isEmpty();
assertTrue(temp.delete());
}
@@ -542,7 +543,7 @@ public class FilesTest extends IoTestCase {
w.close();
Files.readLines(temp, Charsets.UTF_8, collect);
assertThat(collect.getResult())
- .has().exactly("hello", "", " world ", "").inOrder();
+ .containsExactly("hello", "", " world ", "").inOrder();
LineProcessor<List<String>> collectNonEmptyLines =
new LineProcessor<List<String>>() {
@@ -562,7 +563,7 @@ public class FilesTest extends IoTestCase {
}
};
Files.readLines(temp, Charsets.UTF_8, collectNonEmptyLines);
- assertThat(collectNonEmptyLines.getResult()).has().exactly(
+ assertThat(collectNonEmptyLines.getResult()).containsExactly(
"hello", " world ").inOrder();
assertTrue(temp.delete());
diff --git a/guava-tests/test/com/google/common/io/LittleEndianDataInputStreamTest.java b/guava-tests/test/com/google/common/io/LittleEndianDataInputStreamTest.java
index d794ad6..6dae439 100644
--- a/guava-tests/test/com/google/common/io/LittleEndianDataInputStreamTest.java
+++ b/guava-tests/test/com/google/common/io/LittleEndianDataInputStreamTest.java
@@ -16,6 +16,8 @@
package com.google.common.io;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.primitives.Bytes;
import junit.framework.TestCase;
@@ -97,7 +99,7 @@ public class LittleEndianDataInputStreamTest extends TestCase {
in.readLine();
fail();
} catch (UnsupportedOperationException expected) {
- assertEquals("readLine is not supported", expected.getMessage());
+ assertThat(expected).hasMessage("readLine is not supported");
}
}
diff --git a/guava-tests/test/com/google/common/io/ResourcesTest.java b/guava-tests/test/com/google/common/io/ResourcesTest.java
index 3bf17ac..80a21cc 100644
--- a/guava-tests/test/com/google/common/io/ResourcesTest.java
+++ b/guava-tests/test/com/google/common/io/ResourcesTest.java
@@ -41,6 +41,7 @@ import java.util.List;
*
* @author Chris Nokleberg
*/
+
public class ResourcesTest extends IoTestCase {
public static TestSuite suite() {
@@ -108,7 +109,7 @@ public class ResourcesTest extends IoTestCase {
Resources.getResource("no such resource");
fail();
} catch (IllegalArgumentException e) {
- assertEquals("resource no such resource not found.", e.getMessage());
+ assertThat(e).hasMessage("resource no such resource not found.");
}
}
@@ -123,9 +124,10 @@ public class ResourcesTest extends IoTestCase {
getClass(), "com/google/common/io/testdata/i18n.txt");
fail();
} catch (IllegalArgumentException e) {
- assertEquals("resource com/google/common/io/testdata/i18n.txt" +
- " relative to com.google.common.io.ResourcesTest not found.",
- e.getMessage());
+ assertThat(e)
+ .hasMessage(
+ "resource com/google/common/io/testdata/i18n.txt"
+ + " relative to com.google.common.io.ResourcesTest not found.");
}
}
diff --git a/guava-tests/test/com/google/common/io/SourceSinkFactories.java b/guava-tests/test/com/google/common/io/SourceSinkFactories.java
index 0165bf8..fd48fbf 100644
--- a/guava-tests/test/com/google/common/io/SourceSinkFactories.java
+++ b/guava-tests/test/com/google/common/io/SourceSinkFactories.java
@@ -152,7 +152,7 @@ public class SourceSinkFactories {
}
public static ByteSourceFactory asSlicedByteSourceFactory(final ByteSourceFactory factory,
- final int off, final int len) {
+ final long off, final long len) {
checkNotNull(factory);
return new ByteSourceFactory() {
@Override
@@ -163,7 +163,9 @@ public class SourceSinkFactories {
@Override
public byte[] getExpected(byte[] bytes) {
byte[] baseExpected = factory.getExpected(bytes);
- return Arrays.copyOfRange(baseExpected, off, Math.min(baseExpected.length, off + len));
+ int startOffset = (int) Math.min(off, baseExpected.length);
+ int actualLen = (int) Math.min(len, baseExpected.length - startOffset);
+ return Arrays.copyOfRange(baseExpected, startOffset, startOffset + actualLen);
}
@Override
diff --git a/guava-tests/test/com/google/common/io/SourceSinkTester.java b/guava-tests/test/com/google/common/io/SourceSinkTester.java
index ff3167b..878d74f 100644
--- a/guava-tests/test/com/google/common/io/SourceSinkTester.java
+++ b/guava-tests/test/com/google/common/io/SourceSinkTester.java
@@ -37,6 +37,7 @@ import java.util.List;
* @param <F> the factory type
* @author Colin Decker
*/
+ at SuppressUnderAndroid // Android doesn't understand tests that lack default constructors.
public class SourceSinkTester<S, T, F extends SourceSinkFactory<S, T>> extends TestCase {
static final String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing "
diff --git a/guava-tests/test/com/google/common/io/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/io/SuppressUnderAndroid.java
new file mode 100644
index 0000000..6613d88
--- /dev/null
+++ b/guava-tests/test/com/google/common/io/SuppressUnderAndroid.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.io;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>For more discussion, see {@linkplain com.google.common.base.SuppressUnderAndroid the
+ * documentation on another copy of this annotation}.
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/math/BigIntegerMathTest.java b/guava-tests/test/com/google/common/math/BigIntegerMathTest.java
index 7e1aa77..4eb78f7 100644
--- a/guava-tests/test/com/google/common/math/BigIntegerMathTest.java
+++ b/guava-tests/test/com/google/common/math/BigIntegerMathTest.java
@@ -367,13 +367,18 @@ public class BigIntegerMathTest extends TestCase {
}
@GwtIncompatible("TODO")
+ @SuppressUnderAndroid // TODO(cpovirk): Problem with BigIntegerMath.divide on Android?
public void testDivNonZeroExact() {
for (BigInteger p : NONZERO_BIGINTEGER_CANDIDATES) {
for (BigInteger q : NONZERO_BIGINTEGER_CANDIDATES) {
boolean dividesEvenly = p.remainder(q).equals(ZERO);
try {
- assertEquals(p, BigIntegerMath.divide(p, q, UNNECESSARY).multiply(q));
+ BigInteger quotient = BigIntegerMath.divide(p, q, UNNECESSARY);
+ BigInteger undone = quotient.multiply(q);
+ if (!p.equals(undone)) {
+ failFormat("expected %s.multiply(%s) = %s; got %s", quotient, q, p, undone);
+ }
assertTrue(dividesEvenly);
} catch (ArithmeticException e) {
assertFalse(dividesEvenly);
@@ -465,4 +470,9 @@ public class BigIntegerMathTest extends TestCase {
tester.setDefault(long.class, 1L);
tester.testAllPublicStaticMethods(BigIntegerMath.class);
}
+
+ @GwtIncompatible("String.format")
+ private static void failFormat(String template, Object... args) {
+ fail(String.format(template, args));
+ }
}
diff --git a/guava-tests/test/com/google/common/math/DoubleUtilsTest.java b/guava-tests/test/com/google/common/math/DoubleUtilsTest.java
index 65952aa..6f241e7 100644
--- a/guava-tests/test/com/google/common/math/DoubleUtilsTest.java
+++ b/guava-tests/test/com/google/common/math/DoubleUtilsTest.java
@@ -32,15 +32,23 @@ import java.math.BigInteger;
* @author Louis Wasserman
*/
public class DoubleUtilsTest extends TestCase {
+ @SuppressUnderAndroid // no FpUtils
public void testNextDown() {
for (double d : FINITE_DOUBLE_CANDIDATES) {
assertEquals(FpUtils.nextDown(d), DoubleUtils.nextDown(d));
}
}
+ @SuppressUnderAndroid // TODO(cpovirk): File bug for BigDecimal.doubleValue().
public void testBigToDouble() {
for (BigInteger b : ALL_BIGINTEGER_CANDIDATES) {
- assertEquals(b.doubleValue(), DoubleUtils.bigToDouble(b));
+ if (b.doubleValue() != DoubleUtils.bigToDouble(b)) {
+ failFormat(
+ "Converting %s to double: expected doubleValue %s but got bigToDouble %s",
+ b,
+ b.doubleValue(),
+ DoubleUtils.bigToDouble(b));
+ }
}
}
@@ -58,4 +66,8 @@ public class DoubleUtilsTest extends TestCase {
} catch (IllegalArgumentException expected) {
}
}
+
+ private static void failFormat(String template, Object... args) {
+ fail(String.format(template, args));
+ }
}
diff --git a/guava-tests/test/com/google/common/math/LongMathTest.java b/guava-tests/test/com/google/common/math/LongMathTest.java
index d3ac668..f29d94b 100644
--- a/guava-tests/test/com/google/common/math/LongMathTest.java
+++ b/guava-tests/test/com/google/common/math/LongMathTest.java
@@ -16,7 +16,6 @@
package com.google.common.math;
-import static com.google.common.math.MathTesting.ALL_INTEGER_CANDIDATES;
import static com.google.common.math.MathTesting.ALL_LONG_CANDIDATES;
import static com.google.common.math.MathTesting.ALL_ROUNDING_MODES;
import static com.google.common.math.MathTesting.ALL_SAFE_ROUNDING_MODES;
@@ -252,12 +251,14 @@ public class LongMathTest extends TestCase {
public void testLog10Exact() {
for (long x : POSITIVE_LONG_CANDIDATES) {
int floor = LongMath.log10(x, FLOOR);
- boolean expectSuccess = LongMath.pow(10, floor) == x;
+ boolean expectedSuccess = LongMath.pow(10, floor) == x;
try {
assertEquals(floor, LongMath.log10(x, UNNECESSARY));
- assertTrue(expectSuccess);
+ assertTrue(expectedSuccess);
} catch (ArithmeticException e) {
- assertFalse(expectSuccess);
+ if (expectedSuccess) {
+ failFormat("expected log10(%s, UNNECESSARY) = %s; got ArithmeticException", x, floor);
+ }
}
}
}
@@ -322,29 +323,37 @@ public class LongMathTest extends TestCase {
}
@GwtIncompatible("TODO")
+ @SuppressUnderAndroid // TODO(cpovirk): File BigDecimal.divide() rounding bug.
public void testDivNonZero() {
for (long p : NONZERO_LONG_CANDIDATES) {
for (long q : NONZERO_LONG_CANDIDATES) {
for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
long expected =
new BigDecimal(valueOf(p)).divide(new BigDecimal(valueOf(q)), 0, mode).longValue();
- assertEquals(expected, LongMath.divide(p, q, mode));
+ long actual = LongMath.divide(p, q, mode);
+ if (expected != actual) {
+ failFormat("expected divide(%s, %s, %s) = %s; got %s", p, q, mode, expected, actual);
+ }
}
}
}
}
@GwtIncompatible("TODO")
+ @SuppressUnderAndroid // TODO(cpovirk): Problem with LongMath.divide on Android?
public void testDivNonZeroExact() {
for (long p : NONZERO_LONG_CANDIDATES) {
for (long q : NONZERO_LONG_CANDIDATES) {
- boolean dividesEvenly = (p % q) == 0L;
+ boolean expectedSuccess = (p % q) == 0L;
try {
assertEquals(p, LongMath.divide(p, q, UNNECESSARY) * q);
- assertTrue(dividesEvenly);
+ assertTrue(expectedSuccess);
} catch (ArithmeticException e) {
- assertFalse(dividesEvenly);
+ if (expectedSuccess) {
+ failFormat(
+ "expected divide(%s, %s, UNNECESSARY) to succeed; got ArithmeticException", p, q);
+ }
}
}
}
@@ -474,15 +483,18 @@ public class LongMathTest extends TestCase {
@GwtIncompatible("TODO")
public void testCheckedAdd() {
- for (long a : ALL_INTEGER_CANDIDATES) {
- for (long b : ALL_INTEGER_CANDIDATES) {
+ for (long a : ALL_LONG_CANDIDATES) {
+ for (long b : ALL_LONG_CANDIDATES) {
BigInteger expectedResult = valueOf(a).add(valueOf(b));
boolean expectedSuccess = fitsInLong(expectedResult);
try {
assertEquals(a + b, LongMath.checkedAdd(a, b));
assertTrue(expectedSuccess);
} catch (ArithmeticException e) {
- assertFalse(expectedSuccess);
+ if (expectedSuccess) {
+ failFormat(
+ "expected checkedAdd(%s, %s) = %s; got ArithmeticException", a, b, expectedResult);
+ }
}
}
}
@@ -490,31 +502,44 @@ public class LongMathTest extends TestCase {
@GwtIncompatible("TODO")
public void testCheckedSubtract() {
- for (long a : ALL_INTEGER_CANDIDATES) {
- for (long b : ALL_INTEGER_CANDIDATES) {
+ for (long a : ALL_LONG_CANDIDATES) {
+ for (long b : ALL_LONG_CANDIDATES) {
BigInteger expectedResult = valueOf(a).subtract(valueOf(b));
boolean expectedSuccess = fitsInLong(expectedResult);
try {
assertEquals(a - b, LongMath.checkedSubtract(a, b));
assertTrue(expectedSuccess);
} catch (ArithmeticException e) {
- assertFalse(expectedSuccess);
+ if (expectedSuccess) {
+ failFormat(
+ "expected checkedSubtract(%s, %s) = %s; got ArithmeticException",
+ a,
+ b,
+ expectedResult);
+ }
}
}
}
}
@GwtIncompatible("TODO")
+ @SuppressUnderAndroid // TODO(cpovirk): Problem with LongMath.checkedMultiply on Android?
public void testCheckedMultiply() {
- for (long a : ALL_INTEGER_CANDIDATES) {
- for (long b : ALL_INTEGER_CANDIDATES) {
+ for (long a : ALL_LONG_CANDIDATES) {
+ for (long b : ALL_LONG_CANDIDATES) {
BigInteger expectedResult = valueOf(a).multiply(valueOf(b));
boolean expectedSuccess = fitsInLong(expectedResult);
try {
assertEquals(a * b, LongMath.checkedMultiply(a, b));
assertTrue(expectedSuccess);
} catch (ArithmeticException e) {
- assertFalse(expectedSuccess);
+ if (expectedSuccess) {
+ failFormat(
+ "expected checkedMultiply(%s, %s) = %s; got ArithmeticException",
+ a,
+ b,
+ expectedResult);
+ }
}
}
}
@@ -522,7 +547,7 @@ public class LongMathTest extends TestCase {
@GwtIncompatible("TODO")
public void testCheckedPow() {
- for (long b : ALL_INTEGER_CANDIDATES) {
+ for (long b : ALL_LONG_CANDIDATES) {
for (int exp : EXPONENTS) {
BigInteger expectedResult = valueOf(b).pow(exp);
boolean expectedSuccess = fitsInLong(expectedResult);
@@ -530,7 +555,13 @@ public class LongMathTest extends TestCase {
assertEquals(expectedResult.longValue(), LongMath.checkedPow(b, exp));
assertTrue(expectedSuccess);
} catch (ArithmeticException e) {
- assertFalse(expectedSuccess);
+ if (expectedSuccess) {
+ failFormat(
+ "expected checkedPow(%s, %s) = %s; got ArithmeticException",
+ b,
+ exp,
+ expectedResult);
+ }
}
}
}
@@ -693,4 +724,9 @@ public class LongMathTest extends TestCase {
tester.setDefault(long.class, 1L);
tester.testAllPublicStaticMethods(LongMath.class);
}
+
+ @GwtIncompatible("String.format")
+ private static void failFormat(String template, Object... args) {
+ fail(String.format(template, args));
+ }
}
diff --git a/guava-tests/test/com/google/common/math/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/math/SuppressUnderAndroid.java
new file mode 100644
index 0000000..c6b7af0
--- /dev/null
+++ b/guava-tests/test/com/google/common/math/SuppressUnderAndroid.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.math;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>For more discussion, see {@linkplain com.google.common.base.SuppressUnderAndroid the
+ * documentation on another copy of this annotation}.
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/net/HostSpecifierTest.java b/guava-tests/test/com/google/common/net/HostSpecifierTest.java
index 12c7631..439bae6 100644
--- a/guava-tests/test/com/google/common/net/HostSpecifierTest.java
+++ b/guava-tests/test/com/google/common/net/HostSpecifierTest.java
@@ -16,6 +16,8 @@
package com.google.common.net;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.collect.ImmutableList;
import com.google.common.testing.EqualsTester;
import com.google.common.testing.NullPointerTester;
@@ -112,7 +114,7 @@ public final class HostSpecifierTest extends TestCase {
HostSpecifier.from(spec);
fail("Should have thrown ParseException: " + spec);
} catch (ParseException expected) {
- assertTrue(expected.getCause() instanceof IllegalArgumentException);
+ assertThat(expected.getCause()).isInstanceOf(IllegalArgumentException.class);
}
assertFalse(HostSpecifier.isValid(spec));
diff --git a/guava-tests/test/com/google/common/net/InetAddressesTest.java b/guava-tests/test/com/google/common/net/InetAddressesTest.java
index 7978155..f5f2fb5 100644
--- a/guava-tests/test/com/google/common/net/InetAddressesTest.java
+++ b/guava-tests/test/com/google/common/net/InetAddressesTest.java
@@ -16,6 +16,8 @@
package com.google.common.net;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.testing.NullPointerTester;
import junit.framework.TestCase;
@@ -387,26 +389,26 @@ public class InetAddressesTest extends TestCase {
String mappedStr = "::ffff:192.168.0.1";
assertTrue(InetAddresses.isMappedIPv4Address(mappedStr));
InetAddress mapped = InetAddresses.forString(mappedStr);
- assertFalse(mapped instanceof Inet6Address);
+ assertThat(mapped).isNotInstanceOf(Inet6Address.class);
assertEquals(InetAddress.getByName("192.168.0.1"), mapped);
// check upper case
mappedStr = "::FFFF:192.168.0.1";
assertTrue(InetAddresses.isMappedIPv4Address(mappedStr));
mapped = InetAddresses.forString(mappedStr);
- assertFalse(mapped instanceof Inet6Address);
+ assertThat(mapped).isNotInstanceOf(Inet6Address.class);
assertEquals(InetAddress.getByName("192.168.0.1"), mapped);
mappedStr = "0:00:000:0000:0:ffff:1.2.3.4";
assertTrue(InetAddresses.isMappedIPv4Address(mappedStr));
mapped = InetAddresses.forString(mappedStr);
- assertFalse(mapped instanceof Inet6Address);
+ assertThat(mapped).isNotInstanceOf(Inet6Address.class);
assertEquals(InetAddress.getByName("1.2.3.4"), mapped);
mappedStr = "::ffff:0102:0304";
assertTrue(InetAddresses.isMappedIPv4Address(mappedStr));
mapped = InetAddresses.forString(mappedStr);
- assertFalse(mapped instanceof Inet6Address);
+ assertThat(mapped).isNotInstanceOf(Inet6Address.class);
assertEquals(InetAddress.getByName("1.2.3.4"), mapped);
assertFalse(InetAddresses.isMappedIPv4Address("::"));
diff --git a/guava-tests/test/com/google/common/net/InternetDomainNameTest.java b/guava-tests/test/com/google/common/net/InternetDomainNameTest.java
index 91a4347..3df6977 100644
--- a/guava-tests/test/com/google/common/net/InternetDomainNameTest.java
+++ b/guava-tests/test/com/google/common/net/InternetDomainNameTest.java
@@ -111,7 +111,7 @@ public final class InternetDomainNameTest extends TestCase {
);
private static final ImmutableSet<String> NO_PS = ImmutableSet.of(
- "www", "foo.google", "x.y.z");
+ "www", "foo.ihopethiswillneverbeapublicsuffix", "x.y.z");
private static final ImmutableSet<String> NON_PS = ImmutableSet.of(
"foo.bar.com", "foo.ca", "foo.bar.ca",
diff --git a/guava-tests/test/com/google/common/net/MediaTypeTest.java b/guava-tests/test/com/google/common/net/MediaTypeTest.java
index 12efed6..bfbc1c6 100644
--- a/guava-tests/test/com/google/common/net/MediaTypeTest.java
+++ b/guava-tests/test/com/google/common/net/MediaTypeTest.java
@@ -27,12 +27,12 @@ import static com.google.common.net.MediaType.ANY_VIDEO_TYPE;
import static com.google.common.net.MediaType.HTML_UTF_8;
import static com.google.common.net.MediaType.JPEG;
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
+import static com.google.common.truth.Truth.assertThat;
import static java.lang.reflect.Modifier.isFinal;
import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isStatic;
import static java.util.Arrays.asList;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
@@ -57,7 +57,6 @@ import java.nio.charset.UnsupportedCharsetException;
*
* @author Gregory Kick
*/
- at Beta
@GwtCompatible(emulated = true)
public class MediaTypeTest extends TestCase {
@GwtIncompatible("reflection") public void testParse_useConstants() throws Exception {
@@ -77,9 +76,9 @@ public class MediaTypeTest extends TestCase {
for (Field field : getConstantFields()) {
Optional<Charset> charset = ((MediaType) field.get(null)).charset();
if (field.getName().endsWith("_UTF_8")) {
- assertEquals(Optional.of(UTF_8), charset);
+ assertThat(charset).hasValue(UTF_8);
} else {
- assertEquals(Optional.absent(), charset);
+ assertThat(charset).isAbsent();
}
}
}
@@ -333,14 +332,13 @@ public class MediaTypeTest extends TestCase {
}
public void testGetCharset() {
- assertEquals(Optional.absent(), MediaType.parse("text/plain").charset());
- assertEquals(Optional.of(UTF_8),
- MediaType.parse("text/plain; charset=utf-8").charset());
+ assertThat(MediaType.parse("text/plain").charset()).isAbsent();
+ assertThat(MediaType.parse("text/plain; charset=utf-8").charset()).hasValue(UTF_8);
}
- @GwtIncompatible("Non-UTF-8 Charset") public void testGetCharset_utf16() {
- assertEquals(Optional.of(UTF_16),
- MediaType.parse("text/plain; charset=utf-16").charset());
+ @GwtIncompatible("Non-UTF-8 Charset")
+ public void testGetCharset_utf16() {
+ assertThat(MediaType.parse("text/plain; charset=utf-16").charset()).hasValue(UTF_16);
}
public void testGetCharset_tooMany() {
diff --git a/guava-tests/test/com/google/common/net/PercentEscaperTest.java b/guava-tests/test/com/google/common/net/PercentEscaperTest.java
index 65425d3..7acdd41 100644
--- a/guava-tests/test/com/google/common/net/PercentEscaperTest.java
+++ b/guava-tests/test/com/google/common/net/PercentEscaperTest.java
@@ -19,6 +19,7 @@ package com.google.common.net;
import static com.google.common.escape.testing.EscaperAsserts.assertEscaping;
import static com.google.common.escape.testing.EscaperAsserts.assertUnescaped;
import static com.google.common.escape.testing.EscaperAsserts.assertUnicodeEscaping;
+import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Preconditions;
@@ -124,7 +125,7 @@ public class PercentEscaperTest extends TestCase {
new PercentEscaper("-+#abc.!", false);
fail(msg);
} catch (IllegalArgumentException expected) {
- assertEquals(msg, expected.getMessage());
+ assertThat(expected).hasMessage(msg);
}
}
@@ -144,7 +145,7 @@ public class PercentEscaperTest extends TestCase {
new PercentEscaper(" ", true);
fail(msg);
} catch (IllegalArgumentException expected) {
- assertEquals(msg, expected.getMessage());
+ assertThat(expected).hasMessage(msg);
}
}
diff --git a/guava-tests/test/com/google/common/primitives/BooleansTest.java b/guava-tests/test/com/google/common/primitives/BooleansTest.java
index e7610ff..d23e979 100644
--- a/guava-tests/test/com/google/common/primitives/BooleansTest.java
+++ b/guava-tests/test/com/google/common/primitives/BooleansTest.java
@@ -123,6 +123,7 @@ public class BooleansTest extends TestCase {
Booleans.ensureCapacity(new boolean[] {true}, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Booleans.ensureCapacity(ARRAY_FALSE, -1, 1);
@@ -202,6 +203,7 @@ public class BooleansTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Boolean> list = Arrays.asList(false, true, null);
try {
diff --git a/guava-tests/test/com/google/common/primitives/BytesTest.java b/guava-tests/test/com/google/common/primitives/BytesTest.java
index e268427..ca6b201 100644
--- a/guava-tests/test/com/google/common/primitives/BytesTest.java
+++ b/guava-tests/test/com/google/common/primitives/BytesTest.java
@@ -145,6 +145,7 @@ public class BytesTest extends TestCase {
Bytes.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Bytes.ensureCapacity(ARRAY1, -1, 1);
@@ -191,6 +192,7 @@ public class BytesTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Byte> list = Arrays.asList((byte) 0, (byte) 1, null);
try {
diff --git a/guava-tests/test/com/google/common/primitives/CharsTest.java b/guava-tests/test/com/google/common/primitives/CharsTest.java
index e6d7439..2dab40f 100644
--- a/guava-tests/test/com/google/common/primitives/CharsTest.java
+++ b/guava-tests/test/com/google/common/primitives/CharsTest.java
@@ -29,6 +29,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.Locale;
/**
* Unit test for {@link Chars}.
@@ -75,6 +76,7 @@ public class CharsTest extends TestCase {
assertEquals(LEAST, Chars.saturatedCast(Long.MIN_VALUE));
}
+ @SuppressWarnings("CheckReturnValue")
private void assertCastFails(long value) {
try {
Chars.checkedCast(value);
@@ -168,6 +170,7 @@ public class CharsTest extends TestCase {
(char) 3));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
Chars.max();
@@ -184,6 +187,7 @@ public class CharsTest extends TestCase {
(char) 5, (char) 3, (char) 0, (char) 9));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
Chars.min();
@@ -221,7 +225,11 @@ public class CharsTest extends TestCase {
new byte[] {0x23, 0x45, (byte) 0xDC}));
assertEquals('\uFEDC', Chars.fromByteArray(
new byte[] {(byte) 0xFE, (byte) 0xDC}));
+ }
+ @SuppressWarnings("CheckReturnValue")
+ @GwtIncompatible("Chars.fromByteArray")
+ public void testFromByteArrayFails() {
try {
Chars.fromByteArray(new byte[Chars.BYTES - 1]);
fail();
@@ -241,7 +249,8 @@ public class CharsTest extends TestCase {
for (int hi = 0; hi < 256; hi++) {
for (int lo = 0; lo < 256; lo++) {
char result = Chars.fromByteArray(new byte[]{(byte) hi, (byte) lo});
- assertEquals(String.format("hi=%s, lo=%s, expected=%s, result=%s",
+ assertEquals(String.format(Locale.ROOT,
+ "hi=%s, lo=%s, expected=%s, result=%s",
hi, lo, (int) c, (int) result), c, result);
byte[] bytes = Chars.toByteArray(c);
@@ -252,7 +261,11 @@ public class CharsTest extends TestCase {
}
}
assertEquals((char) 0, c); // sanity check
+ }
+ @SuppressWarnings("CheckReturnValue")
+ @GwtIncompatible("Chars.fromByteArray, Chars.toByteArray")
+ public void testByteArrayRoundTripsFails() {
try {
Chars.fromByteArray(new byte[] {0x11});
fail();
@@ -269,6 +282,7 @@ public class CharsTest extends TestCase {
Chars.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Chars.ensureCapacity(ARRAY1, -1, 1);
@@ -344,6 +358,7 @@ public class CharsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Character> list = Arrays.asList((char) 0, (char) 1, null);
try {
diff --git a/guava-tests/test/com/google/common/primitives/DoublesTest.java b/guava-tests/test/com/google/common/primitives/DoublesTest.java
index 3ee962f..23fa450 100644
--- a/guava-tests/test/com/google/common/primitives/DoublesTest.java
+++ b/guava-tests/test/com/google/common/primitives/DoublesTest.java
@@ -181,6 +181,7 @@ public class DoublesTest extends TestCase {
assertEquals(-1, Doubles.lastIndexOf(new double[] {NaN, 5.0}, NaN));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
Doubles.max();
@@ -202,6 +203,7 @@ public class DoublesTest extends TestCase {
assertTrue(Double.isNaN(Doubles.max(VALUES)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
Doubles.min();
@@ -247,6 +249,7 @@ public class DoublesTest extends TestCase {
Doubles.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Doubles.ensureCapacity(ARRAY1, -1, 1);
@@ -336,6 +339,7 @@ public class DoublesTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Double> list = Arrays.asList((double) 0, (double) 1, null);
try {
@@ -369,7 +373,7 @@ public class DoublesTest extends TestCase {
list.set(0, (double) 2);
assertTrue(Arrays.equals(new double[] {(double) 2, (double) 1}, array));
array[1] = (double) 3;
- assertThat(list).has().exactly((double) 2, (double) 3).inOrder();
+ assertThat(list).containsExactly((double) 2, (double) 3).inOrder();
}
public void testAsList_toArray_roundTrip() {
@@ -418,14 +422,24 @@ public class DoublesTest extends TestCase {
private static void checkTryParse(String input) {
Double expected = referenceTryParse(input);
assertEquals(expected, Doubles.tryParse(input));
- assertEquals(expected != null,
- Doubles.FLOATING_POINT_PATTERN.matcher(input).matches());
+ if (expected != null && !Doubles.FLOATING_POINT_PATTERN.matcher(input).matches()) {
+ // TODO(cpovirk): Use SourceCodeEscapers if it is added to Guava.
+ StringBuilder escapedInput = new StringBuilder();
+ for (char c : input.toCharArray()) {
+ if (c >= 0x20 && c <= 0x7E) {
+ escapedInput.append(c);
+ } else {
+ escapedInput.append(String.format("\\u%04x", (int) c));
+ }
+ }
+ fail("FLOATING_POINT_PATTERN should have matched valid input <" + escapedInput + ">");
+ }
}
@GwtIncompatible("Doubles.tryParse")
private static void checkTryParse(double expected, String input) {
assertEquals(Double.valueOf(expected), Doubles.tryParse(input));
- assertTrue(Doubles.FLOATING_POINT_PATTERN.matcher(input).matches());
+ assertThat(input).matches(Doubles.FLOATING_POINT_PATTERN);
}
@GwtIncompatible("Doubles.tryParse")
@@ -493,7 +507,7 @@ public class DoublesTest extends TestCase {
@GwtIncompatible("Doubles.tryParse")
public void testTryParseFailures() {
for (String badInput : BAD_TRY_PARSE_INPUTS) {
- assertFalse(Doubles.FLOATING_POINT_PATTERN.matcher(badInput).matches());
+ assertThat(badInput).doesNotMatch(Doubles.FLOATING_POINT_PATTERN);
assertEquals(referenceTryParse(badInput), Doubles.tryParse(badInput));
assertNull(Doubles.tryParse(badInput));
}
@@ -516,6 +530,7 @@ public class DoublesTest extends TestCase {
assertEquals((Double) 1e-6, converter.convert("1e-6"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testStringConverter_convertError() {
try {
Doubles.stringConverter().convert("notanumber");
diff --git a/guava-tests/test/com/google/common/primitives/FloatsTest.java b/guava-tests/test/com/google/common/primitives/FloatsTest.java
index 2584328..dbbf6fa 100644
--- a/guava-tests/test/com/google/common/primitives/FloatsTest.java
+++ b/guava-tests/test/com/google/common/primitives/FloatsTest.java
@@ -179,6 +179,7 @@ public class FloatsTest extends TestCase {
assertEquals(-1, Floats.lastIndexOf(new float[] {NaN, 5f}, NaN));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
Floats.max();
@@ -200,6 +201,7 @@ public class FloatsTest extends TestCase {
assertTrue(Float.isNaN(Floats.max(VALUES)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
Floats.min();
@@ -245,6 +247,7 @@ public class FloatsTest extends TestCase {
Floats.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Floats.ensureCapacity(ARRAY1, -1, 1);
@@ -327,6 +330,7 @@ public class FloatsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Float> list = Arrays.asList((float) 0, (float) 1, null);
try {
@@ -360,7 +364,7 @@ public class FloatsTest extends TestCase {
list.set(0, (float) 2);
assertTrue(Arrays.equals(new float[] {(float) 2, (float) 1}, array));
array[1] = (float) 3;
- assertThat(list).has().exactly((float) 2, (float) 3).inOrder();
+ assertThat(list).containsExactly((float) 2, (float) 3).inOrder();
}
public void testAsList_toArray_roundTrip() {
@@ -503,6 +507,7 @@ public class FloatsTest extends TestCase {
assertEquals((Float) 1e-6f, converter.convert("1e-6"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testStringConverter_convertError() {
try {
Floats.stringConverter().convert("notanumber");
diff --git a/guava-tests/test/com/google/common/primitives/IntsTest.java b/guava-tests/test/com/google/common/primitives/IntsTest.java
index 58279e6..73b13ac 100644
--- a/guava-tests/test/com/google/common/primitives/IntsTest.java
+++ b/guava-tests/test/com/google/common/primitives/IntsTest.java
@@ -77,6 +77,7 @@ public class IntsTest extends TestCase {
assertEquals(LEAST, Ints.saturatedCast(Long.MIN_VALUE));
}
+ @SuppressWarnings("CheckReturnValue")
private static void assertCastFails(long value) {
try {
Ints.checkedCast(value);
@@ -170,6 +171,7 @@ public class IntsTest extends TestCase {
(int) 3));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
Ints.max();
@@ -186,6 +188,7 @@ public class IntsTest extends TestCase {
(int) 5, (int) 3, (int) 0, (int) 9));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
Ints.min();
@@ -232,7 +235,11 @@ public class IntsTest extends TestCase {
Ints.fromByteArray(new byte[] {0x12, 0x13, 0x14, 0x15, 0x33}));
assertEquals(0xFFEEDDCC, Ints.fromByteArray(
new byte[] {(byte) 0xFF, (byte) 0xEE, (byte) 0xDD, (byte) 0xCC}));
+ }
+ @SuppressWarnings("CheckReturnValue")
+ @GwtIncompatible("Ints.fromByteArray")
+ public void testFromByteArrayFails() {
try {
Ints.fromByteArray(new byte[Ints.BYTES - 1]);
fail();
@@ -272,6 +279,7 @@ public class IntsTest extends TestCase {
Ints.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Ints.ensureCapacity(ARRAY1, -1, 1);
@@ -353,6 +361,7 @@ public class IntsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Integer> list = Arrays.asList((int) 0, (int) 1, null);
try {
@@ -433,6 +442,7 @@ public class IntsTest extends TestCase {
assertEquals((Integer) 438, converter.convert("0666"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testStringConverter_convertError() {
try {
Ints.stringConverter().convert("notanumber");
@@ -496,4 +506,51 @@ public class IntsTest extends TestCase {
private static void tryParseAndAssertEquals(Integer expected, String value) {
assertEquals(expected, Ints.tryParse(value));
}
+
+ public void testTryParse_radix() {
+ for (int radix = Character.MIN_RADIX;
+ radix <= Character.MAX_RADIX; radix++) {
+ radixEncodeParseAndAssertEquals(0, radix);
+ radixEncodeParseAndAssertEquals(8000, radix);
+ radixEncodeParseAndAssertEquals(-8000, radix);
+ radixEncodeParseAndAssertEquals(GREATEST, radix);
+ radixEncodeParseAndAssertEquals(LEAST, radix);
+ assertNull("Radix: " + radix, Ints.tryParse("9999999999999999", radix));
+ assertNull("Radix: " + radix,
+ Ints.tryParse(Long.toString((long) GREATEST + 1, radix), radix));
+ assertNull("Radix: " + radix,
+ Ints.tryParse(Long.toString((long) LEAST - 1, radix), radix));
+ }
+ assertNull("Hex string and dec parm", Ints.tryParse("FFFF", 10));
+ assertEquals("Mixed hex case", 65535, (int) Ints.tryParse("ffFF", 16));
+ }
+
+ /**
+ * Encodes the an integer as a string with given radix, then uses
+ * {@link Ints#tryParse(String, int)} to parse the result. Asserts the result
+ * is the same as what we started with.
+ */
+ private static void radixEncodeParseAndAssertEquals(Integer value,
+ int radix) {
+ assertEquals("Radix: " + radix, value,
+ Ints.tryParse(Integer.toString(value, radix), radix));
+ }
+
+ @SuppressWarnings("CheckReturnValue")
+ public void testTryParse_radixTooBig() {
+ try {
+ Ints.tryParse("0", Character.MAX_RADIX + 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @SuppressWarnings("CheckReturnValue")
+ public void testTryParse_radixTooSmall() {
+ try {
+ Ints.tryParse("0", Character.MIN_RADIX - 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
}
diff --git a/guava-tests/test/com/google/common/primitives/LongsTest.java b/guava-tests/test/com/google/common/primitives/LongsTest.java
index 7575a14..45d4235 100644
--- a/guava-tests/test/com/google/common/primitives/LongsTest.java
+++ b/guava-tests/test/com/google/common/primitives/LongsTest.java
@@ -143,6 +143,7 @@ public class LongsTest extends TestCase {
(long) 3));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
Longs.max();
@@ -159,6 +160,7 @@ public class LongsTest extends TestCase {
(long) 5, (long) 3, (long) 0, (long) 9));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
Longs.min();
@@ -214,7 +216,10 @@ public class LongsTest extends TestCase {
new byte[] {
(byte) 0xFF, (byte) 0xEE, (byte) 0xDD, (byte) 0xCC,
(byte) 0xBB, (byte) 0xAA, (byte) 0x99, (byte) 0x88}));
+ }
+ @SuppressWarnings("CheckReturnValue")
+ public void testFromByteArrayFails() {
try {
Longs.fromByteArray(new byte[Longs.BYTES - 1]);
fail();
@@ -255,6 +260,7 @@ public class LongsTest extends TestCase {
Longs.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Longs.ensureCapacity(ARRAY1, -1, 1);
@@ -336,6 +342,7 @@ public class LongsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Long> list = Arrays.asList((long) 0, (long) 1, null);
try {
@@ -477,4 +484,50 @@ public class LongsTest extends TestCase {
private static void tryParseAndAssertEquals(Long expected, String value) {
assertEquals(expected, Longs.tryParse(value));
}
+
+ public void testTryParse_radix() {
+ for (int radix = Character.MIN_RADIX;
+ radix <= Character.MAX_RADIX; radix++) {
+ radixEncodeParseAndAssertEquals((long) 0, radix);
+ radixEncodeParseAndAssertEquals((long) 8000, radix);
+ radixEncodeParseAndAssertEquals((long) -8000, radix);
+ radixEncodeParseAndAssertEquals(MAX_VALUE, radix);
+ radixEncodeParseAndAssertEquals(MIN_VALUE, radix);
+ assertNull("Radix: " + radix, Longs.tryParse("999999999999999999999999", radix));
+ assertNull("Radix: " + radix,
+ Longs.tryParse(BigInteger.valueOf(MAX_VALUE).add(BigInteger.ONE).toString(), radix));
+ assertNull("Radix: " + radix,
+ Longs.tryParse(BigInteger.valueOf(MIN_VALUE).subtract(BigInteger.ONE).toString(), radix));
+ }
+ assertNull("Hex string and dec parm", Longs.tryParse("FFFF", 10));
+ assertEquals("Mixed hex case", 65535, Longs.tryParse("ffFF", 16).longValue());
+ }
+
+ /**
+ * Encodes the long as a string with given radix, then uses
+ * {@link Longs#tryParse(String, int)} to parse the result. Asserts the result
+ * is the same as what we started with.
+ */
+ private static void radixEncodeParseAndAssertEquals(Long value, int radix) {
+ assertEquals("Radix: " + radix, value,
+ Longs.tryParse(Long.toString(value, radix), radix));
+ }
+
+ @SuppressWarnings("CheckReturnValue")
+ public void testTryParse_radixTooBig() {
+ try {
+ Longs.tryParse("0", Character.MAX_RADIX + 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @SuppressWarnings("CheckReturnValue")
+ public void testTryParse_radixTooSmall() {
+ try {
+ Longs.tryParse("0", Character.MIN_RADIX - 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
}
diff --git a/guava-tests/test/com/google/common/primitives/ShortsTest.java b/guava-tests/test/com/google/common/primitives/ShortsTest.java
index f9b9412..b981e12 100644
--- a/guava-tests/test/com/google/common/primitives/ShortsTest.java
+++ b/guava-tests/test/com/google/common/primitives/ShortsTest.java
@@ -77,6 +77,7 @@ public class ShortsTest extends TestCase {
assertEquals(LEAST, Shorts.saturatedCast(Long.MIN_VALUE));
}
+ @SuppressWarnings("CheckReturnValue")
private static void assertCastFails(long value) {
try {
Shorts.checkedCast(value);
@@ -178,6 +179,7 @@ public class ShortsTest extends TestCase {
(short) 3));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
Shorts.max();
@@ -194,6 +196,7 @@ public class ShortsTest extends TestCase {
(short) 5, (short) 3, (short) 0, (short) 9));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
Shorts.min();
@@ -240,7 +243,11 @@ public class ShortsTest extends TestCase {
Shorts.fromByteArray(new byte[] {0x23, 0x45}));
assertEquals((short) 0xFEDC, Shorts.fromByteArray(
new byte[] {(byte) 0xFE, (byte) 0xDC}));
+ }
+ @SuppressWarnings("CheckReturnValue")
+ @GwtIncompatible("Shorts.fromByteArray")
+ public void testFromByteArrayFails() {
try {
Shorts.fromByteArray(new byte[] {0x01});
fail();
@@ -279,6 +286,7 @@ public class ShortsTest extends TestCase {
Shorts.ensureCapacity(ARRAY1, 2, 1)));
}
+ @SuppressWarnings("CheckReturnValue")
public void testEnsureCapacity_fail() {
try {
Shorts.ensureCapacity(ARRAY1, -1, 1);
@@ -360,6 +368,7 @@ public class ShortsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testToArray_withNull() {
List<Short> list = Arrays.asList((short) 0, (short) 1, null);
try {
@@ -440,6 +449,7 @@ public class ShortsTest extends TestCase {
assertEquals((Short) (short) 438, converter.convert("0666"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testStringConverter_convertError() {
try {
Shorts.stringConverter().convert("notanumber");
diff --git a/guava-tests/test/com/google/common/primitives/SignedBytesTest.java b/guava-tests/test/com/google/common/primitives/SignedBytesTest.java
index 8e205fe..b5e3dd6 100644
--- a/guava-tests/test/com/google/common/primitives/SignedBytesTest.java
+++ b/guava-tests/test/com/google/common/primitives/SignedBytesTest.java
@@ -65,6 +65,7 @@ public class SignedBytesTest extends TestCase {
assertEquals(LEAST, SignedBytes.saturatedCast(Long.MIN_VALUE));
}
+ @SuppressWarnings("CheckReturnValue")
private static void assertCastFails(long value) {
try {
SignedBytes.checkedCast(value);
@@ -94,6 +95,7 @@ public class SignedBytesTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
SignedBytes.max();
@@ -109,6 +111,7 @@ public class SignedBytesTest extends TestCase {
(byte) 0, (byte) -128, (byte) -1, (byte) 127, (byte) 1));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
SignedBytes.min();
diff --git a/guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java b/guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java
index 575eb7e..d818875 100644
--- a/guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java
+++ b/guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java
@@ -71,6 +71,7 @@ public class UnsignedBytesTest extends TestCase {
assertEquals(LEAST, UnsignedBytes.saturatedCast(Long.MIN_VALUE));
}
+ @SuppressWarnings("CheckReturnValue")
private static void assertCastFails(long value) {
try {
UnsignedBytes.checkedCast(value);
@@ -96,6 +97,7 @@ public class UnsignedBytesTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
UnsignedBytes.max();
@@ -111,6 +113,7 @@ public class UnsignedBytesTest extends TestCase {
(byte) 0, (byte) -128, (byte) -1, (byte) 127, (byte) 1));
}
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
UnsignedBytes.min();
@@ -128,6 +131,7 @@ public class UnsignedBytesTest extends TestCase {
(byte) -1, (byte) 127, (byte) 1, (byte) -128, (byte) 0));
}
+ @SuppressWarnings("CheckReturnValue")
private static void assertParseFails(String value) {
try {
UnsignedBytes.parseUnsignedByte(value);
@@ -152,6 +156,7 @@ public class UnsignedBytesTest extends TestCase {
.compare(UnsignedBytes.MAX_VALUE, (byte) (UnsignedBytes.MAX_VALUE + 1)) > 0);
}
+ @SuppressWarnings("CheckReturnValue")
private static void assertParseFails(String value, int radix) {
try {
UnsignedBytes.parseUnsignedByte(value, radix);
@@ -173,6 +178,7 @@ public class UnsignedBytesTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testParseUnsignedByteThrowsExceptionForInvalidRadix() {
// Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX,
// inclusive.
diff --git a/guava-tests/test/com/google/common/primitives/UnsignedIntsTest.java b/guava-tests/test/com/google/common/primitives/UnsignedIntsTest.java
index d1fd13c..9e2e12b 100644
--- a/guava-tests/test/com/google/common/primitives/UnsignedIntsTest.java
+++ b/guava-tests/test/com/google/common/primitives/UnsignedIntsTest.java
@@ -45,7 +45,7 @@ public class UnsignedIntsTest extends TestCase {
0xfffffffdL,
0xfffffffeL,
0xffffffffL};
-
+
private static final int LEAST = (int) 0L;
private static final int GREATEST = (int) 0xffffffffL;
@@ -64,7 +64,8 @@ public class UnsignedIntsTest extends TestCase {
}
}
}
-
+
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
UnsignedInts.max();
@@ -72,7 +73,7 @@ public class UnsignedIntsTest extends TestCase {
} catch (IllegalArgumentException expected) {
}
}
-
+
public void testMax() {
assertEquals(LEAST, UnsignedInts.max(LEAST));
assertEquals(GREATEST, UnsignedInts.max(GREATEST));
@@ -81,7 +82,8 @@ public class UnsignedIntsTest extends TestCase {
(int) 0x12345678L, (int) 0x5a4316b8L,
(int) 0xff1a618bL, (int) 0L));
}
-
+
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
UnsignedInts.min();
@@ -157,27 +159,29 @@ public class UnsignedIntsTest extends TestCase {
}
public void testParseInt() {
- try {
- for (long a : UNSIGNED_INTS) {
- assertEquals((int) a, UnsignedInts.parseUnsignedInt(Long.toString(a)));
- }
- } catch (NumberFormatException e) {
- fail(e.getMessage());
+ for (long a : UNSIGNED_INTS) {
+ assertEquals((int) a, UnsignedInts.parseUnsignedInt(Long.toString(a)));
}
+ }
+ @SuppressWarnings("CheckReturnValue")
+ public void testParseIntFail() {
try {
UnsignedInts.parseUnsignedInt(Long.toString(1L << 32));
fail("Expected NumberFormatException");
} catch (NumberFormatException expected) {}
}
- public void testParseIntWithRadix() throws NumberFormatException {
+ public void testParseIntWithRadix() {
for (long a : UNSIGNED_INTS) {
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
assertEquals((int) a, UnsignedInts.parseUnsignedInt(Long.toString(a, radix), radix));
}
}
+ }
+ @SuppressWarnings("CheckReturnValue")
+ public void testParseIntWithRadixLimits() {
// loops through all legal radix values.
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
// tests can successfully parse a number string with this radix.
@@ -194,6 +198,7 @@ public class UnsignedIntsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testParseIntThrowsExceptionForInvalidRadix() {
// Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX,
// inclusive.
@@ -224,6 +229,7 @@ public class UnsignedIntsTest extends TestCase {
assertEquals(0, UnsignedInts.decode("0"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testDecodeIntFails() {
try {
// One more than maximum value
diff --git a/guava-tests/test/com/google/common/primitives/UnsignedLongTest.java b/guava-tests/test/com/google/common/primitives/UnsignedLongTest.java
index 1df86cb..7fe6724 100644
--- a/guava-tests/test/com/google/common/primitives/UnsignedLongTest.java
+++ b/guava-tests/test/com/google/common/primitives/UnsignedLongTest.java
@@ -233,7 +233,7 @@ public class UnsignedLongTest extends TestCase {
}
}
- @SuppressWarnings("ReturnValueIgnored")
+ @SuppressWarnings("CheckReturnValue")
public void testModByZero() {
for (long a : TEST_LONGS) {
try {
diff --git a/guava-tests/test/com/google/common/primitives/UnsignedLongsTest.java b/guava-tests/test/com/google/common/primitives/UnsignedLongsTest.java
index 7abee87..e12975d 100644
--- a/guava-tests/test/com/google/common/primitives/UnsignedLongsTest.java
+++ b/guava-tests/test/com/google/common/primitives/UnsignedLongsTest.java
@@ -61,6 +61,7 @@ public class UnsignedLongsTest extends TestCase {
assertTrue(UnsignedLongs.compare(0xff1a618b7f65ea12L, 0xff1a618b7f65ea12L) == 0);
}
+ @SuppressWarnings("CheckReturnValue")
public void testMax_noArgs() {
try {
UnsignedLongs.max();
@@ -76,7 +77,8 @@ public class UnsignedLongsTest extends TestCase {
0x5a4316b8c153ac4dL, 8L, 100L,
0L, 0x6cf78a4b139a4e2aL, 0xff1a618b7f65ea12L));
}
-
+
+ @SuppressWarnings("CheckReturnValue")
public void testMin_noArgs() {
try {
UnsignedLongs.min();
@@ -150,7 +152,10 @@ public class UnsignedLongsTest extends TestCase {
assertEquals(0xff1a618b7f65ea12L, UnsignedLongs.parseUnsignedLong("18382112080831834642"));
assertEquals(0x5a4316b8c153ac4dL, UnsignedLongs.parseUnsignedLong("6504067269626408013"));
assertEquals(0x6cf78a4b139a4e2aL, UnsignedLongs.parseUnsignedLong("7851896530399809066"));
+ }
+ @SuppressWarnings("CheckReturnValue")
+ public void testParseLongFails() {
try {
// One more than maximum value
UnsignedLongs.parseUnsignedLong("18446744073709551616");
@@ -169,6 +174,7 @@ public class UnsignedLongsTest extends TestCase {
assertEquals(0L, UnsignedLongs.decode("0"));
}
+ @SuppressWarnings("CheckReturnValue")
public void testDecodeLongFails() {
try {
// One more than maximum value
@@ -199,7 +205,10 @@ public class UnsignedLongsTest extends TestCase {
public void testParseLongWithRadix() {
assertEquals(0xffffffffffffffffL, UnsignedLongs.parseUnsignedLong("ffffffffffffffff", 16));
assertEquals(0x1234567890abcdefL, UnsignedLongs.parseUnsignedLong("1234567890abcdef", 16));
+ }
+ @SuppressWarnings("CheckReturnValue")
+ public void testParseLongWithRadixLimits() {
BigInteger max = BigInteger.ZERO.setBit(64).subtract(ONE);
// loops through all legal radix values.
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
@@ -224,6 +233,7 @@ public class UnsignedLongsTest extends TestCase {
}
}
+ @SuppressWarnings("CheckReturnValue")
public void testParseLongThrowsExceptionForInvalidRadix() {
// Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX, inclusive.
try {
diff --git a/guava-tests/test/com/google/common/reflect/ClassPathTest.java b/guava-tests/test/com/google/common/reflect/ClassPathTest.java
index f492409..cafcbbf 100644
--- a/guava-tests/test/com/google/common/reflect/ClassPathTest.java
+++ b/guava-tests/test/com/google/common/reflect/ClassPathTest.java
@@ -20,13 +20,11 @@ import static com.google.common.truth.Truth.assertThat;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
import com.google.common.io.Closer;
+import com.google.common.io.Files;
import com.google.common.io.Resources;
import com.google.common.reflect.ClassPath.ClassInfo;
import com.google.common.reflect.ClassPath.ResourceInfo;
-import com.google.common.reflect.subpackage.ClassInSubPackage;
import com.google.common.testing.EqualsTester;
import com.google.common.testing.NullPointerTester;
@@ -39,13 +37,16 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
-import java.util.Map;
+import java.util.Enumeration;
+import java.util.HashSet;
import java.util.Set;
import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
@@ -56,105 +57,6 @@ import java.util.zip.ZipEntry;
*/
public class ClassPathTest extends TestCase {
- public void testGetResources() throws Exception {
- Map<String, ResourceInfo> byName = Maps.newHashMap();
- Map<String, ResourceInfo> byToString = Maps.newHashMap();
- ClassPath classpath = ClassPath.from(getClass().getClassLoader());
- for (ResourceInfo resource : classpath.getResources()) {
- assertThat(resource.getResourceName()).isNotEqualTo(JarFile.MANIFEST_NAME);
- assertThat(resource.toString()).isNotEqualTo(JarFile.MANIFEST_NAME);
- byName.put(resource.getResourceName(), resource);
- byToString.put(resource.toString(), resource);
- assertNotNull(resource.url());
- }
- String testResourceName = "com/google/common/reflect/test.txt";
- assertThat(byName.keySet()).has().allOf(
- "com/google/common/reflect/ClassPath.class",
- "com/google/common/reflect/ClassPathTest.class",
- "com/google/common/reflect/ClassPathTest$Nested.class",
- testResourceName);
- assertThat(byToString.keySet()).has().allOf(
- "com.google.common.reflect.ClassPath",
- "com.google.common.reflect.ClassPathTest",
- "com.google.common.reflect.ClassPathTest$Nested",
- testResourceName);
- assertEquals(getClass().getClassLoader().getResource(testResourceName),
- byName.get("com/google/common/reflect/test.txt").url());
- }
-
- public void testGetAllClasses() throws Exception {
- Set<String> names = Sets.newHashSet();
- Set<String> strings = Sets.newHashSet();
- Set<Class<?>> classes = Sets.newHashSet();
- Set<String> packageNames = Sets.newHashSet();
- Set<String> simpleNames = Sets.newHashSet();
- ClassPath classpath = ClassPath.from(getClass().getClassLoader());
- for (ClassInfo classInfo : classpath.getAllClasses()) {
- if (!classInfo.getPackageName().equals(ClassPathTest.class.getPackage().getName())) {
- continue;
- }
- names.add(classInfo.getName());
- strings.add(classInfo.toString());
- classes.add(classInfo.load());
- packageNames.add(classInfo.getPackageName());
- simpleNames.add(classInfo.getSimpleName());
- }
- class LocalClass {}
- Class<?> anonymousClass = new Object() {}.getClass();
- assertThat(names).has().allOf(anonymousClass.getName(), LocalClass.class.getName(),
- ClassPath.class.getName(), ClassPathTest.class.getName());
- assertThat(strings).has().allOf(anonymousClass.getName(), LocalClass.class.getName(),
- ClassPath.class.getName(), ClassPathTest.class.getName());
- assertThat(classes).has().allOf(anonymousClass, LocalClass.class, ClassPath.class,
- ClassPathTest.class);
- assertThat(packageNames).has().exactly(ClassPath.class.getPackage().getName());
- assertThat(simpleNames).has().allOf("", "Local", "ClassPath", "ClassPathTest");
- }
-
- public void testGetTopLevelClasses() throws Exception {
- Set<String> names = Sets.newHashSet();
- Set<String> strings = Sets.newHashSet();
- Set<Class<?>> classes = Sets.newHashSet();
- Set<String> packageNames = Sets.newHashSet();
- Set<String> simpleNames = Sets.newHashSet();
- ClassPath classpath = ClassPath.from(getClass().getClassLoader());
- for (ClassInfo classInfo
- : classpath.getTopLevelClasses(ClassPathTest.class.getPackage().getName())) {
- names.add(classInfo.getName());
- strings.add(classInfo.toString());
- classes.add(classInfo.load());
- packageNames.add(classInfo.getPackageName());
- simpleNames.add(classInfo.getSimpleName());
- }
- assertThat(names).has().allOf(ClassPath.class.getName(), ClassPathTest.class.getName());
- assertThat(strings).has().allOf(ClassPath.class.getName(), ClassPathTest.class.getName());
- assertThat(classes).has().allOf(ClassPath.class, ClassPathTest.class);
- assertThat(packageNames).has().item(ClassPath.class.getPackage().getName());
- assertThat(simpleNames).has().allOf("ClassPath", "ClassPathTest");
- assertFalse(classes.contains(ClassInSubPackage.class));
- }
-
- public void testGetTopLevelClassesRecursive() throws Exception {
- Set<Class<?>> classes = Sets.newHashSet();
- ClassPath classpath = ClassPath.from(ClassPathTest.class.getClassLoader());
- for (ClassInfo classInfo
- : classpath.getTopLevelClassesRecursive(ClassPathTest.class.getPackage().getName())) {
- if (classInfo.getName().contains("ClassPathTest")) {
- System.err.println("");
- }
- classes.add(classInfo.load());
- }
- assertThat(classes).has().allOf(ClassPathTest.class, ClassInSubPackage.class);
- }
-
- public void testGetTopLevelClasses_diamond() throws Exception {
- ClassLoader parent = ClassPathTest.class.getClassLoader();
- ClassLoader sub1 = new ClassLoader(parent) {};
- ClassLoader sub2 = new ClassLoader(parent) {};
- assertEquals(findClass(ClassPath.from(sub1).getTopLevelClasses(), ClassPathTest.class),
- findClass(ClassPath.from(sub2).getTopLevelClasses(), ClassPathTest.class));
- }
-
public void testEquals() {
new EqualsTester()
.addEqualityGroup(classInfo(ClassPathTest.class), classInfo(ClassPathTest.class))
@@ -167,74 +69,83 @@ public class ClassPathTest extends TestCase {
.testEquals();
}
+ @SuppressUnderAndroid // Android forbids null parent ClassLoader
public void testClassPathEntries_emptyURLClassLoader_noParent() {
- assertThat(ClassPath.getClassPathEntries(new URLClassLoader(new URL[0], null)).keySet())
+ assertThat(ClassPath.Scanner.getClassPathEntries(new URLClassLoader(new URL[0], null)).keySet())
.isEmpty();
}
+ @SuppressUnderAndroid // Android forbids null parent ClassLoader
public void testClassPathEntries_URLClassLoader_noParent() throws Exception {
URL url1 = new URL("file:/a");
URL url2 = new URL("file:/b");
URLClassLoader classloader = new URLClassLoader(new URL[] {url1, url2}, null);
assertEquals(
- ImmutableMap.of(url1.toURI(), classloader, url2.toURI(), classloader),
- ClassPath.getClassPathEntries(classloader));
+ ImmutableMap.of(new File("/a"), classloader, new File("/b"), classloader),
+ ClassPath.Scanner.getClassPathEntries(classloader));
}
+ @SuppressUnderAndroid // Android forbids null parent ClassLoader
public void testClassPathEntries_URLClassLoader_withParent() throws Exception {
URL url1 = new URL("file:/a");
URL url2 = new URL("file:/b");
URLClassLoader parent = new URLClassLoader(new URL[] {url1}, null);
URLClassLoader child = new URLClassLoader(new URL[] {url2}, parent) {};
- ImmutableMap<URI, ClassLoader> classPathEntries = ClassPath.getClassPathEntries(child);
- assertEquals(ImmutableMap.of(url1.toURI(), parent, url2.toURI(), child), classPathEntries);
- assertThat(classPathEntries.keySet()).has().exactly(url1.toURI(), url2.toURI()).inOrder();
+ ImmutableMap<File, ClassLoader> classPathEntries = ClassPath.Scanner.getClassPathEntries(child);
+ assertEquals(ImmutableMap.of(new File("/a"), parent, new File("/b"), child), classPathEntries);
+ assertThat(classPathEntries.keySet()).containsExactly(new File("/a"), new File("/b")).inOrder();
}
+ @SuppressUnderAndroid // Android forbids null parent ClassLoader
public void testClassPathEntries_duplicateUri_parentWins() throws Exception {
URL url = new URL("file:/a");
URLClassLoader parent = new URLClassLoader(new URL[] {url}, null);
URLClassLoader child = new URLClassLoader(new URL[] {url}, parent) {};
- assertEquals(ImmutableMap.of(url.toURI(), parent), ClassPath.getClassPathEntries(child));
+ assertEquals(ImmutableMap.of(new File("/a"), parent),
+ ClassPath.Scanner.getClassPathEntries(child));
}
+ @SuppressUnderAndroid // Android forbids null parent ClassLoader
public void testClassPathEntries_notURLClassLoader_noParent() {
- assertThat(ClassPath.getClassPathEntries(new ClassLoader(null) {}).keySet()).isEmpty();
+ assertThat(ClassPath.Scanner.getClassPathEntries(new ClassLoader(null) {}).keySet()).isEmpty();
}
+ @SuppressUnderAndroid // Android forbids null parent ClassLoader
public void testClassPathEntries_notURLClassLoader_withParent() throws Exception {
URL url = new URL("file:/a");
URLClassLoader parent = new URLClassLoader(new URL[] {url}, null);
assertEquals(
- ImmutableMap.of(url.toURI(), parent),
- ClassPath.getClassPathEntries(new ClassLoader(parent) {}));
+ ImmutableMap.of(new File("/a"), parent),
+ ClassPath.Scanner.getClassPathEntries(new ClassLoader(parent) {}));
}
+ @SuppressUnderAndroid // Android forbids null parent ClassLoader
public void testClassPathEntries_notURLClassLoader_withParentAndGrandParent() throws Exception {
URL url1 = new URL("file:/a");
URL url2 = new URL("file:/b");
URLClassLoader grandParent = new URLClassLoader(new URL[] {url1}, null);
URLClassLoader parent = new URLClassLoader(new URL[] {url2}, grandParent);
assertEquals(
- ImmutableMap.of(url1.toURI(), grandParent, url2.toURI(), parent),
- ClassPath.getClassPathEntries(new ClassLoader(parent) {}));
+ ImmutableMap.of(new File("/a"), grandParent, new File("/b"), parent),
+ ClassPath.Scanner.getClassPathEntries(new ClassLoader(parent) {}));
}
+ @SuppressUnderAndroid // Android forbids null parent ClassLoader
public void testClassPathEntries_notURLClassLoader_withGrandParent() throws Exception {
URL url = new URL("file:/a");
URLClassLoader grandParent = new URLClassLoader(new URL[] {url}, null);
ClassLoader parent = new ClassLoader(grandParent) {};
assertEquals(
- ImmutableMap.of(url.toURI(), grandParent),
- ClassPath.getClassPathEntries(new ClassLoader(parent) {}));
+ ImmutableMap.of(new File("/a"), grandParent),
+ ClassPath.Scanner.getClassPathEntries(new ClassLoader(parent) {}));
}
public void testScan_classPathCycle() throws IOException {
File jarFile = File.createTempFile("with_circular_class_path", ".jar");
try {
writeSelfReferencingJarFile(jarFile, "test.txt");
- ClassPath.Scanner scanner = new ClassPath.Scanner();
- scanner.scan(jarFile.toURI(), ClassPathTest.class.getClassLoader());
+ ClassPath.DefaultScanner scanner = new ClassPath.DefaultScanner();
+ scanner.scan(jarFile, ClassPathTest.class.getClassLoader());
assertEquals(1, scanner.getResources().size());
} finally {
jarFile.delete();
@@ -243,33 +154,37 @@ public class ClassPathTest extends TestCase {
public void testScanFromFile_fileNotExists() throws IOException {
ClassLoader classLoader = ClassPathTest.class.getClassLoader();
- ClassPath.Scanner scanner = new ClassPath.Scanner();
- scanner.scanFrom(new File("no/such/file/anywhere"), classLoader);
+ ClassPath.DefaultScanner scanner = new ClassPath.DefaultScanner();
+ scanner.scan(new File("no/such/file/anywhere"), classLoader);
assertThat(scanner.getResources()).isEmpty();
}
public void testScanFromFile_notJarFile() throws IOException {
ClassLoader classLoader = ClassPathTest.class.getClassLoader();
File notJar = File.createTempFile("not_a_jar", "txt");
- ClassPath.Scanner scanner = new ClassPath.Scanner();
+ ClassPath.DefaultScanner scanner = new ClassPath.DefaultScanner();
try {
- scanner.scanFrom(notJar, classLoader);
+ scanner.scan(notJar, classLoader);
} finally {
notJar.delete();
}
assertThat(scanner.getResources()).isEmpty();
}
- public void testGetClassPathEntry() throws URISyntaxException {
- assertEquals(URI.create("file:/usr/test/dep.jar"),
+ public void testGetClassPathEntry() throws MalformedURLException, URISyntaxException {
+ assertEquals(new File("/usr/test/dep.jar").toURI(),
ClassPath.Scanner.getClassPathEntry(
- new File("/home/build/outer.jar"), "file:/usr/test/dep.jar"));
- assertEquals(URI.create("file:/home/build/a.jar"),
- ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "a.jar"));
- assertEquals(URI.create("file:/home/build/x/y/z"),
- ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x/y/z"));
- assertEquals(URI.create("file:/home/build/x/y/z.jar"),
- ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x/y/z.jar"));
+ new File("/home/build/outer.jar"), "file:/usr/test/dep.jar").toURI());
+ assertEquals(new File("/home/build/a.jar").toURI(),
+ ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "a.jar").toURI());
+ assertEquals(new File("/home/build/x/y/z").toURI(),
+ ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x/y/z").toURI());
+ assertEquals(new File("/home/build/x/y/z.jar").toURI(),
+ ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x/y/z.jar")
+ .toURI());
+ assertEquals("/home/build/x y.jar",
+ ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x y.jar")
+ .getFile());
}
public void testGetClassPathFromManifest_nullManifest() {
@@ -290,17 +205,24 @@ public class ClassPathTest extends TestCase {
public void testGetClassPathFromManifest_badClassPath() throws IOException {
File jarFile = new File("base.jar");
- Manifest manifest = manifestClasspath("an_invalid^path");
+ Manifest manifest = manifestClasspath("nosuchscheme:an_invalid^path");
assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
.isEmpty();
}
+ public void testGetClassPathFromManifest_pathWithStrangeCharacter() throws IOException {
+ File jarFile = new File("base/some.jar");
+ Manifest manifest = manifestClasspath("file:the^file.jar");
+ assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
+ .containsExactly(fullpath("base/the^file.jar"));
+ }
+
public void testGetClassPathFromManifest_relativeDirectory() throws IOException {
File jarFile = new File("base/some.jar");
// with/relative/directory is the Class-Path value in the mf file.
Manifest manifest = manifestClasspath("with/relative/dir");
assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
- .has().exactly(new File("base/with/relative/dir").toURI()).inOrder();
+ .containsExactly(fullpath("base/with/relative/dir"));
}
public void testGetClassPathFromManifest_relativeJar() throws IOException {
@@ -308,7 +230,7 @@ public class ClassPathTest extends TestCase {
// with/relative/directory is the Class-Path value in the mf file.
Manifest manifest = manifestClasspath("with/relative.jar");
assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
- .has().exactly(new File("base/with/relative.jar").toURI()).inOrder();
+ .containsExactly(fullpath("base/with/relative.jar"));
}
public void testGetClassPathFromManifest_jarInCurrentDirectory() throws IOException {
@@ -316,31 +238,31 @@ public class ClassPathTest extends TestCase {
// with/relative/directory is the Class-Path value in the mf file.
Manifest manifest = manifestClasspath("current.jar");
assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
- .has().exactly(new File("base/current.jar").toURI()).inOrder();
+ .containsExactly(fullpath("base/current.jar"));
}
public void testGetClassPathFromManifest_absoluteDirectory() throws IOException {
File jarFile = new File("base/some.jar");
Manifest manifest = manifestClasspath("file:/with/absolute/dir");
assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
- .has().exactly(new File("/with/absolute/dir").toURI()).inOrder();
+ .containsExactly(fullpath("/with/absolute/dir"));
}
public void testGetClassPathFromManifest_absoluteJar() throws IOException {
File jarFile = new File("base/some.jar");
Manifest manifest = manifestClasspath("file:/with/absolute.jar");
assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
- .has().exactly(new File("/with/absolute.jar").toURI()).inOrder();
+ .containsExactly(fullpath("/with/absolute.jar"));
}
public void testGetClassPathFromManifest_multiplePaths() throws IOException {
File jarFile = new File("base/some.jar");
Manifest manifest = manifestClasspath("file:/with/absolute.jar relative.jar relative/dir");
assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
- .has().exactly(
- new File("/with/absolute.jar").toURI(),
- new File("base/relative.jar").toURI(),
- new File("base/relative/dir").toURI())
+ .containsExactly(
+ fullpath("/with/absolute.jar"),
+ fullpath("base/relative.jar"),
+ fullpath("base/relative/dir"))
.inOrder();
}
@@ -348,14 +270,14 @@ public class ClassPathTest extends TestCase {
File jarFile = new File("base/some.jar");
Manifest manifest = manifestClasspath(" relative.jar");
assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
- .has().exactly(new File("base/relative.jar").toURI()).inOrder();
+ .containsExactly(fullpath("base/relative.jar"));
}
public void testGetClassPathFromManifest_trailingBlanks() throws IOException {
File jarFile = new File("base/some.jar");
Manifest manifest = manifestClasspath("relative.jar ");
assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest))
- .has().exactly(new File("base/relative.jar").toURI()).inOrder();
+ .containsExactly(fullpath("base/relative.jar"));
}
public void testGetClassName() {
@@ -369,21 +291,21 @@ public class ClassPathTest extends TestCase {
}
public void testGetSimpleName() {
+ ClassLoader classLoader = getClass().getClassLoader();
assertEquals("Foo",
- new ClassInfo("Foo.class", getClass().getClassLoader()).getSimpleName());
+ new ClassInfo("Foo.class", classLoader).getSimpleName());
assertEquals("Foo",
- new ClassInfo("a/b/Foo.class", getClass().getClassLoader()).getSimpleName());
+ new ClassInfo("a/b/Foo.class", classLoader).getSimpleName());
assertEquals("Foo",
- new ClassInfo("a/b/Bar$Foo.class", getClass().getClassLoader()).getSimpleName());
+ new ClassInfo("a/b/Bar$Foo.class", classLoader).getSimpleName());
assertEquals("",
- new ClassInfo("a/b/Bar$1.class", getClass().getClassLoader()).getSimpleName());
+ new ClassInfo("a/b/Bar$1.class", classLoader).getSimpleName());
assertEquals("Foo",
- new ClassInfo("a/b/Bar$Foo.class", getClass().getClassLoader()).getSimpleName());
+ new ClassInfo("a/b/Bar$Foo.class", classLoader).getSimpleName());
assertEquals("",
- new ClassInfo("a/b/Bar$1.class", getClass().getClassLoader()).getSimpleName());
+ new ClassInfo("a/b/Bar$1.class", classLoader).getSimpleName());
assertEquals("Local",
- new ClassInfo("a/b/Bar$1Local.class", getClass().getClassLoader()).getSimpleName());
-
+ new ClassInfo("a/b/Bar$1Local.class", classLoader).getSimpleName());
}
public void testGetPackageName() {
@@ -393,6 +315,12 @@ public class ClassPathTest extends TestCase {
new ClassInfo("a/b/Foo.class", getClass().getClassLoader()).getPackageName());
}
+ // Test that ResourceInfo.urls() returns identical content to ClassLoader.getResources()
+
+ private static boolean contentEquals(URL left, URL right) throws IOException {
+ return Resources.asByteSource(left).contentEquals(Resources.asByteSource(right));
+ }
+
private static class Nested {}
public void testNulls() throws IOException {
@@ -401,6 +329,12 @@ public class ClassPathTest extends TestCase {
.testAllPublicInstanceMethods(ClassPath.from(getClass().getClassLoader()));
}
+ public void testResourceScanner() throws IOException {
+ ResourceScanner scanner = new ResourceScanner();
+ scanner.scan(ClassLoader.getSystemClassLoader());
+ assertThat(scanner.resources).contains("com/google/common/reflect/ClassPathTest.class");
+ }
+
private static ClassPath.ClassInfo findClass(
Iterable<ClassPath.ClassInfo> classes, Class<?> cls) {
for (ClassPath.ClassInfo classInfo : classes) {
@@ -412,7 +346,9 @@ public class ClassPathTest extends TestCase {
}
private static ResourceInfo resourceInfo(Class<?> cls) {
- return ResourceInfo.of(cls.getName().replace('.', '/') + ".class", cls.getClassLoader());
+ String resource = cls.getName().replace('.', '/') + ".class";
+ ClassLoader loader = cls.getClassLoader();
+ return ResourceInfo.of(resource, loader);
}
private static ClassInfo classInfo(Class<?> cls) {
@@ -420,7 +356,8 @@ public class ClassPathTest extends TestCase {
}
private static ClassInfo classInfo(Class<?> cls, ClassLoader classLoader) {
- return new ClassInfo(cls.getName().replace('.', '/') + ".class", classLoader);
+ String resource = cls.getName().replace('.', '/') + ".class";
+ return new ClassInfo(resource, classLoader);
}
private static Manifest manifestClasspath(String classpath) throws IOException {
@@ -456,4 +393,27 @@ public class ClassPathTest extends TestCase {
manifest.read(in);
return manifest;
}
+
+ private static File fullpath(String path) {
+ return new File(new File(path).toURI());
+ }
+
+ private static class ResourceScanner extends ClassPath.Scanner {
+ final Set<String> resources = new HashSet<String>();
+
+ @Override protected void scanDirectory(ClassLoader loader, File root) throws IOException {
+ URI base = root.toURI();
+ for (File entry : Files.fileTreeTraverser().preOrderTraversal(root)) {
+ String resourceName = new File(base.relativize(entry.toURI()).getPath()).getPath();
+ resources.add(resourceName);
+ }
+ }
+
+ @Override protected void scanJarFile(ClassLoader loader, JarFile file) throws IOException {
+ Enumeration<JarEntry> entries = file.entries();
+ while (entries.hasMoreElements()) {
+ resources.add(entries.nextElement().getName());
+ }
+ }
+ }
}
diff --git a/guava-tests/test/com/google/common/reflect/ImmutableTypeToInstanceMapTest.java b/guava-tests/test/com/google/common/reflect/ImmutableTypeToInstanceMapTest.java
index d622b22..9ad3b91 100644
--- a/guava-tests/test/com/google/common/reflect/ImmutableTypeToInstanceMapTest.java
+++ b/guava-tests/test/com/google/common/reflect/ImmutableTypeToInstanceMapTest.java
@@ -42,6 +42,7 @@ import java.util.Map.Entry;
*/
public class ImmutableTypeToInstanceMapTest extends TestCase {
+ @SuppressUnderAndroid // problem with suite builders on Android
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(ImmutableTypeToInstanceMapTest.class);
@@ -109,7 +110,7 @@ public class ImmutableTypeToInstanceMapTest extends TestCase {
.put(type, array)
.build();
assertEquals(1, map.size());
- assertThat(map.getInstance(type)).asList().has().exactly(array[0]).inOrder();
+ assertThat(map.getInstance(type)).asList().containsExactly(array[0]);
}
public void testWildcardType() {
diff --git a/guava-tests/test/com/google/common/reflect/InvokableTest.java b/guava-tests/test/com/google/common/reflect/InvokableTest.java
index b8875fd..af0f9c0 100644
--- a/guava-tests/test/com/google/common/reflect/InvokableTest.java
+++ b/guava-tests/test/com/google/common/reflect/InvokableTest.java
@@ -16,6 +16,8 @@
package com.google.common.reflect;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.testing.EqualsTester;
@@ -38,6 +40,7 @@ import javax.annotation.Nullable;
*
* @author Ben Yu
*/
+ at SuppressUnderAndroid // lots of failures, possibly some related to bad equals() implementations?
public class InvokableTest extends TestCase {
public void testConstructor_returnType() throws Exception {
@@ -56,7 +59,7 @@ public class InvokableTest extends TestCase {
@SuppressWarnings("rawtypes") // Foo.class
Constructor<WithConstructorAndTypeParameter> constructor = type.getDeclaredConstructor();
Invokable<?, ?> factory = Invokable.from(constructor);
- assertEquals(2, factory.getTypeParameters().length);
+ assertThat(factory.getTypeParameters()).hasLength(2);
assertEquals(type.getTypeParameters()[0], factory.getTypeParameters()[0]);
assertEquals(constructor.getTypeParameters()[0], factory.getTypeParameters()[1]);
ParameterizedType returnType = (ParameterizedType) factory.getReturnType().getType();
@@ -71,9 +74,8 @@ public class InvokableTest extends TestCase {
}
public void testConstructor_typeParameters() throws Exception {
- TypeVariable<?>[] variables =
- Prepender.constructor().getTypeParameters();
- assertEquals(1, variables.length);
+ TypeVariable<?>[] variables = Prepender.constructor().getTypeParameters();
+ assertThat(variables).hasLength(1);
assertEquals("A", variables[0].getName());
}
@@ -127,7 +129,7 @@ public class InvokableTest extends TestCase {
public void testStaticMethod_typeParameters() throws Exception {
Invokable<?, ?> delegate = Prepender.method("prepend", String.class, Iterable.class);
TypeVariable<?>[] variables = delegate.getTypeParameters();
- assertEquals(1, variables.length);
+ assertThat(variables).hasLength(1);
assertEquals("T", variables[0].getName());
}
@@ -197,7 +199,7 @@ public class InvokableTest extends TestCase {
public void testInstanceMethod_typeParameters() throws Exception {
Invokable<?, ?> delegate = Prepender.method("prepend", Iterable.class);
- assertEquals(0, delegate.getTypeParameters().length);
+ assertThat(delegate.getTypeParameters()).isEmpty();
}
public void testInstanceMethod_parameters() throws Exception {
@@ -205,10 +207,8 @@ public class InvokableTest extends TestCase {
ImmutableList<Parameter> parameters = delegate.getParameters();
assertEquals(1, parameters.size());
assertEquals(new TypeToken<Iterable<String>>() {}, parameters.get(0).getType());
- assertEquals(0, parameters.get(0).getAnnotations().length);
- new EqualsTester()
- .addEqualityGroup(parameters.get(0))
- .testEquals();
+ assertThat(parameters.get(0).getAnnotations()).isEmpty();
+ new EqualsTester().addEqualityGroup(parameters.get(0)).testEquals();
}
public void testInstanceMethod_call() throws Exception {
diff --git a/guava-tests/test/com/google/common/reflect/MutableTypeToInstanceMapTest.java b/guava-tests/test/com/google/common/reflect/MutableTypeToInstanceMapTest.java
index 26f702e..ad19d36 100644
--- a/guava-tests/test/com/google/common/reflect/MutableTypeToInstanceMapTest.java
+++ b/guava-tests/test/com/google/common/reflect/MutableTypeToInstanceMapTest.java
@@ -42,6 +42,7 @@ import java.util.Map.Entry;
*/
public class MutableTypeToInstanceMapTest extends TestCase {
+ @SuppressUnderAndroid // problem with suite builders on Android
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(MutableTypeToInstanceMapTest.class);
@@ -200,7 +201,7 @@ public class MutableTypeToInstanceMapTest extends TestCase {
TypeToken<ImmutableList<Integer>[]> type = new TypeToken<ImmutableList<Integer>[]>() {};
map.putInstance(type, array);
assertEquals(1, map.size());
- assertThat(map.getInstance(type)).asList().has().exactly(array[0]).inOrder();
+ assertThat(map.getInstance(type)).asList().containsExactly(array[0]);
}
public void testWildcardType() {
diff --git a/guava-tests/test/com/google/common/reflect/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/reflect/SuppressUnderAndroid.java
new file mode 100644
index 0000000..e5b20bf
--- /dev/null
+++ b/guava-tests/test/com/google/common/reflect/SuppressUnderAndroid.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.reflect;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>For more discussion, see {@linkplain com.google.common.base.SuppressUnderAndroid the
+ * documentation on another copy of this annotation}.
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/reflect/TypeResolverTest.java b/guava-tests/test/com/google/common/reflect/TypeResolverTest.java
index 84b1b5e..a14adec 100644
--- a/guava-tests/test/com/google/common/reflect/TypeResolverTest.java
+++ b/guava-tests/test/com/google/common/reflect/TypeResolverTest.java
@@ -28,6 +28,7 @@ import java.util.Map;
*
* @author Ben Yu
*/
+ at SuppressUnderAndroid // lots of failures, possibly some related to bad equals() implementations?
public class TypeResolverTest extends TestCase {
public void testWhere_noMapping() {
@@ -111,11 +112,11 @@ public class TypeResolverTest extends TestCase {
.where(new TypeCapture<List<T>>() {}.capture(),
new TypeCapture<List<String>>() {}.capture())
.resolveType(t));
- assertEquals(Types.subtypeOf(String.class), new TypeResolver()
+ assertEquals(t, new TypeResolver()
.where(new TypeCapture<List<T>>() {}.capture(),
new TypeCapture<List<? extends String>>() {}.capture())
.resolveType(t));
- assertEquals(Types.supertypeOf(String.class), new TypeResolver()
+ assertEquals(t, new TypeResolver()
.where(new TypeCapture<List<T>>() {}.capture(),
new TypeCapture<List<? super String>>() {}.capture())
.resolveType(t));
@@ -186,24 +187,67 @@ public class TypeResolverTest extends TestCase {
public <T> void testWhere_wrongOrder() {
try {
new TypeResolver().where(String.class, aTypeVariable());
- fail();
+ fail();
} catch (IllegalArgumentException expected) {}
}
public <T> void testWhere_mapFromConcreteParameterizedType() {
try {
new TypeResolver().where(new TypeCapture<List<String>>() {}.capture(), aTypeVariable());
- fail();
+ fail();
} catch (IllegalArgumentException expected) {}
}
public <T> void testWhere_mapFromConcreteGenericArrayType() {
try {
new TypeResolver().where(new TypeCapture<List<String>>() {}.capture(), aTypeVariable());
- fail();
+ fail();
} catch (IllegalArgumentException expected) {}
}
+ public <K, V> void testWhere_actualArgHasWildcard() {
+ TypeResolver resolver = new TypeResolver().where(
+ new TypeCapture<Iterable<Map<?, V>>>() {}.capture(),
+ new TypeCapture<Iterable<Map<String, Integer>>>() {}.capture());
+ assertEquals(
+ new TypeCapture<K>() {}.capture(), resolver.resolveType(new TypeCapture<K>() {}.capture()));
+ assertEquals(
+ Integer.class, resolver.resolveType(new TypeCapture<V>() {}.capture()));
+ }
+
+ public <T> void testWhere_mapFromWildcard() {
+ Type subType = new TypeCapture<TypedKeyMap<T>>() {}.capture();
+ assertEquals(new TypeCapture<TypedKeyMap<String>>() {}.capture(),
+ new TypeResolver()
+ .where(
+ new TypeCapture<Map<Integer, T>>() {}.capture(),
+ new TypeCapture<Map<?, String>>() {}.capture())
+ .resolveType(subType));
+ }
+
+ public <T> void testWhere_mapFromWildcardToParameterized() {
+ Type subType = new TypeCapture<TypedListKeyMap<T>>() {}.capture();
+ assertEquals(new TypeCapture<TypedListKeyMap<String>>() {}.capture(),
+ new TypeResolver()
+ .where(
+ new TypeCapture<Map<List<Integer>, T>>() {}.capture(),
+ new TypeCapture<Map<?, String>>() {}.capture())
+ .resolveType(subType));
+ }
+
+ public <T> void testWhere_mapFromBoundedWildcard() {
+ Type subType = new TypeCapture<TypedKeyMap<T>>() {}.capture();
+ // TODO(benyu): This should check equality to an expected value, see discussion in cl/98674873
+ new TypeResolver()
+ .where(
+ new TypeCapture<Map<Integer, T>>() {}.capture(),
+ new TypeCapture<Map<? extends Number, ? extends Number>>() {}.capture())
+ .resolveType(subType);
+ }
+
+ interface TypedKeyMap<T> extends Map<Integer, T> {}
+ interface TypedListKeyMap<T> extends Map<List<Integer>, T> {}
+
private static <T> Type aTypeVariable() {
return new TypeCapture<T>() {}.capture();
}
diff --git a/guava-tests/test/com/google/common/reflect/TypeTokenResolutionTest.java b/guava-tests/test/com/google/common/reflect/TypeTokenResolutionTest.java
index bf9dd11..bf511c6 100644
--- a/guava-tests/test/com/google/common/reflect/TypeTokenResolutionTest.java
+++ b/guava-tests/test/com/google/common/reflect/TypeTokenResolutionTest.java
@@ -37,6 +37,7 @@ import java.util.Map;
*
* @author Ben Yu
*/
+ at SuppressUnderAndroid // lots of failures, possibly some related to bad equals() implementations?
public class TypeTokenResolutionTest extends TestCase {
private static class Foo<A, B> {
@@ -124,9 +125,8 @@ public class TypeTokenResolutionTest extends TestCase {
parameterized.parameterizedType());
assertEquals(TypeTokenResolutionTest.class, resolved.getOwnerType());
assertEquals(Bar.class, resolved.getRawType());
- assertThat(resolved.getActualTypeArguments()).asList().has().item(String.class);
+ assertThat(resolved.getActualTypeArguments()).asList().contains(String.class);
}
-
private interface StringListPredicate extends Predicate<List<String>> {}
private interface IntegerSupplier extends Supplier<Integer> {}
diff --git a/guava-tests/test/com/google/common/reflect/TypeTokenTest.java b/guava-tests/test/com/google/common/reflect/TypeTokenTest.java
index 893a054..4a91392 100644
--- a/guava-tests/test/com/google/common/reflect/TypeTokenTest.java
+++ b/guava-tests/test/com/google/common/reflect/TypeTokenTest.java
@@ -27,7 +27,7 @@ import com.google.common.primitives.Primitives;
import com.google.common.testing.EqualsTester;
import com.google.common.testing.NullPointerTester;
import com.google.common.testing.SerializableTester;
-import com.google.common.truth.CollectionSubject;
+import com.google.common.truth.IterableSubject;
import junit.framework.TestCase;
@@ -49,6 +49,7 @@ import java.util.Map;
* @author Sven Mawson
* @author Ben Yu
*/
+ at SuppressUnderAndroid // lots of failures, possibly some related to bad equals() implementations?
public class TypeTokenTest extends TestCase {
private abstract static class StringList implements List<String> {}
@@ -109,19 +110,19 @@ public class TypeTokenTest extends TestCase {
assertEquals(new Local<String>() {}.getClass().getGenericSuperclass(), type.getType());
}
- public void testGenericArrayType() throws Exception {
+ public void testGenericArrayType() {
TypeToken<List<String>[]> token = new TypeToken<List<String>[]>() {};
assertEquals(List[].class, token.getRawType());
- assertTrue(token.getType() instanceof GenericArrayType);
+ assertThat(token.getType()).isInstanceOf(GenericArrayType.class);
}
- public void testMultiDimensionalGenericArrayType() throws Exception {
+ public void testMultiDimensionalGenericArrayType() {
TypeToken<List<Long>[][][]> token = new TypeToken<List<Long>[][][]>() {};
assertEquals(List[][][].class, token.getRawType());
- assertTrue(token.getType() instanceof GenericArrayType);
+ assertThat(token.getType()).isInstanceOf(GenericArrayType.class);
}
- public <T> void testGenericVariableTypeArrays() throws Exception {
+ public <T> void testGenericVariableTypeArrays() {
assertEquals("T[]", new TypeToken<T[]>() {}.toString());
}
@@ -133,7 +134,7 @@ public class TypeTokenTest extends TestCase {
}
public <F extends Enum<F> & Function<String, Integer> & Iterable<Long>>
- void testResolveType_fromTypeVariable() throws Exception {
+ void testResolveType_fromTypeVariable() {
TypeToken<?> f = TypeToken.of(new TypeCapture<F>() {}.capture());
assertEquals(String.class,
f.resolveType(Function.class.getTypeParameters()[0]).getType());
@@ -144,13 +145,13 @@ public class TypeTokenTest extends TestCase {
}
public <E extends Comparable<Iterable<String>> & Iterable<Integer>>
- void testResolveType_fromTypeVariable_onlyDirectBoundsAreUsed() throws Exception {
+ void testResolveType_fromTypeVariable_onlyDirectBoundsAreUsed() {
TypeToken<?> e = TypeToken.of(new TypeCapture<E>() {}.capture());
assertEquals(Integer.class,
e.resolveType(Iterable.class.getTypeParameters()[0]).getType());
}
- public void testResolveType_fromWildcard() throws Exception {
+ public void testResolveType_fromWildcard() {
ParameterizedType withWildcardType = (ParameterizedType)
new TypeCapture<Comparable<? extends Iterable<String>>>() {}.capture();
TypeToken<?> wildcardType = TypeToken.of(withWildcardType.getActualTypeArguments()[0]);
@@ -160,39 +161,39 @@ public class TypeTokenTest extends TestCase {
public void testGetTypes_noSuperclass() {
TypeToken<Object>.TypeSet types = new TypeToken<Object>() {}.getTypes();
- assertThat(types).has().item(TypeToken.of(Object.class));
- assertThat(types.rawTypes()).has().item(Object.class);
+ assertThat(types).contains(TypeToken.of(Object.class));
+ assertThat(types.rawTypes()).contains(Object.class);
assertThat(types.interfaces()).isEmpty();
assertThat(types.interfaces().rawTypes()).isEmpty();
- assertThat(types.classes()).has().item(TypeToken.of(Object.class));
- assertThat(types.classes().rawTypes()).has().item(Object.class);
+ assertThat(types.classes()).contains(TypeToken.of(Object.class));
+ assertThat(types.classes().rawTypes()).contains(Object.class);
}
public void testGetTypes_fromInterface() {
TypeToken<Interface1>.TypeSet types = new TypeToken<Interface1>() {}.getTypes();
- assertThat(types).has().item(TypeToken.of(Interface1.class));
- assertThat(types.rawTypes()).has().item(Interface1.class);
- assertThat(types.interfaces()).has().item(TypeToken.of(Interface1.class));
- assertThat(types.interfaces().rawTypes()).has().item(Interface1.class);
+ assertThat(types).contains(TypeToken.of(Interface1.class));
+ assertThat(types.rawTypes()).contains(Interface1.class);
+ assertThat(types.interfaces()).contains(TypeToken.of(Interface1.class));
+ assertThat(types.interfaces().rawTypes()).contains(Interface1.class);
assertThat(types.classes()).isEmpty();
assertThat(types.classes().rawTypes()).isEmpty();
}
public void testGetTypes_fromPrimitive() {
TypeToken<Integer>.TypeSet types = TypeToken.of(int.class).getTypes();
- assertThat(types).has().item(TypeToken.of(int.class));
- assertThat(types.rawTypes()).has().item(int.class);
+ assertThat(types).contains(TypeToken.of(int.class));
+ assertThat(types.rawTypes()).contains(int.class);
assertThat(types.interfaces()).isEmpty();
assertThat(types.interfaces().rawTypes()).isEmpty();
- assertThat(types.classes()).has().item(TypeToken.of(int.class));
- assertThat(types.classes().rawTypes()).has().item(int.class);
+ assertThat(types.classes()).contains(TypeToken.of(int.class));
+ assertThat(types.classes().rawTypes()).contains(int.class);
}
public void testGetTypes_withInterfacesAndSuperclasses() {
abstract class Class2 extends Class1 implements Interface12 {}
abstract class Class3<T> extends Class2 implements Interface3<T> {}
TypeToken<Class3<String>>.TypeSet types = new TypeToken<Class3<String>>() {}.getTypes();
- makeUnmodifiable(types).has().exactly(
+ makeUnmodifiable(types).containsExactly(
new TypeToken<Class3<String>>() {},
new TypeToken<Interface3<String>>() {},
new TypeToken<Iterable<String>>() {},
@@ -202,13 +203,13 @@ public class TypeTokenTest extends TestCase {
TypeToken.of(Interface2.class),
TypeToken.of(Class1.class),
TypeToken.of(Object.class));
- makeUnmodifiable(types.interfaces()).has().exactly(
+ makeUnmodifiable(types.interfaces()).containsExactly(
new TypeToken<Interface3<String>>() {},
TypeToken.of(Interface12.class),
TypeToken.of(Interface1.class),
TypeToken.of(Interface2.class),
new TypeToken<Iterable<String>>() {});
- makeUnmodifiable(types.classes()).has().exactly(
+ makeUnmodifiable(types.classes()).containsExactly(
new TypeToken<Class3<String>>() {},
TypeToken.of(Class2.class),
TypeToken.of(Class1.class),
@@ -220,7 +221,7 @@ public class TypeTokenTest extends TestCase {
abstract class Class2 extends Class1 implements Interface12 {}
abstract class Class3<T> extends Class2 implements Interface3<T> {}
TypeToken<Class3<String>>.TypeSet types = new TypeToken<Class3<String>>() {}.getTypes();
- makeUnmodifiable(types.rawTypes()).has().exactly(
+ makeUnmodifiable(types.rawTypes()).containsExactly(
Class3.class, Interface3.class,
Iterable.class,
Class2.class,
@@ -229,13 +230,13 @@ public class TypeTokenTest extends TestCase {
Interface2.class,
Class1.class,
Object.class);
- makeUnmodifiable(types.interfaces().rawTypes()).has().exactly(
+ makeUnmodifiable(types.interfaces().rawTypes()).containsExactly(
Interface3.class,
Interface12.class,
Interface1.class,
Interface2.class,
Iterable.class);
- makeUnmodifiable(types.classes().rawTypes()).has().exactly(
+ makeUnmodifiable(types.classes().rawTypes()).containsExactly(
Class3.class,
Class2.class,
Class1.class,
@@ -246,15 +247,13 @@ public class TypeTokenTest extends TestCase {
public <A extends Class1 & Interface1, B extends A>
void testGetTypes_ignoresTypeVariablesByDefault() {
TypeToken<?>.TypeSet types = TypeToken.of(new TypeCapture<B>() {}.capture()).getTypes();
- makeUnmodifiable(types).has().exactly(
+ makeUnmodifiable(types).containsExactly(
TypeToken.of(Interface1.class), TypeToken.of(Class1.class),
TypeToken.of(Object.class));
assertSubtypeFirst(types);
- makeUnmodifiable(types.interfaces())
- .has().exactly(TypeToken.of(Interface1.class))
- .inOrder();
+ makeUnmodifiable(types.interfaces()).containsExactly(TypeToken.of(Interface1.class));
makeUnmodifiable(types.classes())
- .has().exactly(TypeToken.of(Class1.class), TypeToken.of(Object.class))
+ .containsExactly(TypeToken.of(Class1.class), TypeToken.of(Object.class))
.inOrder();
}
@@ -262,12 +261,10 @@ public class TypeTokenTest extends TestCase {
void testGetTypes_rawTypes_ignoresTypeVariablesByDefault() {
TypeToken<?>.TypeSet types = TypeToken.of(new TypeCapture<B>() {}.capture()).getTypes();
makeUnmodifiable(types.rawTypes())
- .has().exactly(Interface1.class, Class1.class, Object.class);
- makeUnmodifiable(types.interfaces().rawTypes())
- .has().exactly(Interface1.class)
- .inOrder();
+ .containsExactly(Interface1.class, Class1.class, Object.class);
+ makeUnmodifiable(types.interfaces().rawTypes()).containsExactly(Interface1.class);
makeUnmodifiable(types.classes().rawTypes())
- .has().exactly(Class1.class, Object.class)
+ .containsExactly(Class1.class, Object.class)
.inOrder();
}
@@ -275,7 +272,7 @@ public class TypeTokenTest extends TestCase {
void testGetTypes_manyBounds() {
TypeToken<?>.TypeSet types = TypeToken.of(new TypeCapture<A>() {}.capture()).getTypes();
makeUnmodifiable(types.rawTypes())
- .has().exactly(Interface1.class, Interface2.class, Interface3.class, Iterable.class);
+ .containsExactly(Interface1.class, Interface2.class, Interface3.class, Iterable.class);
}
private static void assertSubtypeFirst(TypeToken<?>.TypeSet types) {
@@ -293,7 +290,7 @@ public class TypeTokenTest extends TestCase {
for (TypeToken<?> left : types) {
int j = 0;
for (TypeToken<?> right : types) {
- if (left.isAssignableFrom(right)) {
+ if (left.isSupertypeOf(right)) {
assertTrue(left + " should be after " + right, i >= j);
}
j++;
@@ -477,28 +474,28 @@ public class TypeTokenTest extends TestCase {
public <T extends NoInterface&Iterable<String>>
void testGetGenericInterfaces_typeVariable_boundsAreClassWithInterface() {
makeUnmodifiable(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
- .has().exactly(new TypeToken<Iterable<String>>() {});
+ .containsExactly(new TypeToken<Iterable<String>>() {});
assertHasArrayInterfaces(new TypeToken<T[]>() {});
}
public <T extends CharSequence&Iterable<String>>
void testGetGenericInterfaces_typeVariable_boundsAreInterfaces() {
makeUnmodifiable(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
- .has().exactly(TypeToken.of(CharSequence.class), new TypeToken<Iterable<String>>() {});
+ .containsExactly(TypeToken.of(CharSequence.class), new TypeToken<Iterable<String>>() {});
assertHasArrayInterfaces(new TypeToken<T[]>() {});
}
public <T extends CharSequence&Iterable<T>>
void testGetGenericInterfaces_typeVariable_boundsAreFBoundedInterfaces() {
makeUnmodifiable(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
- .has().exactly(TypeToken.of(CharSequence.class), new TypeToken<Iterable<T>>() {});
+ .containsExactly(TypeToken.of(CharSequence.class), new TypeToken<Iterable<T>>() {});
assertHasArrayInterfaces(new TypeToken<T[]>() {});
}
public <T extends Base&Iterable<T>>
void testGetGenericInterfaces_typeVariable_boundsAreClassWithFBoundedInterface() {
makeUnmodifiable(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
- .has().exactly(new TypeToken<Iterable<T>>() {});
+ .containsExactly(new TypeToken<Iterable<T>>() {});
assertHasArrayInterfaces(new TypeToken<T[]>() {});
}
@@ -511,7 +508,7 @@ public class TypeTokenTest extends TestCase {
public <T extends Iterable<T>, T1 extends T, T2 extends T1>
void testGetGenericInterfaces_typeVariable_boundIsTypeVariableAndInterface() {
makeUnmodifiable(TypeToken.of(new TypeCapture<T2>() {}.capture()).getGenericInterfaces())
- .has().exactly(TypeToken.of(new TypeCapture<T1>() {}.capture()));
+ .containsExactly(TypeToken.of(new TypeCapture<T1>() {}.capture()));
assertHasArrayInterfaces(new TypeToken<T2[]>() {});
}
@@ -528,7 +525,7 @@ public class TypeTokenTest extends TestCase {
public void testGetGenericInterfaces_wildcard_boundIsInterface() {
TypeToken<Iterable<String>> interfaceType = new TypeToken<Iterable<String>>() {};
makeUnmodifiable(TypeToken.of(Types.subtypeOf(interfaceType.getType())).getGenericInterfaces())
- .has().exactly(interfaceType);
+ .containsExactly(interfaceType);
assertHasArrayInterfaces(new TypeToken<Iterable<String>[]>() {});
}
@@ -539,8 +536,8 @@ public class TypeTokenTest extends TestCase {
public void testGetGenericInterfaces_withInterfaces() {
Map<Class<?>, Type> interfaceMap = Maps.newHashMap();
- for (TypeToken<?> interfaceType:
- new TypeToken<Implementation<Integer, String>>() {}.getGenericInterfaces()) {
+ for (TypeToken<?> interfaceType
+ : new TypeToken<Implementation<Integer, String>>() {}.getGenericInterfaces()) {
interfaceMap.put(interfaceType.getRawType(), interfaceType.getType());
}
assertEquals(ImmutableMap.of(
@@ -575,171 +572,228 @@ public class TypeTokenTest extends TestCase {
public void testAssignableClassToClass() {
@SuppressWarnings("rawtypes") // To test TypeToken<List>
TypeToken<List> tokL = new TypeToken<List>() {};
- assertTrue(tokL.isAssignableFrom(List.class));
- assertTrue(tokL.isAssignableFrom(ArrayList.class));
- assertFalse(tokL.isAssignableFrom(List[].class));
+ assertTrue(tokL.isSupertypeOf(List.class));
+ assertTrue(tokL.isSupertypeOf(ArrayList.class));
+ assertFalse(tokL.isSupertypeOf(List[].class));
TypeToken<Number> tokN = new TypeToken<Number>() {};
- assertTrue(tokN.isAssignableFrom(Number.class));
- assertTrue(tokN.isAssignableFrom(Integer.class));
+ assertTrue(tokN.isSupertypeOf(Number.class));
+ assertTrue(tokN.isSupertypeOf(Integer.class));
}
public <T> void testAssignableParameterizedTypeToObject() {
- assertTrue(TypeToken.of(Object.class).isAssignableFrom(
+ assertTrue(TypeToken.of(Object.class).isSupertypeOf(
TypeToken.of(new TypeCapture<T>() {}.capture())));
- assertFalse(TypeToken.of(int.class).isAssignableFrom(
+ assertFalse(TypeToken.of(int.class).isSupertypeOf(
TypeToken.of(new TypeCapture<T>() {}.capture())));
}
public <T, T1 extends T> void testAssignableGenericArrayToGenericArray() {
- assertTrue(new TypeToken<T[]>() {}.isAssignableFrom(new TypeToken<T[]>() {}));
- assertTrue(new TypeToken<T[]>() {}.isAssignableFrom(new TypeToken<T1[]>() {}));
- assertFalse(new TypeToken<T[]>() {}.isAssignableFrom(new TypeToken<T[][]>() {}));
+ assertTrue(new TypeToken<T[]>() {}.isSupertypeOf(new TypeToken<T[]>() {}));
+ assertTrue(new TypeToken<T[]>() {}.isSupertypeOf(new TypeToken<T1[]>() {}));
+ assertFalse(new TypeToken<T[]>() {}.isSupertypeOf(new TypeToken<T[][]>() {}));
+ }
+
+ public <T, T1 extends T> void testAssignableGenericArrayToClass() {
+ assertTrue(TypeToken.of(Object[].class.getSuperclass())
+ .isSupertypeOf(new TypeToken<T[]>() {}));
+ for (Class<?> interfaceType : Object[].class.getInterfaces()) {
+ assertTrue(TypeToken.of(interfaceType)
+ .isSupertypeOf(new TypeToken<T[]>() {}));
+ }
+ assertTrue(TypeToken.of(Object.class).isSupertypeOf(new TypeToken<T[]>() {}));
+ assertFalse(TypeToken.of(String.class).isSupertypeOf(new TypeToken<T[]>() {}));
}
- public void testAssignableWildcardBoundedByArrayToArrayClass() throws Exception {
+ public void testAssignableWildcardBoundedByArrayToArrayClass() {
Type wildcardType = Types.subtypeOf(Object[].class);
- assertTrue(TypeToken.of(Object[].class).isAssignableFrom(wildcardType));
- assertTrue(TypeToken.of(Object.class).isAssignableFrom(wildcardType));
- assertTrue(TypeToken.of(wildcardType).isAssignableFrom(wildcardType));
- assertFalse(TypeToken.of(int[].class).isAssignableFrom(wildcardType));
+ assertTrue(TypeToken.of(Object[].class).isSupertypeOf(wildcardType));
+ assertTrue(TypeToken.of(Object.class).isSupertypeOf(wildcardType));
+ assertFalse(TypeToken.of(wildcardType).isSupertypeOf(wildcardType));
+ assertFalse(TypeToken.of(int[].class).isSupertypeOf(wildcardType));
+ }
+
+ public void testAssignableWildcardTypeParameterToClassTypeParameter() {
+ TypeToken<?> wildcardType = new TypeToken<Iterable<? extends Object[]>>() {};
+ assertFalse(new TypeToken<Iterable<Object[]>>() {}.isSupertypeOf(wildcardType));
+ assertFalse(new TypeToken<Iterable<Object>>() {}.isSupertypeOf(wildcardType));
+ assertTrue(wildcardType.isSupertypeOf(wildcardType));
+ assertFalse(new TypeToken<Iterable<int[]>>() {}.isSupertypeOf(wildcardType));
+ }
+
+ public void testAssignableArrayClassToBoundedWildcard() {
+ TypeToken<?> subtypeOfArray = TypeToken.of(Types.subtypeOf(Object[].class));
+ TypeToken<?> supertypeOfArray = TypeToken.of(Types.supertypeOf(Object[].class));
+ assertFalse(subtypeOfArray.isSupertypeOf(Object[].class));
+ assertFalse(subtypeOfArray.isSupertypeOf(Object[][].class));
+ assertFalse(subtypeOfArray.isSupertypeOf(String[].class));
+ assertTrue(supertypeOfArray.isSupertypeOf(Object[].class));
+ assertFalse(supertypeOfArray.isSupertypeOf(Object.class));
+ assertTrue(supertypeOfArray.isSupertypeOf(Object[][].class));
+ assertTrue(supertypeOfArray.isSupertypeOf(String[].class));
+ }
+
+ public void testAssignableClassTypeParameterToWildcardTypeParameter() {
+ TypeToken<?> subtypeOfArray = new TypeToken<Iterable<? extends Object[]>>() {};
+ TypeToken<?> supertypeOfArray = new TypeToken<Iterable<? super Object[]>>() {};
+ assertTrue(subtypeOfArray.isSupertypeOf(new TypeToken<Iterable<Object[]>>() {}));
+ assertTrue(subtypeOfArray.isSupertypeOf(new TypeToken<Iterable<Object[][]>>() {}));
+ assertTrue(subtypeOfArray.isSupertypeOf(new TypeToken<Iterable<String[]>>() {}));
+ assertTrue(supertypeOfArray.isSupertypeOf(new TypeToken<Iterable<Object[]>>() {}));
+ assertTrue(supertypeOfArray.isSupertypeOf(new TypeToken<Iterable<Object>>() {}));
+ assertFalse(supertypeOfArray.isSupertypeOf(new TypeToken<Iterable<Object[][]>>() {}));
+ assertFalse(supertypeOfArray.isSupertypeOf(new TypeToken<Iterable<String[]>>() {}));
+ }
+
+ public void testAssignableNonParameterizedClassToWildcard() {
+ TypeToken<?> supertypeOfString = TypeToken.of(Types.supertypeOf(String.class));
+ assertFalse(supertypeOfString.isSupertypeOf(supertypeOfString));
+ assertFalse(supertypeOfString.isSupertypeOf(Object.class));
+ assertFalse(supertypeOfString.isSupertypeOf(CharSequence.class));
+ assertTrue(supertypeOfString.isSupertypeOf(String.class));
+ assertTrue(supertypeOfString.isSupertypeOf(Types.subtypeOf(String.class)));
+ }
+
+ public void testAssignableWildcardBoundedByIntArrayToArrayClass() {
+ Type wildcardType = Types.subtypeOf(int[].class);
+ assertTrue(TypeToken.of(int[].class).isSupertypeOf(wildcardType));
+ assertTrue(TypeToken.of(Object.class).isSupertypeOf(wildcardType));
+ assertFalse(TypeToken.of(wildcardType).isSupertypeOf(wildcardType));
+ assertFalse(TypeToken.of(Object[].class).isSupertypeOf(wildcardType));
}
- public void testAssignableArrayClassToBoundedWildcard() throws Exception {
- TypeToken<?> upperBounded = TypeToken.of(Types.subtypeOf(Object[].class));
- TypeToken<?> lowerBounded = TypeToken.of(Types.supertypeOf(Object[].class));
- assertTrue(upperBounded.isAssignableFrom(Object[].class));
- assertTrue(upperBounded.isAssignableFrom(Object[][].class));
- assertTrue(upperBounded.isAssignableFrom(String[].class));
- assertTrue(lowerBounded.isAssignableFrom(Object[].class));
- assertTrue(lowerBounded.isAssignableFrom(Object.class));
- assertFalse(lowerBounded.isAssignableFrom(Object[][].class));
- assertFalse(lowerBounded.isAssignableFrom(String[].class));
+ public void testAssignableWildcardTypeParameterBoundedByIntArrayToArrayClassTypeParameter() {
+ TypeToken<?> wildcardType = new TypeToken<Iterable<? extends int[]>>() {};
+ assertFalse(new TypeToken<Iterable<int[]>>() {}.isSupertypeOf(wildcardType));
+ assertFalse(new TypeToken<Iterable<Object>>() {}.isSupertypeOf(wildcardType));
+ assertTrue(wildcardType.isSupertypeOf(wildcardType));
+ assertFalse(new TypeToken<Iterable<Object[]>>() {}.isSupertypeOf(wildcardType));
}
- public void testAssignableWildcardBoundedByIntArrayToArrayClass() throws Exception {
- Type wildcardType = Types.subtypeOf(int[].class);
- assertTrue(TypeToken.of(int[].class).isAssignableFrom(wildcardType));
- assertTrue(TypeToken.of(Object.class).isAssignableFrom(wildcardType));
- assertTrue(TypeToken.of(wildcardType).isAssignableFrom(wildcardType));
- assertFalse(TypeToken.of(Object[].class).isAssignableFrom(wildcardType));
+ public void testAssignableWildcardToWildcard() {
+ TypeToken<?> subtypeOfArray = TypeToken.of(Types.subtypeOf(Object[].class));
+ TypeToken<?> supertypeOfArray = TypeToken.of(Types.supertypeOf(Object[].class));
+ assertTrue(supertypeOfArray.isSupertypeOf(subtypeOfArray));
+ assertFalse(supertypeOfArray.isSupertypeOf(supertypeOfArray));
+ assertFalse(subtypeOfArray.isSupertypeOf(subtypeOfArray));
+ assertFalse(subtypeOfArray.isSupertypeOf(supertypeOfArray));
}
- public void testAssignableWildcardToWildcard() throws Exception {
- TypeToken<?> upperBounded = TypeToken.of(Types.subtypeOf(Object[].class));
- TypeToken<?> lowerBounded = TypeToken.of(Types.supertypeOf(Object[].class));
- assertFalse(lowerBounded.isAssignableFrom(upperBounded));
- assertTrue(lowerBounded.isAssignableFrom(lowerBounded));
- assertTrue(upperBounded.isAssignableFrom(upperBounded));
- assertFalse(upperBounded.isAssignableFrom(lowerBounded));
+ public void testAssignableWildcardTypeParameterToWildcardTypeParameter() {
+ TypeToken<?> subtypeOfArray = new TypeToken<Iterable<? extends Object[]>>() {};
+ TypeToken<?> supertypeOfArray = new TypeToken<Iterable<? super Object[]>>() {};
+ assertFalse(supertypeOfArray.isSupertypeOf(subtypeOfArray));
+ assertTrue(supertypeOfArray.isSupertypeOf(supertypeOfArray));
+ assertTrue(subtypeOfArray.isSupertypeOf(subtypeOfArray));
+ assertFalse(subtypeOfArray.isSupertypeOf(supertypeOfArray));
}
public <T> void testAssignableGenericArrayToArrayClass() {
- assertTrue(TypeToken.of(Object[].class).isAssignableFrom(new TypeToken<T[]>() {}));
- assertTrue(TypeToken.of(Object[].class).isAssignableFrom(new TypeToken<T[][]>() {}));
- assertTrue(TypeToken.of(Object[][].class).isAssignableFrom(new TypeToken<T[][]>() {}));
+ assertTrue(TypeToken.of(Object[].class).isSupertypeOf(new TypeToken<T[]>() {}));
+ assertTrue(TypeToken.of(Object[].class).isSupertypeOf(new TypeToken<T[][]>() {}));
+ assertTrue(TypeToken.of(Object[][].class).isSupertypeOf(new TypeToken<T[][]>() {}));
}
public void testAssignableParameterizedTypeToClass() {
@SuppressWarnings("rawtypes") // Trying to test raw class
TypeToken<List> tokL = new TypeToken<List>() {};
- assertTrue(tokL.isAssignableFrom(StringList.class));
- assertTrue(tokL.isAssignableFrom(
+ assertTrue(tokL.isSupertypeOf(StringList.class));
+ assertTrue(tokL.isSupertypeOf(
StringList.class.getGenericInterfaces()[0]));
@SuppressWarnings("rawtypes") // Trying to test raw class
TypeToken<Second> tokS = new TypeToken<Second>() {};
- assertTrue(tokS.isAssignableFrom(Second.class));
- assertTrue(tokS.isAssignableFrom(Third.class.getGenericSuperclass()));
+ assertTrue(tokS.isSupertypeOf(Second.class));
+ assertTrue(tokS.isSupertypeOf(Third.class.getGenericSuperclass()));
}
- public void testAssignableArrayToClass() throws Exception {
+ public void testAssignableArrayToClass() {
@SuppressWarnings("rawtypes") // Trying to test raw class
TypeToken<List[]> tokL = new TypeToken<List[]>() {};
- assertTrue(tokL.isAssignableFrom(List[].class));
- assertFalse(tokL.isAssignableFrom(List.class));
+ assertTrue(tokL.isSupertypeOf(List[].class));
+ assertFalse(tokL.isSupertypeOf(List.class));
@SuppressWarnings("rawtypes") // Trying to test raw class
TypeToken<Second[]> tokS = new TypeToken<Second[]>() {};
- assertTrue(tokS.isAssignableFrom(Second[].class));
- assertTrue(tokS.isAssignableFrom(Third[].class));
+ assertTrue(tokS.isSupertypeOf(Second[].class));
+ assertTrue(tokS.isSupertypeOf(Third[].class));
}
@SuppressWarnings("rawtypes") // Trying to test raw class
public void testAssignableTokenToClass() {
TypeToken<List> tokL = new TypeToken<List>() {};
- assertTrue(tokL.isAssignableFrom(new TypeToken<List>() {}));
- assertTrue(tokL.isAssignableFrom(new TypeToken<List<String>>() {}));
- assertTrue(tokL.isAssignableFrom(new TypeToken<List<?>>() {}));
+ assertTrue(tokL.isSupertypeOf(new TypeToken<List>() {}));
+ assertTrue(tokL.isSupertypeOf(new TypeToken<List<String>>() {}));
+ assertTrue(tokL.isSupertypeOf(new TypeToken<List<?>>() {}));
TypeToken<Second> tokS = new TypeToken<Second>() {};
- assertTrue(tokS.isAssignableFrom(new TypeToken<Second>() {}));
- assertTrue(tokS.isAssignableFrom(new TypeToken<Third>() {}));
- assertTrue(tokS.isAssignableFrom(
+ assertTrue(tokS.isSupertypeOf(new TypeToken<Second>() {}));
+ assertTrue(tokS.isSupertypeOf(new TypeToken<Third>() {}));
+ assertTrue(tokS.isSupertypeOf(
new TypeToken<Third<String, Integer>>() {}));
TypeToken<List[]> tokA = new TypeToken<List[]>() {};
- assertTrue(tokA.isAssignableFrom(new TypeToken<List[]>() {}));
- assertTrue(tokA.isAssignableFrom(new TypeToken<List<String>[]>() {}));
- assertTrue(tokA.isAssignableFrom(new TypeToken<List<?>[]>() {}));
+ assertTrue(tokA.isSupertypeOf(new TypeToken<List[]>() {}));
+ assertTrue(tokA.isSupertypeOf(new TypeToken<List<String>[]>() {}));
+ assertTrue(tokA.isSupertypeOf(new TypeToken<List<?>[]>() {}));
}
public void testAssignableClassToType() {
TypeToken<List<String>> tokenL = new TypeToken<List<String>>() {};
- assertTrue(tokenL.isAssignableFrom(StringList.class));
- assertFalse(tokenL.isAssignableFrom(List.class));
+ assertTrue(tokenL.isSupertypeOf(StringList.class));
+ assertFalse(tokenL.isSupertypeOf(List.class));
TypeToken<First<String>> tokenF = new TypeToken<First<String>>() {};
- assertTrue(tokenF.isAssignableFrom(ConcreteIS.class));
- assertFalse(tokenF.isAssignableFrom(ConcreteSI.class));
+ assertTrue(tokenF.isSupertypeOf(ConcreteIS.class));
+ assertFalse(tokenF.isSupertypeOf(ConcreteSI.class));
}
public void testAssignableClassToArrayType() {
TypeToken<List<String>[]> tokenL = new TypeToken<List<String>[]>() {};
- assertTrue(tokenL.isAssignableFrom(StringList[].class));
- assertFalse(tokenL.isAssignableFrom(List[].class));
+ assertTrue(tokenL.isSupertypeOf(StringList[].class));
+ assertFalse(tokenL.isSupertypeOf(List[].class));
}
public void testAssignableParameterizedTypeToType() {
TypeToken<List<String>> tokenL = new TypeToken<List<String>>() {};
- assertTrue(tokenL.isAssignableFrom(
+ assertTrue(tokenL.isSupertypeOf(
StringList.class.getGenericInterfaces()[0]));
- assertFalse(tokenL.isAssignableFrom(
+ assertFalse(tokenL.isSupertypeOf(
IntegerList.class.getGenericInterfaces()[0]));
TypeToken<First<String>> tokenF = new TypeToken<First<String>>() {};
- assertTrue(tokenF.isAssignableFrom(
+ assertTrue(tokenF.isSupertypeOf(
ConcreteIS.class.getGenericSuperclass()));
- assertFalse(tokenF.isAssignableFrom(
+ assertFalse(tokenF.isSupertypeOf(
ConcreteSI.class.getGenericSuperclass()));
}
- public void testGenericArrayTypeToArrayType() throws Exception {
+ public void testGenericArrayTypeToArrayType() {
TypeToken<List<String>[]> tokL = new TypeToken<List<String>[]>() {};
TypeToken<ArrayList<String>[]> token =
new TypeToken<ArrayList<String>[]>() {};
- assertTrue(tokL.isAssignableFrom(tokL.getType()));
- assertTrue(tokL.isAssignableFrom(token.getType()));
+ assertTrue(tokL.isSupertypeOf(tokL.getType()));
+ assertTrue(tokL.isSupertypeOf(token.getType()));
}
public void testAssignableTokenToType() {
TypeToken<List<String>> tokenL = new TypeToken<List<String>>() {};
- assertTrue(tokenL.isAssignableFrom(new TypeToken<List<String>>() {}));
- assertTrue(tokenL.isAssignableFrom(new TypeToken<ArrayList<String>>() {}));
- assertTrue(tokenL.isAssignableFrom(new TypeToken<StringList>() {}));
+ assertTrue(tokenL.isSupertypeOf(new TypeToken<List<String>>() {}));
+ assertTrue(tokenL.isSupertypeOf(new TypeToken<ArrayList<String>>() {}));
+ assertTrue(tokenL.isSupertypeOf(new TypeToken<StringList>() {}));
TypeToken<First<String>> tokenF = new TypeToken<First<String>>() {};
- assertTrue(tokenF.isAssignableFrom(new TypeToken<Second<String>>() {}));
- assertTrue(tokenF.isAssignableFrom(
+ assertTrue(tokenF.isSupertypeOf(new TypeToken<Second<String>>() {}));
+ assertTrue(tokenF.isSupertypeOf(
new TypeToken<Third<String, Integer>>() {}));
- assertFalse(tokenF.isAssignableFrom(
+ assertFalse(tokenF.isSupertypeOf(
new TypeToken<Third<Integer, String>>() {}));
- assertTrue(tokenF.isAssignableFrom(
+ assertTrue(tokenF.isSupertypeOf(
new TypeToken<Fourth<Integer, String>>() {}));
- assertFalse(tokenF.isAssignableFrom(
+ assertFalse(tokenF.isSupertypeOf(
new TypeToken<Fourth<String, Integer>>() {}));
- assertTrue(tokenF.isAssignableFrom(new TypeToken<ConcreteIS>() {}));
- assertFalse(tokenF.isAssignableFrom(new TypeToken<ConcreteSI>() {}));
+ assertTrue(tokenF.isSupertypeOf(new TypeToken<ConcreteIS>() {}));
+ assertFalse(tokenF.isSupertypeOf(new TypeToken<ConcreteSI>() {}));
}
public void testAssignableWithWildcards() {
@@ -754,41 +808,41 @@ public class TypeTokenTest extends TestCase {
concreteToken, subtypeToken, supertypeToken);
for (TypeToken<?> typeToken : allTokens) {
- assertTrue(typeToken.toString(), unboundedToken.isAssignableFrom(typeToken));
+ assertTrue(typeToken.toString(), unboundedToken.isSupertypeOf(typeToken));
}
- assertFalse(upperBoundToken.isAssignableFrom(unboundedToken));
- assertTrue(upperBoundToken.isAssignableFrom(upperBoundToken));
- assertFalse(upperBoundToken.isAssignableFrom(lowerBoundToken));
- assertTrue(upperBoundToken.isAssignableFrom(concreteToken));
- assertTrue(upperBoundToken.isAssignableFrom(subtypeToken));
- assertFalse(upperBoundToken.isAssignableFrom(supertypeToken));
+ assertFalse(upperBoundToken.isSupertypeOf(unboundedToken));
+ assertTrue(upperBoundToken.isSupertypeOf(upperBoundToken));
+ assertFalse(upperBoundToken.isSupertypeOf(lowerBoundToken));
+ assertTrue(upperBoundToken.isSupertypeOf(concreteToken));
+ assertTrue(upperBoundToken.isSupertypeOf(subtypeToken));
+ assertFalse(upperBoundToken.isSupertypeOf(supertypeToken));
- assertFalse(lowerBoundToken.isAssignableFrom(unboundedToken));
- assertFalse(lowerBoundToken.isAssignableFrom(upperBoundToken));
- assertTrue(lowerBoundToken.isAssignableFrom(lowerBoundToken));
- assertTrue(lowerBoundToken.isAssignableFrom(concreteToken));
- assertFalse(lowerBoundToken.isAssignableFrom(subtypeToken));
- assertTrue(lowerBoundToken.isAssignableFrom(supertypeToken));
+ assertFalse(lowerBoundToken.isSupertypeOf(unboundedToken));
+ assertFalse(lowerBoundToken.isSupertypeOf(upperBoundToken));
+ assertTrue(lowerBoundToken.isSupertypeOf(lowerBoundToken));
+ assertTrue(lowerBoundToken.isSupertypeOf(concreteToken));
+ assertFalse(lowerBoundToken.isSupertypeOf(subtypeToken));
+ assertTrue(lowerBoundToken.isSupertypeOf(supertypeToken));
for (TypeToken<?> typeToken : allTokens) {
assertEquals(typeToken.toString(),
- typeToken == concreteToken, concreteToken.isAssignableFrom(typeToken));
+ typeToken == concreteToken, concreteToken.isSupertypeOf(typeToken));
}
for (TypeToken<?> typeToken : allTokens) {
assertEquals(typeToken.toString(),
- typeToken == subtypeToken, subtypeToken.isAssignableFrom(typeToken));
+ typeToken == subtypeToken, subtypeToken.isSupertypeOf(typeToken));
}
for (TypeToken<?> typeToken : allTokens) {
assertEquals(typeToken.toString(),
- typeToken == supertypeToken, supertypeToken.isAssignableFrom(typeToken));
+ typeToken == supertypeToken, supertypeToken.isSupertypeOf(typeToken));
}
}
public <N1 extends Number, N2 extends Number, N11 extends N1>
- void testIsAssignableFrom_typeVariable() {
+ void testisSupertypeOf_typeVariable() {
assertAssignable(TypeToken.of(new TypeCapture<N1>() {}.capture()),
TypeToken.of(new TypeCapture<N1>() {}.capture()));
assertNotAssignable(new TypeToken<List<N11>>() {},
@@ -802,7 +856,7 @@ public class TypeTokenTest extends TestCase {
}
public <N1 extends Number, N2 extends Number, N11 extends N1>
- void testIsAssignableFrom_equalWildcardTypes() {
+ void testisSupertypeOf_equalWildcardTypes() {
assertAssignable(new TypeToken<List<? extends N1>>() {},
new TypeToken<List<? extends N1>>() {});
assertAssignable(new TypeToken<List<? super N1>>() {},
@@ -813,7 +867,7 @@ public class TypeTokenTest extends TestCase {
new TypeToken<List<? super Number>>() {});
}
- public <N> void testIsAssignableFrom_wildcard_noBound() {
+ public <N> void testisSupertypeOf_wildcard_noBound() {
assertAssignable(new TypeToken<List<? super N>>() {},
new TypeToken<List<?>>() {});
assertAssignable(new TypeToken<List<N>>() {},
@@ -821,7 +875,7 @@ public class TypeTokenTest extends TestCase {
}
public <N1 extends Number, N2 extends Number, N11 extends N1>
- void testIsAssignableFrom_wildcardType_upperBoundMatch() {
+ void testisSupertypeOf_wildcardType_upperBoundMatch() {
// ? extends T
assertAssignable(new TypeToken<List<N11>>() {},
new TypeToken<List<? extends N1>>() {});
@@ -840,7 +894,7 @@ public class TypeTokenTest extends TestCase {
}
public <N1 extends Number, N2 extends Number, N11 extends N1>
- void testIsAssignableFrom_wildcardType_lowerBoundMatch() {
+ void testisSupertypeOf_wildcardType_lowerBoundMatch() {
// ? super T
assertAssignable(new TypeToken<List<N1>>() {},
new TypeToken<List<? super N11>>() {});
@@ -863,7 +917,7 @@ public class TypeTokenTest extends TestCase {
}
public <L extends List<R>, R extends List<L>>
- void testIsAssignableFrom_recursiveTypeVariableBounds() {
+ void testisSupertypeOf_recursiveTypeVariableBounds() {
assertAssignable(TypeToken.of(new TypeCapture<L>() {}.capture()),
TypeToken.of(new TypeCapture<L>() {}.capture()));
assertNotAssignable(TypeToken.of(new TypeCapture<R>() {}.capture()),
@@ -872,7 +926,7 @@ public class TypeTokenTest extends TestCase {
new TypeToken<List<R>>() {});
}
- public void testIsAssignableFrom_resolved() {
+ public void testisSupertypeOf_resolved() {
assertFalse(Assignability.of().isAssignable());
assertTrue(new Assignability<Integer, Integer>() {}.isAssignable());
assertTrue(new Assignability<Integer, Object>() {}.isAssignable());
@@ -880,6 +934,14 @@ public class TypeTokenTest extends TestCase {
TypeTokenTest.<Number, Integer>assignabilityTestWithTypeVariables();
}
+ public <From extends String&List<? extends String>>
+ void testMultipleTypeBoundsAssignability() {
+ assertTrue(new Assignability<From, String>() {}.isAssignable());
+ assertFalse(new Assignability<From, Number>() {}.isAssignable());
+ assertTrue(new Assignability<From, Iterable<? extends CharSequence>>() {}.isAssignable());
+ assertFalse(new Assignability<From, Iterable<Object>>() {}.isAssignable());
+ }
+
private static <N1 extends Number, N11 extends N1>
void assignabilityTestWithTypeVariables() {
assertTrue(new Assignability<N11, N1>() {}.isAssignable());
@@ -908,7 +970,7 @@ public class TypeTokenTest extends TestCase {
assertTrue(new TypeToken<T[][]>() {}.isArray());
}
- public void testIsArray_wildcardType() throws Exception {
+ public void testIsArray_wildcardType() {
assertTrue(TypeToken.of(Types.subtypeOf(Object[].class)).isArray());
assertTrue(TypeToken.of(Types.subtypeOf(int[].class)).isArray());
assertFalse(TypeToken.of(Types.subtypeOf(Object.class)).isArray());
@@ -951,7 +1013,7 @@ public class TypeTokenTest extends TestCase {
assertEquals(new TypeToken<T[]>() {}, new TypeToken<T[][]>() {}.getComponentType());
}
- public void testGetComponentType_wildcardType() throws Exception {
+ public void testGetComponentType_wildcardType() {
assertEquals(Types.subtypeOf(Object.class),
TypeToken.of(Types.subtypeOf(Object[].class)).getComponentType().getType());
assertEquals(Types.subtypeOf(Object[].class),
@@ -1003,6 +1065,14 @@ public class TypeTokenTest extends TestCase {
TypeToken.of(ListIterable.class).getSupertype(Iterable.class).getType());
}
+ public <A, T extends Number&Iterable<A>>
+ void testGetSupertype_typeVariableWithMultipleBounds() {
+ assertEquals(Number.class,
+ new TypeToken<T>(getClass()) {}.getSupertype(Number.class).getType());
+ assertEquals(new TypeToken<Iterable<A>>() {},
+ new TypeToken<T>(getClass()) {}.getSupertype(Iterable.class));
+ }
+
public void testGetSupertype_withoutTypeVariable() {
ParameterizedType expectedType = Types.newParameterizedType(Iterable.class,
Types.newParameterizedType(List.class, String.class));
@@ -1160,6 +1230,121 @@ public class TypeTokenTest extends TestCase {
new TypeToken<Iterable<String>[]>() {}.getSubtype(List[].class));
}
+ private static class ForGetSubType {
+
+ private abstract static class TwoTypeArgs<K, V> {
+ class InnerType<K2, V2> {}
+ }
+
+ private abstract static class StringForFirstTypeArg<V> extends TwoTypeArgs<String, V> {
+ class StringInnerType<V> extends InnerType<String, V> {}
+ }
+
+ private abstract static class OuterTypeVar<V>
+ extends StringForFirstTypeArg<List<V>> {}
+
+ private abstract static class SingleGenericExtendsBase<T> extends Base {}
+
+ private abstract static class DoubleGenericExtendsSingleGeneric<T1, T2>
+ extends SingleGenericExtendsBase<T1> {}
+
+ private interface FourTypeArgs<T1, T2, T3, T4> {}
+ private interface ThreeTypeArgs<T1, T2, T3> extends FourTypeArgs<T1, T2, T3, String> {}
+
+ static class BaseWithTypeVar<T> {}
+ static class Outer<O> {
+ class Sub<X> extends BaseWithTypeVar<List<X>> {}
+ class Sub2<Y extends Sub2<Y>> extends BaseWithTypeVar<List<Y>> {}
+ }
+ }
+
+ public void testGetSubtype_toWildcard() {
+ TypeToken<ForGetSubType.TwoTypeArgs<?, ?>> superType =
+ new TypeToken<ForGetSubType.TwoTypeArgs<?, ?>>() {};
+ TypeToken<ForGetSubType.StringForFirstTypeArg<String>> subType =
+ new TypeToken<ForGetSubType.StringForFirstTypeArg<String>>() {};
+ assertTrue(subType.isSubtypeOf(superType));
+ assertEquals(new TypeToken<ForGetSubType.StringForFirstTypeArg<?>>() {},
+ superType.getSubtype(subType.getRawType()));
+ }
+
+ public void testGetSubtype_innerTypeOfGenericClassTranslatesOwnerTypeVars() {
+ TypeToken<ForGetSubType.TwoTypeArgs<?, ?>.InnerType<?, ?>> superType =
+ new TypeToken<ForGetSubType.TwoTypeArgs<?, ?>.InnerType<?, ?>>() {};
+ TypeToken<ForGetSubType.StringForFirstTypeArg<Integer>.StringInnerType<Long>> subType =
+ new TypeToken<ForGetSubType.StringForFirstTypeArg<Integer>.StringInnerType<Long>>() {};
+ assertTrue(subType.isSubtypeOf(superType));
+ TypeToken<ForGetSubType.StringForFirstTypeArg<?>.StringInnerType<?>> expected =
+ new TypeToken<ForGetSubType.StringForFirstTypeArg<?>.StringInnerType<?>>() {};
+ assertEquals(expected, superType.getSubtype(subType.getRawType()));
+ }
+
+ public void testGetSubtype_localTypeTranslatesTypeVar() {
+ class LocalType<T> extends ForGetSubType.TwoTypeArgs<String, String> {}
+
+ TypeToken<ForGetSubType.TwoTypeArgs<String, String>> superType =
+ new TypeToken<ForGetSubType.TwoTypeArgs<String, String>>() {};
+ TypeToken<LocalType<Integer>> subType = new TypeToken<LocalType<Integer>>() {};
+ assertTrue(subType.isSubtypeOf(superType));
+ assertEquals(new TypeToken<LocalType<?>>() {}, superType.getSubtype(subType.getRawType()));
+ }
+
+ public void testGetSubtype_outerTypeVarTranslatesInnerTypeVar() {
+ TypeToken<ForGetSubType.StringForFirstTypeArg<List<?>>> type =
+ new TypeToken<ForGetSubType.StringForFirstTypeArg<List<?>>>() {};
+ assertEquals(new TypeToken<ForGetSubType.OuterTypeVar<?>>() {},
+ type.getSubtype(ForGetSubType.OuterTypeVar.class));
+ }
+
+ public void testGetSubtype_toWildcardWithBounds() {
+ TypeToken<ForGetSubType.TwoTypeArgs<?, ? extends Number>> superType =
+ new TypeToken<ForGetSubType.TwoTypeArgs<?, ? extends Number>>() {};
+ TypeToken<ForGetSubType.StringForFirstTypeArg<Integer>> subType =
+ new TypeToken<ForGetSubType.StringForFirstTypeArg<Integer>>() {};
+ assertTrue(subType.isSubtypeOf(superType));
+
+ // TODO(benyu): This should check equality to an expected value, see discussion in cl/98674873
+ superType.getSubtype(subType.getRawType());
+ }
+
+ public void testGetSubtype_baseClassWithNoTypeArgs() {
+ TypeToken<Base> superType = new TypeToken<Base>() {};
+ TypeToken<ForGetSubType.SingleGenericExtendsBase<String>> subType =
+ new TypeToken<ForGetSubType.SingleGenericExtendsBase<String>>() {};
+ assertTrue(subType.isSubtypeOf(superType));
+ assertEquals(TypeToken.of(ForGetSubType.SingleGenericExtendsBase.class),
+ superType.getSubtype(subType.getRawType()));
+ }
+
+ public void testGetSubtype_baseClassWithLessTypeArgs() {
+ TypeToken<ForGetSubType.SingleGenericExtendsBase<?>> superType =
+ new TypeToken<ForGetSubType.SingleGenericExtendsBase<?>>() {};
+ TypeToken<ForGetSubType.DoubleGenericExtendsSingleGeneric<String, Integer>> subType =
+ new TypeToken<ForGetSubType.DoubleGenericExtendsSingleGeneric<String, Integer>>() {};
+ assertTrue(subType.isSubtypeOf(superType));
+ assertEquals(new TypeToken<ForGetSubType.DoubleGenericExtendsSingleGeneric<?, ?>>() {},
+ superType.getSubtype(subType.getRawType()));
+ }
+
+ public <T> void testGetSubtype_manyGenericArgs() {
+ TypeToken<ForGetSubType.FourTypeArgs<T, Integer, ?, ?>> superType =
+ new TypeToken<ForGetSubType.FourTypeArgs<T, Integer, ?, ?>>() {};
+ TypeToken<ForGetSubType.ThreeTypeArgs<T, Integer, String>> subType =
+ new TypeToken<ForGetSubType.ThreeTypeArgs<T, Integer, String>>() {};
+ assertTrue(subType.isSubtypeOf(superType));
+ assertEquals(new TypeToken<ForGetSubType.ThreeTypeArgs<T, Integer, ?>>() {},
+ superType.getSubtype(subType.getRawType()));
+ }
+
+ public void testGetSubtype_recursiveTypeBoundInSubTypeTranslatedAsIs() {
+ assertEquals(new TypeToken<ForGetSubType.Outer<?>.Sub<?>>() {},
+ new TypeToken<ForGetSubType.BaseWithTypeVar<List<?>>>() {}
+ .getSubtype(ForGetSubType.Outer.Sub.class));
+ // This returns a strange ? extends Sub2<Y> type, which isn't ideal.
+ new TypeToken<ForGetSubType.BaseWithTypeVar<List<?>>>() {}
+ .getSubtype(ForGetSubType.Outer.Sub2.class);
+ }
+
@SuppressWarnings("unchecked") // To construct TypeToken<T> with TypeToken.of()
public <T> void testWhere_circleRejected() {
TypeToken<List<T>> type = new TypeToken<List<T>>() {};
@@ -1195,7 +1380,7 @@ public class TypeTokenTest extends TestCase {
Holder.class.getDeclaredMethod("setList", List.class).getGenericParameterTypes()[0]);
assertEquals(List.class, parameterType.getRawType());
assertFalse(parameterType.getType().toString(),
- parameterType.isAssignableFrom(new TypeToken<List<Integer>>() {}));
+ parameterType.isSupertypeOf(new TypeToken<List<Integer>>() {}));
}
public void testWildcardCaptured_field_upperBound() throws Exception {
@@ -1277,7 +1462,7 @@ public class TypeTokenTest extends TestCase {
throws NoSuchMethodException {
Method failMethod = Loser.class.getMethod("lose");
Invokable<T, ?> invokable = new TypeToken<T>(getClass()) {}.method(failMethod);
- assertThat(invokable.getExceptionTypes()).has().item(TypeToken.of(AssertionError.class));
+ assertThat(invokable.getExceptionTypes()).contains(TypeToken.of(AssertionError.class));
}
public void testConstructor_getOwnerType() throws NoSuchMethodException {
@@ -1343,7 +1528,7 @@ public class TypeTokenTest extends TestCase {
@SuppressWarnings("rawtypes") // Reflection API skew
Constructor<CannotConstruct> constructor = CannotConstruct.class.getConstructor();
Invokable<T, ?> invokable = new TypeToken<T>(getClass()) {}.constructor(constructor);
- assertThat(invokable.getExceptionTypes()).has().item(TypeToken.of(AssertionError.class));
+ assertThat(invokable.getExceptionTypes()).contains(TypeToken.of(AssertionError.class));
}
public void testRejectTypeVariable_class() {
@@ -1429,20 +1614,22 @@ public class TypeTokenTest extends TestCase {
static void verifyConsitentRawType() {
for (Method method : RawTypeConsistencyTester.class.getDeclaredMethods()) {
- assertEquals(method.getReturnType(), TypeToken.getRawType(method.getGenericReturnType()));
+ assertEquals(method.getReturnType(),
+ TypeToken.of(method.getGenericReturnType()).getRawType());
for (int i = 0; i < method.getParameterTypes().length; i++) {
assertEquals(method.getParameterTypes()[i],
- TypeToken.getRawType(method.getGenericParameterTypes()[i]));
+ TypeToken.of(method.getGenericParameterTypes()[i]).getRawType());
}
}
}
}
- public void testRawTypes() throws Exception {
+ public void testRawTypes() {
RawTypeConsistencyTester.verifyConsitentRawType();
- assertEquals(Object.class, TypeToken.getRawType(Types.subtypeOf(Object.class)));
- assertEquals(CharSequence.class, TypeToken.getRawType(Types.subtypeOf(CharSequence.class)));
- assertEquals(Object.class, TypeToken.getRawType(Types.supertypeOf(CharSequence.class)));
+ assertEquals(Object.class, TypeToken.of(Types.subtypeOf(Object.class)).getRawType());
+ assertEquals(CharSequence.class,
+ TypeToken.of(Types.subtypeOf(CharSequence.class)).getRawType());
+ assertEquals(Object.class, TypeToken.of(Types.supertypeOf(CharSequence.class)).getRawType());
}
private abstract static class IKnowMyType<T> {
@@ -1597,7 +1784,7 @@ public class TypeTokenTest extends TestCase {
private static class Assignability<From, To> {
boolean isAssignable() {
- return new TypeToken<To>(getClass()) {}.isAssignableFrom(new TypeToken<From>(getClass()) {});
+ return new TypeToken<To>(getClass()) {}.isSupertypeOf(new TypeToken<From>(getClass()) {});
}
static <From, To> Assignability<From, To> of() {
@@ -1609,12 +1796,24 @@ public class TypeTokenTest extends TestCase {
assertTrue(
from.getType() + " is expected to be assignable to " + to.getType(),
to.isAssignableFrom(from));
+ assertTrue(
+ to.getType() + " is expected to be a supertype of " + from.getType(),
+ to.isSupertypeOf(from));
+ assertTrue(
+ from.getType() + " is expected to be a subtype of " + to.getType(),
+ from.isSubtypeOf(to));
}
private static void assertNotAssignable(TypeToken<?> from, TypeToken<?> to) {
assertFalse(
from.getType() + " shouldn't be assignable to " + to.getType(),
to.isAssignableFrom(from));
+ assertFalse(
+ to.getType() + " shouldn't be a supertype of " + from.getType(),
+ to.isSupertypeOf(from));
+ assertFalse(
+ from.getType() + " shouldn't be a subtype of " + to.getType(),
+ from.isSubtypeOf(to));
}
private static void assertHasArrayInterfaces(TypeToken<?> arrayType) {
@@ -1658,7 +1857,7 @@ public class TypeTokenTest extends TestCase {
private static class Base implements BaseInterface {}
private static class Sub extends Base {}
- private static CollectionSubject<?, Object, ?> makeUnmodifiable(Collection<?> actual) {
+ private static IterableSubject<?, Object, ?> makeUnmodifiable(Collection<?> actual) {
return assertThat(Collections.<Object>unmodifiableCollection(actual));
}
}
diff --git a/guava-tests/test/com/google/common/reflect/TypesTest.java b/guava-tests/test/com/google/common/reflect/TypesTest.java
index 8e223bc..65841b9 100644
--- a/guava-tests/test/com/google/common/reflect/TypesTest.java
+++ b/guava-tests/test/com/google/common/reflect/TypesTest.java
@@ -43,8 +43,8 @@ import java.util.Map;
*
* @author Ben Yu
*/
+ at SuppressUnderAndroid // lots of failures, possibly some related to bad equals() implementations?
public class TypesTest extends TestCase {
-
public void testNewParameterizedType_ownerTypeImplied() throws Exception {
ParameterizedType jvmType = (ParameterizedType)
new TypeCapture<Map.Entry<String, Integer>>() {}.capture();
@@ -66,12 +66,12 @@ public class TypesTest extends TestCase {
assertEquals(jvmType.toString(), ourType.toString());
assertEquals(jvmType.hashCode(), ourType.hashCode());
assertEquals(HashMap.class, ourType.getRawType());
- assertThat(ourType.getActualTypeArguments()).asList()
- .has().exactlyAs(asList(jvmType.getActualTypeArguments())).inOrder();
- assertEquals(Arrays.asList(
- String.class,
- Types.newArrayType(Types.newArrayType(int.class))),
- Arrays.asList(ourType.getActualTypeArguments()));
+ assertThat(ourType.getActualTypeArguments())
+ .asList()
+ .containsExactlyElementsIn(asList(jvmType.getActualTypeArguments()))
+ .inOrder();
+ assertEquals(Arrays.asList(String.class, Types.newArrayType(Types.newArrayType(int.class))),
+ Arrays.asList(ourType.getActualTypeArguments()));
assertEquals(null, ourType.getOwnerType());
}
@@ -107,8 +107,10 @@ public class TypesTest extends TestCase {
assertEquals(jvmType.toString(), ourType.toString());
assertEquals(Map.class, ourType.getOwnerType());
assertEquals(Map.Entry.class, ourType.getRawType());
- assertThat(ourType.getActualTypeArguments()).asList()
- .has().exactlyAs(asList(jvmType.getActualTypeArguments())).inOrder();
+ assertThat(ourType.getActualTypeArguments())
+ .asList()
+ .containsExactlyElementsIn(asList(jvmType.getActualTypeArguments()))
+ .inOrder();
}
public void testNewParameterizedType_serializable() {
@@ -268,10 +270,14 @@ public class TypesTest extends TestCase {
WildcardType expected, WildcardType actual) {
assertEquals(expected.toString(), actual.toString());
assertEquals(actual.toString(), expected.hashCode(), actual.hashCode());
- assertThat(actual.getLowerBounds()).asList()
- .has().exactlyAs(asList(expected.getLowerBounds())).inOrder();
- assertThat(actual.getUpperBounds()).asList()
- .has().exactlyAs(asList(expected.getUpperBounds())).inOrder();
+ assertThat(actual.getLowerBounds())
+ .asList()
+ .containsExactlyElementsIn(asList(expected.getLowerBounds()))
+ .inOrder();
+ assertThat(actual.getUpperBounds())
+ .asList()
+ .containsExactlyElementsIn(asList(expected.getUpperBounds()))
+ .inOrder();
}
private static class WithTypeVariable {
@@ -366,8 +372,10 @@ public class TypesTest extends TestCase {
if (!Types.NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY) {
assertEquals(actual.toString(), expected.hashCode(), actual.hashCode());
}
- assertThat(actual.getBounds()).asList()
- .has().exactlyAs(asList(expected.getBounds())).inOrder();
+ assertThat(actual.getBounds())
+ .asList()
+ .containsExactlyElementsIn(asList(expected.getBounds()))
+ .inOrder();
}
/**
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractAbstractFutureTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractAbstractFutureTest.java
new file mode 100644
index 0000000..2170c85
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractAbstractFutureTest.java
@@ -0,0 +1,490 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.Runnables.doNothing;
+import static com.google.common.util.concurrent.TestPlatform.verifyGetOnPendingFuture;
+import static com.google.common.util.concurrent.TestPlatform.verifyTimedGetOnPendingFuture;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.util.concurrent.AbstractFuture.TrustedFuture;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Base class for tests for emulated {@link AbstractFuture} that allow subclasses to swap in a
+ * different "source Future" for {@link AbstractFuture#setFuture} calls.
+ */
+ at GwtCompatible
+abstract class AbstractAbstractFutureTest extends TestCase {
+ private TestedFuture<Integer> future;
+ private AbstractFuture<Integer> delegate;
+
+ abstract AbstractFuture<Integer> newDelegate();
+
+ @Override
+ protected void setUp() {
+ future = TestedFuture.create();
+ delegate = newDelegate();
+ }
+
+ public void testPending() {
+ assertPending(future);
+ }
+
+ public void testSuccessful() throws Exception {
+ assertThat(future.set(1)).isTrue();
+ assertSuccessful(future, 1);
+ }
+
+ public void testFailed() throws Exception {
+ Exception cause = new Exception();
+ assertThat(future.setException(cause)).isTrue();
+ assertFailed(future, cause);
+ }
+
+ public void testCanceled() throws Exception {
+ assertThat(future.cancel(false /* mayInterruptIfRunning */)).isTrue();
+ assertCancelled(future, false);
+ }
+
+ public void testInterrupted() throws Exception {
+ assertThat(future.cancel(true /* mayInterruptIfRunning */)).isTrue();
+ assertCancelled(future, true);
+ }
+
+ public void testSetFuturePending() throws Exception {
+ assertThat(future.setFuture(delegate)).isTrue();
+ assertSetAsynchronously(future);
+ }
+
+ public void testSetFutureThenCancel() throws Exception {
+ assertThat(future.setFuture(delegate)).isTrue();
+ assertThat(future.cancel(false /* mayInterruptIfRunning */)).isTrue();
+ assertCancelled(future, false);
+ assertCancelled(delegate, false);
+ }
+
+ public void testSetFutureThenInterrupt() throws Exception {
+ assertThat(future.setFuture(delegate)).isTrue();
+ assertThat(future.cancel(true /* mayInterruptIfRunning */)).isTrue();
+ assertCancelled(future, true);
+ assertCancelled(delegate, true);
+ }
+
+ public void testSetFutureDelegateAlreadySuccessful() throws Exception {
+ delegate.set(5);
+ assertThat(future.setFuture(delegate)).isTrue();
+ assertSuccessful(future, 5);
+ }
+
+ public void testSetFutureDelegateLaterSuccessful() throws Exception {
+ assertThat(future.setFuture(delegate)).isTrue();
+ delegate.set(6);
+ assertSuccessful(future, 6);
+ }
+
+ public void testSetFutureDelegateAlreadyCancelled() throws Exception {
+ delegate.cancel(false /** mayInterruptIfRunning */);
+ assertThat(future.setFuture(delegate)).isTrue();
+ assertCancelled(future, false);
+ }
+
+ public void testSetFutureDelegateLaterCancelled() throws Exception {
+ assertThat(future.setFuture(delegate)).isTrue();
+ delegate.cancel(false /** mayInterruptIfRunning */);
+ assertCancelled(future, false);
+ }
+
+ public void testSetFutureDelegateAlreadyInterrupted() throws Exception {
+ delegate.cancel(true /** mayInterruptIfRunning */);
+ assertThat(future.setFuture(delegate)).isTrue();
+ /*
+ * Interruption of the delegate propagates to us only if the delegate was a TrustedFuture.
+ * TODO(cpovirk): Consider whether to stop copying this information from TrustedFuture so that
+ * we're consistent.
+ */
+ assertCancelled(future, delegate instanceof TrustedFuture);
+ }
+
+ public void testSetFutureDelegateLaterInterrupted() throws Exception {
+ assertThat(future.setFuture(delegate)).isTrue();
+ delegate.cancel(true /** mayInterruptIfRunning */);
+ // See previous method doc.
+ assertCancelled(future, delegate instanceof TrustedFuture);
+ }
+
+ public void testListenLaterSuccessful() {
+ CountingRunnable listener = new CountingRunnable();
+
+ future.addListener(listener, directExecutor());
+ listener.assertNotRun();
+
+ future.set(1);
+ listener.assertRun();
+ }
+
+ public void testListenLaterFailed() {
+ CountingRunnable listener = new CountingRunnable();
+
+ future.addListener(listener, directExecutor());
+ listener.assertNotRun();
+
+ future.setException(new Exception());
+ listener.assertRun();
+ }
+
+ public void testListenLaterCancelled() {
+ CountingRunnable listener = new CountingRunnable();
+
+ future.addListener(listener, directExecutor());
+ listener.assertNotRun();
+
+ future.cancel(false);
+ listener.assertRun();
+ }
+
+ public void testListenLaterInterrupted() {
+ CountingRunnable listener = new CountingRunnable();
+
+ future.addListener(listener, directExecutor());
+ listener.assertNotRun();
+
+ future.cancel(true);
+ listener.assertRun();
+ }
+
+ public void testListenLaterSetAsynchronously() {
+ CountingRunnable listener = new CountingRunnable();
+
+ future.addListener(listener, directExecutor());
+ listener.assertNotRun();
+
+ future.setFuture(delegate);
+ listener.assertNotRun();
+ }
+
+ public void testListenLaterSetAsynchronouslyLaterDelegateSuccessful() {
+ CountingRunnable before = new CountingRunnable();
+ CountingRunnable inBetween = new CountingRunnable();
+ CountingRunnable after = new CountingRunnable();
+
+ future.addListener(before, directExecutor());
+ future.setFuture(delegate);
+ future.addListener(inBetween, directExecutor());
+ delegate.set(1);
+ future.addListener(after, directExecutor());
+
+ before.assertRun();
+ inBetween.assertRun();
+ after.assertRun();
+ }
+
+ public void testListenLaterSetAsynchronouslyLaterDelegateFailed() {
+ CountingRunnable before = new CountingRunnable();
+ CountingRunnable inBetween = new CountingRunnable();
+ CountingRunnable after = new CountingRunnable();
+
+ future.addListener(before, directExecutor());
+ future.setFuture(delegate);
+ future.addListener(inBetween, directExecutor());
+ delegate.setException(new Exception());
+ future.addListener(after, directExecutor());
+
+ before.assertRun();
+ inBetween.assertRun();
+ after.assertRun();
+ }
+
+ public void testListenLaterSetAsynchronouslyLaterDelegateCancelled() {
+ CountingRunnable before = new CountingRunnable();
+ CountingRunnable inBetween = new CountingRunnable();
+ CountingRunnable after = new CountingRunnable();
+
+ future.addListener(before, directExecutor());
+ future.setFuture(delegate);
+ future.addListener(inBetween, directExecutor());
+ delegate.cancel(false);
+ future.addListener(after, directExecutor());
+
+ before.assertRun();
+ inBetween.assertRun();
+ after.assertRun();
+ }
+
+ public void testListenLaterSetAsynchronouslyLaterDelegateInterrupted() {
+ CountingRunnable before = new CountingRunnable();
+ CountingRunnable inBetween = new CountingRunnable();
+ CountingRunnable after = new CountingRunnable();
+
+ future.addListener(before, directExecutor());
+ future.setFuture(delegate);
+ future.addListener(inBetween, directExecutor());
+ delegate.cancel(true);
+ future.addListener(after, directExecutor());
+
+ before.assertRun();
+ inBetween.assertRun();
+ after.assertRun();
+ }
+
+ public void testListenLaterSetAsynchronouslyLaterSelfCancelled() {
+ CountingRunnable before = new CountingRunnable();
+ CountingRunnable inBetween = new CountingRunnable();
+ CountingRunnable after = new CountingRunnable();
+
+ future.addListener(before, directExecutor());
+ future.setFuture(delegate);
+ future.addListener(inBetween, directExecutor());
+ future.cancel(false);
+ future.addListener(after, directExecutor());
+
+ before.assertRun();
+ inBetween.assertRun();
+ after.assertRun();
+ }
+
+ public void testListenLaterSetAsynchronouslyLaterSelfInterrupted() {
+ CountingRunnable before = new CountingRunnable();
+ CountingRunnable inBetween = new CountingRunnable();
+ CountingRunnable after = new CountingRunnable();
+
+ future.addListener(before, directExecutor());
+ future.setFuture(delegate);
+ future.addListener(inBetween, directExecutor());
+ future.cancel(true);
+ future.addListener(after, directExecutor());
+
+ before.assertRun();
+ inBetween.assertRun();
+ after.assertRun();
+ }
+
+ public void testMisbehavingListenerAlreadyDone() {
+ class BadRunnableException extends RuntimeException {
+ }
+
+ Runnable bad = new Runnable() {
+ @Override
+ public void run() {
+ throw new BadRunnableException();
+ }
+ };
+
+ future.set(1);
+ future.addListener(bad, directExecutor()); // BadRunnableException must not propagate.
+ }
+
+ public void testMisbehavingListenerLaterDone() {
+ class BadRunnableException extends RuntimeException {
+ }
+
+ CountingRunnable before = new CountingRunnable();
+ Runnable bad = new Runnable() {
+ @Override
+ public void run() {
+ throw new BadRunnableException();
+ }
+ };
+ CountingRunnable after = new CountingRunnable();
+
+ future.addListener(before, directExecutor());
+ future.addListener(bad, directExecutor());
+ future.addListener(after, directExecutor());
+
+ future.set(1); // BadRunnableException must not propagate.
+
+ before.assertRun();
+ after.assertRun();
+ }
+
+ public void testNullListener() {
+ try {
+ future.addListener(null, directExecutor());
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testNullExecutor() {
+ try {
+ future.addListener(doNothing(), null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testNullTimeUnit() throws Exception {
+ future.set(1);
+ try {
+ future.get(0, null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testSetNull() throws Exception {
+ future.set(null);
+ assertSuccessful(future, null);
+ }
+
+ public void testSetExceptionNull() throws Exception {
+ try {
+ future.setException(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ assertThat(future.isDone()).isFalse();
+ assertThat(future.set(1)).isTrue();
+ assertSuccessful(future, 1);
+ }
+
+ public void testSetFutureNull() throws Exception {
+ try {
+ future.setFuture(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ assertThat(future.isDone()).isFalse();
+ assertThat(future.set(1)).isTrue();
+ assertSuccessful(future, 1);
+ }
+
+ /**
+ * Concrete subclass for testing.
+ */
+ private static class TestedFuture<V> extends AbstractFuture<V> {
+ private static <V> TestedFuture<V> create() {
+ return new TestedFuture<V>();
+ }
+ }
+
+ private static final class CountingRunnable implements Runnable {
+ int count;
+
+ @Override
+ public void run() {
+ count++;
+ }
+
+ void assertNotRun() {
+ assertEquals(0, count);
+ }
+
+ void assertRun() {
+ assertEquals(1, count);
+ }
+ }
+
+ private static void assertSetAsynchronously(AbstractFuture<Integer> future) {
+ assertCannotSet(future);
+ assertPending(future);
+ }
+
+ private static void assertPending(AbstractFuture<Integer> future) {
+ assertThat(future.isDone()).isFalse();
+ assertThat(future.isCancelled()).isFalse();
+
+ CountingRunnable listener = new CountingRunnable();
+ future.addListener(listener, directExecutor());
+ listener.assertNotRun();
+
+ verifyGetOnPendingFuture(future);
+ verifyTimedGetOnPendingFuture(future);
+ }
+
+ private static void assertSuccessful(AbstractFuture<Integer> future, Integer expectedResult)
+ throws InterruptedException, TimeoutException, ExecutionException {
+ assertDone(future);
+ assertThat(future.isCancelled()).isFalse();
+
+ assertThat(future.get()).isEqualTo(expectedResult);
+ assertThat(future.get(0, SECONDS)).isEqualTo(expectedResult);
+ assertThat(future.get(-1, SECONDS)).isEqualTo(expectedResult);
+ }
+
+ private static void assertFailed(AbstractFuture<Integer> future, Throwable expectedException)
+ throws InterruptedException, TimeoutException {
+ assertDone(future);
+ assertThat(future.isCancelled()).isFalse();
+
+ try {
+ future.get();
+ fail();
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isSameAs(expectedException);
+ }
+
+ try {
+ future.get(0, SECONDS);
+ fail();
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isSameAs(expectedException);
+ }
+ }
+
+ private static void assertCancelled(AbstractFuture<Integer> future, boolean expectWasInterrupted)
+ throws InterruptedException, TimeoutException, ExecutionException {
+ assertDone(future);
+ assertThat(future.isCancelled()).isTrue();
+ assertThat(future.wasInterrupted()).isEqualTo(expectWasInterrupted);
+
+ try {
+ future.get();
+ fail();
+ } catch (CancellationException expected) {
+ }
+
+ try {
+ future.get(0, SECONDS);
+ fail();
+ } catch (CancellationException expected) {
+ }
+ }
+
+ private static void assertDone(AbstractFuture<Integer> future) {
+ CountingRunnable listener = new CountingRunnable();
+ future.addListener(listener, directExecutor());
+ listener.assertRun();
+
+ assertThat(future.isDone()).isTrue();
+ assertCannotSet(future);
+ assertCannotCancel(future);
+ }
+
+ private static void assertCannotSet(AbstractFuture<Integer> future) {
+ assertThat(future.set(99)).isFalse();
+ assertThat(future.setException(new IndexOutOfBoundsException())).isFalse();
+ assertThat(future.setFuture(new AbstractFuture<Integer>() {})).isFalse();
+ assertThat(future.setFuture(immediateFuture(99))).isFalse();
+ }
+
+ private static void assertCannotCancel(AbstractFuture<Integer> future) {
+ assertThat(future.cancel(true)).isFalse();
+ assertThat(future.cancel(false)).isFalse();
+ }
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractExecutionThreadServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractExecutionThreadServiceTest.java
index b30d531..587ff26 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractExecutionThreadServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractExecutionThreadServiceTest.java
@@ -16,8 +16,11 @@
package com.google.common.util.concurrent;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.testing.TearDown;
import com.google.common.testing.TearDownStack;
+import com.google.common.util.concurrent.testing.TestingExecutors;
import junit.framework.TestCase;
@@ -26,6 +29,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -58,6 +62,8 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
@Override protected final void tearDown() {
tearDownStack.runTearDown();
+ assertNull("exceptions should not be propagated to uncaught exception handlers",
+ thrownByExecutionThread);
}
public void testServiceStartStop() throws Exception {
@@ -74,7 +80,6 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
assertTrue(service.shutDownCalled);
assertEquals(Service.State.TERMINATED, service.state());
executionThread.join();
- assertNull(thrownByExecutionThread);
}
public void testServiceStopIdempotence() throws Exception {
@@ -91,7 +96,6 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
assertEquals(Service.State.TERMINATED, service.state());
executionThread.join();
- assertNull(thrownByExecutionThread);
}
public void testServiceExitingOnItsOwn() throws Exception {
@@ -107,7 +111,6 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
assertTrue(service.shutDownCalled);
assertEquals(Service.State.TERMINATED, service.state());
- assertNull(thrownByExecutionThread);
service.stopAsync().awaitTerminated(); // no-op
assertEquals(Service.State.TERMINATED, service.state());
@@ -169,13 +172,13 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
service.awaitRunning();
fail();
} catch (IllegalStateException expected) {
- assertEquals("kaboom!", expected.getCause().getMessage());
+ assertThat(expected.getCause()).hasMessage("kaboom!");
}
executionThread.join();
assertTrue(service.startUpCalled);
assertEquals(Service.State.FAILED, service.state());
- assertTrue(thrownByExecutionThread.getMessage().equals("kaboom!"));
+ assertThat(service.failureCause()).hasMessage("kaboom!");
}
private class ThrowOnStartUpService extends AbstractExecutionThreadService {
@@ -204,11 +207,11 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
fail();
} catch (IllegalStateException expected) {
executionThread.join();
- assertEquals(thrownByExecutionThread, expected.getCause());
+ assertEquals(service.failureCause(), expected.getCause());
+ assertThat(expected.getCause()).hasMessage("kaboom!");
}
assertTrue(service.shutDownCalled);
assertEquals(Service.State.FAILED, service.state());
- assertEquals("kaboom!", thrownByExecutionThread.getMessage());
}
public void testServiceThrowOnRunAndThenAgainOnShutDown() throws Exception {
@@ -221,12 +224,12 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
fail();
} catch (IllegalStateException expected) {
executionThread.join();
- assertEquals(thrownByExecutionThread, expected.getCause());
+ assertEquals(service.failureCause(), expected.getCause());
+ assertThat(expected.getCause()).hasMessage("kaboom!");
}
assertTrue(service.shutDownCalled);
assertEquals(Service.State.FAILED, service.state());
- assertEquals("kaboom!", thrownByExecutionThread.getMessage());
}
private class ThrowOnRunService extends AbstractExecutionThreadService {
@@ -260,7 +263,7 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
executionThread.join();
assertEquals(Service.State.FAILED, service.state());
- assertEquals("kaboom!", thrownByExecutionThread.getMessage());
+ assertThat(service.failureCause()).hasMessage("kaboom!");
}
private class ThrowOnShutDown extends AbstractExecutionThreadService {
@@ -288,7 +291,7 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
service.startAsync().awaitRunning(1, TimeUnit.MILLISECONDS);
fail();
} catch (TimeoutException e) {
- assertTrue(e.getMessage().contains(Service.State.STARTING.toString()));
+ assertThat(e.getMessage()).contains(Service.State.STARTING.toString());
}
}
@@ -339,6 +342,27 @@ public class AbstractExecutionThreadServiceTest extends TestCase {
service.stopAsync().awaitTerminated();
}
+ public void testTimeout() {
+ // Create a service whose executor will never run its commands
+ Service service = new AbstractExecutionThreadService() {
+ @Override protected void run() throws Exception {}
+
+ @Override protected ScheduledExecutorService executor() {
+ return TestingExecutors.noOpScheduledExecutor();
+ }
+
+ @Override protected String serviceName() {
+ return "Foo";
+ }
+ };
+ try {
+ service.startAsync().awaitRunning(1, TimeUnit.MILLISECONDS);
+ fail("Expected timeout");
+ } catch (TimeoutException e) {
+ assertThat(e).hasMessage("Timed out waiting for Foo [STARTING] to reach the RUNNING state.");
+ }
+ }
+
private class FakeService extends AbstractExecutionThreadService implements TearDown {
private final ExecutorService executor = Executors.newSingleThreadExecutor();
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureBenchmarks.java b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureBenchmarks.java
new file mode 100644
index 0000000..fe48ff4
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureBenchmarks.java
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+
+import javax.annotation.Nullable;
+
+/**
+ * Utilities for the AbstractFutureBenchmarks
+ */
+final class AbstractFutureBenchmarks {
+ private AbstractFutureBenchmarks() {}
+
+ interface Facade<T> extends ListenableFuture<T> {
+ boolean set(T t);
+ boolean setException(Throwable t);
+ }
+
+ private static class NewAbstractFutureFacade<T> extends AbstractFuture<T> implements Facade<T> {
+ @Override public boolean set(T t) {
+ return super.set(t);
+ }
+ @Override public boolean setException(Throwable t) {
+ return super.setException(t);
+ }
+ }
+
+ private static class OldAbstractFutureFacade<T>
+ extends OldAbstractFuture<T> implements Facade<T> {
+ @Override public boolean set(T t) {
+ return super.set(t);
+ }
+ @Override public boolean setException(Throwable t) {
+ return super.setException(t);
+ }
+ }
+
+ enum Impl {
+ NEW {
+ @Override <T> Facade<T> newFacade() {
+ return new NewAbstractFutureFacade<T>();
+ }
+ },
+ OLD {
+ @Override <T> Facade<T> newFacade() {
+ return new OldAbstractFutureFacade<T>();
+ }
+ };
+
+ abstract <T> Facade<T> newFacade();
+ }
+
+ static void awaitWaiting(Thread t) {
+ while (true) {
+ Thread.State state = t.getState();
+ switch (state) {
+ case RUNNABLE:
+ case BLOCKED:
+ Thread.yield();
+ break;
+ case WAITING:
+ return;
+ default:
+ throw new AssertionError("unexpected state: " + state);
+ }
+ }
+ }
+
+ abstract static class OldAbstractFuture<V> implements ListenableFuture<V> {
+
+ /** Synchronization control for AbstractFutures. */
+ private final Sync<V> sync = new Sync<V>();
+
+ // The execution list to hold our executors.
+ private final ExecutionList executionList = new ExecutionList();
+
+ /**
+ * Constructor for use by subclasses.
+ */
+ protected OldAbstractFuture() {}
+
+ /*
+ * Improve the documentation of when InterruptedException is thrown. Our
+ * behavior matches the JDK's, but the JDK's documentation is misleading.
+ */
+ /**
+ * {@inheritDoc}
+ *
+ * <p>The default {@link AbstractFuture} implementation throws {@code
+ * InterruptedException} if the current thread is interrupted before or during
+ * the call, even if the value is already available.
+ *
+ * @throws InterruptedException if the current thread was interrupted before
+ * or during the call (optional but recommended).
+ * @throws CancellationException {@inheritDoc}
+ */
+ @Override
+ public V get(long timeout, TimeUnit unit) throws InterruptedException,
+ TimeoutException, ExecutionException {
+ return sync.get(unit.toNanos(timeout));
+ }
+
+ /*
+ * Improve the documentation of when InterruptedException is thrown. Our
+ * behavior matches the JDK's, but the JDK's documentation is misleading.
+ */
+ /**
+ * {@inheritDoc}
+ *
+ * <p>The default {@link AbstractFuture} implementation throws {@code
+ * InterruptedException} if the current thread is interrupted before or during
+ * the call, even if the value is already available.
+ *
+ * @throws InterruptedException if the current thread was interrupted before
+ * or during the call (optional but recommended).
+ * @throws CancellationException {@inheritDoc}
+ */
+ @Override
+ public V get() throws InterruptedException, ExecutionException {
+ return sync.get();
+ }
+
+ @Override
+ public boolean isDone() {
+ return sync.isDone();
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return sync.isCancelled();
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ if (!sync.cancel(mayInterruptIfRunning)) {
+ return false;
+ }
+ executionList.execute();
+ if (mayInterruptIfRunning) {
+ interruptTask();
+ }
+ return true;
+ }
+
+ /**
+ * Subclasses can override this method to implement interruption of the
+ * future's computation. The method is invoked automatically by a successful
+ * call to {@link #cancel(boolean) cancel(true)}.
+ *
+ * <p>The default implementation does nothing.
+ *
+ * @since 10.0
+ */
+ protected void interruptTask() {
+ }
+
+ /**
+ * Returns true if this future was cancelled with {@code
+ * mayInterruptIfRunning} set to {@code true}.
+ *
+ * @since 14.0
+ */
+ protected final boolean wasInterrupted() {
+ return sync.wasInterrupted();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 10.0
+ */
+ @Override
+ public void addListener(Runnable listener, Executor exec) {
+ executionList.add(listener, exec);
+ }
+
+ /**
+ * Subclasses should invoke this method to set the result of the computation
+ * to {@code value}. This will set the state of the future to
+ * {@link OldAbstractFuture.Sync#COMPLETED} and invoke the listeners if the
+ * state was successfully changed.
+ *
+ * @param value the value that was the result of the task.
+ * @return true if the state was successfully changed.
+ */
+ protected boolean set(@Nullable V value) {
+ boolean result = sync.set(value);
+ if (result) {
+ executionList.execute();
+ }
+ return result;
+ }
+
+ /**
+ * Subclasses should invoke this method to set the result of the computation
+ * to an error, {@code throwable}. This will set the state of the future to
+ * {@link OldAbstractFuture.Sync#COMPLETED} and invoke the listeners if the
+ * state was successfully changed.
+ *
+ * @param throwable the exception that the task failed with.
+ * @return true if the state was successfully changed.
+ */
+ protected boolean setException(Throwable throwable) {
+ boolean result = sync.setException(checkNotNull(throwable));
+ if (result) {
+ executionList.execute();
+ }
+ return result;
+ }
+
+ /**
+ * <p>Following the contract of {@link AbstractQueuedSynchronizer} we create a
+ * private subclass to hold the synchronizer. This synchronizer is used to
+ * implement the blocking and waiting calls as well as to handle state changes
+ * in a thread-safe manner. The current state of the future is held in the
+ * Sync state, and the lock is released whenever the state changes to
+ * {@link #COMPLETED}, {@link #CANCELLED}, or {@link #INTERRUPTED}
+ *
+ * <p>To avoid races between threads doing release and acquire, we transition
+ * to the final state in two steps. One thread will successfully CAS from
+ * RUNNING to COMPLETING, that thread will then set the result of the
+ * computation, and only then transition to COMPLETED, CANCELLED, or
+ * INTERRUPTED.
+ *
+ * <p>We don't use the integer argument passed between acquire methods so we
+ * pass around a -1 everywhere.
+ */
+ static final class Sync<V> extends AbstractQueuedSynchronizer {
+
+ private static final long serialVersionUID = 0L;
+
+ /* Valid states. */
+ static final int RUNNING = 0;
+ static final int COMPLETING = 1;
+ static final int COMPLETED = 2;
+ static final int CANCELLED = 4;
+ static final int INTERRUPTED = 8;
+
+ private V value;
+ private Throwable exception;
+
+ /*
+ * Acquisition succeeds if the future is done, otherwise it fails.
+ */
+ @Override
+ protected int tryAcquireShared(int ignored) {
+ if (isDone()) {
+ return 1;
+ }
+ return -1;
+ }
+
+ /*
+ * We always allow a release to go through, this means the state has been
+ * successfully changed and the result is available.
+ */
+ @Override
+ protected boolean tryReleaseShared(int finalState) {
+ setState(finalState);
+ return true;
+ }
+
+ /**
+ * Blocks until the task is complete or the timeout expires. Throws a
+ * {@link TimeoutException} if the timer expires, otherwise behaves like
+ * {@link #get()}.
+ */
+ V get(long nanos) throws TimeoutException, CancellationException,
+ ExecutionException, InterruptedException {
+
+ // Attempt to acquire the shared lock with a timeout.
+ if (!tryAcquireSharedNanos(-1, nanos)) {
+ throw new TimeoutException("Timeout waiting for task.");
+ }
+
+ return getValue();
+ }
+
+ /**
+ * Blocks until {@link #complete(Object, Throwable, int)} has been
+ * successfully called. Throws a {@link CancellationException} if the task
+ * was cancelled, or a {@link ExecutionException} if the task completed with
+ * an error.
+ */
+ V get() throws CancellationException, ExecutionException,
+ InterruptedException {
+
+ // Acquire the shared lock allowing interruption.
+ acquireSharedInterruptibly(-1);
+ return getValue();
+ }
+
+ /**
+ * Implementation of the actual value retrieval. Will return the value
+ * on success, an exception on failure, a cancellation on cancellation, or
+ * an illegal state if the synchronizer is in an invalid state.
+ */
+ private V getValue() throws CancellationException, ExecutionException {
+ int state = getState();
+ switch (state) {
+ case COMPLETED:
+ if (exception != null) {
+ throw new ExecutionException(exception);
+ } else {
+ return value;
+ }
+
+ case CANCELLED:
+ case INTERRUPTED:
+ throw cancellationExceptionWithCause(
+ "Task was cancelled.", exception);
+
+ default:
+ throw new IllegalStateException(
+ "Error, synchronizer in invalid state: " + state);
+ }
+ }
+
+ /**
+ * Checks if the state is {@link #COMPLETED}, {@link #CANCELLED}, or {@link #INTERRUPTED}.
+ */
+ boolean isDone() {
+ return (getState() & (COMPLETED | CANCELLED | INTERRUPTED)) != 0;
+ }
+
+ /**
+ * Checks if the state is {@link #CANCELLED} or {@link #INTERRUPTED}.
+ */
+ boolean isCancelled() {
+ return (getState() & (CANCELLED | INTERRUPTED)) != 0;
+ }
+
+ /**
+ * Checks if the state is {@link #INTERRUPTED}.
+ */
+ boolean wasInterrupted() {
+ return getState() == INTERRUPTED;
+ }
+
+ /**
+ * Transition to the COMPLETED state and set the value.
+ */
+ boolean set(@Nullable V v) {
+ return complete(v, null, COMPLETED);
+ }
+
+ /**
+ * Transition to the COMPLETED state and set the exception.
+ */
+ boolean setException(Throwable t) {
+ return complete(null, t, COMPLETED);
+ }
+
+ /**
+ * Transition to the CANCELLED or INTERRUPTED state.
+ */
+ boolean cancel(boolean interrupt) {
+ return complete(null, null, interrupt ? INTERRUPTED : CANCELLED);
+ }
+
+ /**
+ * Implementation of completing a task. Either {@code v} or {@code t} will
+ * be set but not both. The {@code finalState} is the state to change to
+ * from {@link #RUNNING}. If the state is not in the RUNNING state we
+ * return {@code false} after waiting for the state to be set to a valid
+ * final state ({@link #COMPLETED}, {@link #CANCELLED}, or {@link
+ * #INTERRUPTED}).
+ *
+ * @param v the value to set as the result of the computation.
+ * @param t the exception to set as the result of the computation.
+ * @param finalState the state to transition to.
+ */
+ private boolean complete(@Nullable V v, @Nullable Throwable t,
+ int finalState) {
+ boolean doCompletion = compareAndSetState(RUNNING, COMPLETING);
+ if (doCompletion) {
+ // If this thread successfully transitioned to COMPLETING, set the value
+ // and exception and then release to the final state.
+ this.value = v;
+ // Don't actually construct a CancellationException until necessary.
+ this.exception = ((finalState & (CANCELLED | INTERRUPTED)) != 0)
+ ? new CancellationException("Future.cancel() was called.") : t;
+ releaseShared(finalState);
+ } else if (getState() == COMPLETING) {
+ // If some other thread is currently completing the future, block until
+ // they are done so we can guarantee completion.
+ acquireShared(-1);
+ }
+ return doCompletion;
+ }
+ }
+
+ static final CancellationException cancellationExceptionWithCause(
+ @Nullable String message, @Nullable Throwable cause) {
+ CancellationException exception = new CancellationException(message);
+ exception.initCause(cause);
+ return exception;
+ }
+ }
+}
+
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java
new file mode 100644
index 0000000..f24f340
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import junit.framework.TestCase;
+
+import java.net.URLClassLoader;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.Future;
+
+/**
+ * Tests for {@link AbstractFuture} with the cancellation cause system property set
+ */
+
+public class AbstractFutureCancellationCauseTest extends TestCase {
+
+ private ClassLoader oldClassLoader;
+ private URLClassLoader classReloader;
+
+ @Override protected void setUp() throws Exception {
+ SettableFuture.create();
+ // Hack to load AbstractFuture et. al. in a new classloader so that it re-reads the cancellation
+ // cause system property. This allows us to run with both settings of the property in one jvm
+ // without resorting to even crazier hacks to reset static final boolean fields.
+ System.setProperty("guava.concurrent.generate_cancellation_cause", "true");
+ final String concurrentPackage = SettableFuture.class.getPackage().getName();
+ classReloader =
+ new URLClassLoader(((URLClassLoader) SettableFuture.class.getClassLoader()).getURLs()) {
+ @Override public Class<?> loadClass(String name) throws ClassNotFoundException {
+ if (name.startsWith(concurrentPackage)) {
+ return super.findClass(name);
+ }
+ return super.loadClass(name);
+ }
+ };
+ oldClassLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(classReloader);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ classReloader.close();
+ Thread.currentThread().setContextClassLoader(oldClassLoader);
+ System.clearProperty("guava.concurrent.generate_cancellation_cause");
+ }
+
+ public void testCancel_notDoneNoInterrupt() throws Exception {
+ Future<?> future = newFutureInstance();
+ assertTrue(future.cancel(false));
+ assertTrue(future.isCancelled());
+ assertTrue(future.isDone());
+ try {
+ future.get();
+ fail("Expected CancellationException");
+ } catch (CancellationException e) {
+ assertNotNull(e.getCause());
+ }
+ }
+
+ public void testCancel_notDoneInterrupt() throws Exception {
+ Future<?> future = newFutureInstance();
+ assertTrue(future.cancel(true));
+ assertTrue(future.isCancelled());
+ assertTrue(future.isDone());
+ try {
+ future.get();
+ fail("Expected CancellationException");
+ } catch (CancellationException e) {
+ assertNotNull(e.getCause());
+ }
+ }
+
+ private Future<?> newFutureInstance() throws Exception {
+ return (Future<?>)
+ classReloader.loadClass(SettableFuture.class.getName()).getMethod("create").invoke(null);
+ }
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureFallbackAtomicHelperTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureFallbackAtomicHelperTest.java
new file mode 100644
index 0000000..fc0bcf2
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureFallbackAtomicHelperTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.collect.ImmutableSet;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.URLClassLoader;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+/**
+ * Tests our AtomicHelper fallback strategies in AbstractFuture.
+ *
+ * <p>On different platforms AbstractFuture uses different strategies for its core synchronization
+ * primitives. The strategies are all implemented as subtypes of AtomicHelper and the strategy is
+ * selected in the static initializer of AbstractFuture. This is convenient and performant but
+ * introduces some testing difficulties. This test exercises the two fallback strategies in
+ * abstract future.
+ * <ul>
+ * <li>SafeAtomicHelper: uses AtomicReferenceFieldsUpdaters to implement synchronization
+ * <li>SynchronizedHelper: uses {@code synchronized} blocks for synchronization
+ * </ul>
+ *
+ * To force selection of our fallback strategies we load {@link AbstractFuture} (and all of
+ * {@code com.google.common.util.concurrent} in degenerate class loaders which make certain platform
+ * classes unavailable. Then we construct a test suite so we can run the normal AbstractFutureTest
+ * test methods in these degenerate classloaders.
+ */
+
+public class AbstractFutureFallbackAtomicHelperTest extends TestCase {
+
+ // stash these in static fields to avoid loading them over and over again (speeds up test
+ // execution significantly)
+
+ /**
+ * This classloader blacklists sun.misc.Unsafe which will prevent us from selecting our preferred
+ * strategy {@code UnsafeAtomicHelper}.
+ */
+ private static final ClassLoader NO_UNSAFE =
+ getClassLoader(ImmutableSet.of(sun.misc.Unsafe.class.getName()));
+
+ /**
+ * This classloader blacklists sun.misc.Unsafe and AtomicReferenceFieldUpdater which will prevent
+ * us from selecting our {@code SafeAtomicHelper} strategy.
+ */
+ private static final ClassLoader NO_ATOMIC_REFERENCE_FIELD_UPDATER =
+ getClassLoader(
+ ImmutableSet.of(
+ sun.misc.Unsafe.class.getName(), AtomicReferenceFieldUpdater.class.getName()));
+
+ public static TestSuite suite() {
+ // we create a test suite containing a test for every AbstractFutureTest test method and we
+ // set it as the name of the test. Then in runTest we can reflectively load and invoke the
+ // corresponding method on AbstractFutureTest in the correct classloader.
+ TestSuite suite = new TestSuite(AbstractFutureFallbackAtomicHelperTest.class.getName());
+ for (Method method : AbstractFutureTest.class.getDeclaredMethods()) {
+ if (Modifier.isPublic(method.getModifiers()) && method.getName().startsWith("test")) {
+ suite.addTest(
+ TestSuite.createTest(AbstractFutureFallbackAtomicHelperTest.class, method.getName()));
+ }
+ }
+ return suite;
+ }
+
+ @Override
+ public void runTest() throws Exception {
+ // First ensure that our classloaders are intializing the correct helper versions
+ checkHelperVersion(getClass().getClassLoader(), "UnsafeAtomicHelper");
+ checkHelperVersion(NO_UNSAFE, "SafeAtomicHelper");
+ checkHelperVersion(NO_ATOMIC_REFERENCE_FIELD_UPDATER, "SynchronizedHelper");
+
+ // Run the corresponding AbstractFutureTest test method in a new classloader that blacklists
+ // certain core jdk classes.
+ ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(NO_UNSAFE);
+ try {
+ runTestMethod(NO_UNSAFE);
+ } finally {
+ Thread.currentThread().setContextClassLoader(oldClassLoader);
+ }
+
+ Thread.currentThread().setContextClassLoader(NO_ATOMIC_REFERENCE_FIELD_UPDATER);
+ try {
+ runTestMethod(NO_ATOMIC_REFERENCE_FIELD_UPDATER);
+ // TODO(lukes): assert that the logs are full of errors
+ } finally {
+ Thread.currentThread().setContextClassLoader(oldClassLoader);
+ }
+ }
+
+ private void runTestMethod(ClassLoader classLoader) throws Exception {
+ Class<?> test = classLoader.loadClass(AbstractFutureTest.class.getName());
+ test.getMethod(getName()).invoke(test.newInstance());
+ }
+
+ private void checkHelperVersion(ClassLoader classLoader, String expectedHelperClassName)
+ throws Exception {
+ // Make sure we are actually running with the expected helper implementation
+ Class<?> abstractFutureClass = classLoader.loadClass(AbstractFuture.class.getName());
+ Field helperField = abstractFutureClass.getDeclaredField("ATOMIC_HELPER");
+ helperField.setAccessible(true);
+ assertEquals(expectedHelperClassName, helperField.get(null).getClass().getSimpleName());
+ }
+
+ private static ClassLoader getClassLoader(final Set<String> blacklist) {
+ final String concurrentPackage = SettableFuture.class.getPackage().getName();
+ ClassLoader classLoader = AbstractFutureFallbackAtomicHelperTest.class.getClassLoader();
+ return
+ // we delegate to the current classloader so both loaders agree on classes like TestCase
+ new URLClassLoader(((URLClassLoader) classLoader).getURLs(), classLoader) {
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ if (blacklist.contains(name)) {
+ throw new ClassNotFoundException("I'm sorry Dave, I'm afraid I can't do that.");
+ }
+ if (name.startsWith(concurrentPackage)) {
+ Class<?> c = findLoadedClass(name);
+ if (c == null) {
+ return super.findClass(name);
+ }
+ return c;
+ }
+ return super.loadClass(name);
+ }
+ };
+ }
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java
index 166be3d..f5c5ff0 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java
@@ -18,14 +18,32 @@ package com.google.common.util.concurrent;
import static com.google.common.truth.Truth.assertThat;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Range;
+import com.google.common.collect.Sets;
+
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.LockSupport;
/**
* Tests for {@link AbstractFuture}.
@@ -75,7 +93,8 @@ public class AbstractFutureTest extends TestCase {
future.get();
fail("Expected CancellationException");
} catch (CancellationException e) {
- assertNotNull(e.getCause());
+ // See AbstractFutureCancellationCauseTest for how to set causes
+ assertNull(e.getCause());
}
}
@@ -90,7 +109,8 @@ public class AbstractFutureTest extends TestCase {
future.get();
fail("Expected CancellationException");
} catch (CancellationException e) {
- assertNotNull(e.getCause());
+ // See AbstractFutureCancellationCauseTest for how to set causes
+ assertNull(e.getCause());
}
}
@@ -105,11 +125,86 @@ public class AbstractFutureTest extends TestCase {
assertTrue(future.isDone());
}
+ public void testGetWithTimeoutDoneFuture() throws Exception {
+ AbstractFuture<String> future = new AbstractFuture<String>() {
+ {
+ set("foo");
+ }
+ };
+ assertEquals("foo", future.get(0, TimeUnit.SECONDS));
+ }
+
+ public void testEvilFuture_setFuture() throws Exception {
+ final RuntimeException exception = new RuntimeException("you didn't say the magic word!");
+ AbstractFuture<String> evilFuture = new AbstractFuture<String>() {
+ @Override public void addListener(Runnable r, Executor e) {
+ throw exception;
+ }
+ };
+ AbstractFuture<String> normalFuture = new AbstractFuture<String>() {};
+ normalFuture.setFuture(evilFuture);
+ assertTrue(normalFuture.isDone());
+ try {
+ normalFuture.get();
+ fail();
+ } catch (ExecutionException e) {
+ assertSame(exception, e.getCause());
+ }
+ }
+
+ public void testRemoveWaiter_interruption() throws Exception {
+ final AbstractFuture<String> future = new AbstractFuture<String>() {};
+ WaiterThread waiter1 = new WaiterThread(future);
+ waiter1.start();
+ waiter1.awaitWaiting();
+
+ WaiterThread waiter2 = new WaiterThread(future);
+ waiter2.start();
+ waiter2.awaitWaiting();
+ // The waiter queue should be waiter2->waiter1
+
+ // This should wake up waiter1 and cause the waiter1 node to be removed.
+ waiter1.interrupt();
+
+ waiter1.join();
+ waiter2.awaitWaiting(); // should still be blocked
+
+ LockSupport.unpark(waiter2); // spurious wakeup
+ waiter2.awaitWaiting(); // should eventually re-park
+
+ future.set(null);
+ waiter2.join();
+ }
+
+ public void testRemoveWaiter_polling() throws Exception {
+ final AbstractFuture<String> future = new AbstractFuture<String>() {};
+ WaiterThread waiter = new WaiterThread(future);
+ waiter.start();
+ waiter.awaitWaiting();
+ PollingThread poller = new PollingThread(future);
+ poller.start();
+ PollingThread poller2 = new PollingThread(future);
+ poller2.start();
+ PollingThread poller3 = new PollingThread(future);
+ poller3.start();
+ poller.awaitInLoop();
+ poller2.awaitInLoop();
+ poller3.awaitInLoop();
+
+ // The waiter queue should be {poller x 3}->waiter1
+ waiter.interrupt();
+
+ // This should wake up waiter1 and cause the waiter1 node to be removed.
+ waiter.join();
+ future.set(null);
+ poller.join();
+ }
+
public void testCompletionFinishesWithDone() {
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 50000; i++) {
final AbstractFuture<String> future = new AbstractFuture<String>() {};
- final AtomicReference<String> errorMessage = new AtomicReference<String>();
+ final AtomicReference<String> errorMessage = Atomics.newReference();
executor.execute(new Runnable() {
@Override
public void run() {
@@ -148,6 +243,376 @@ public class AbstractFutureTest extends TestCase {
executor.shutdown();
}
+ /**
+ * He did the bash, he did the future bash
+ * The future bash, it was a concurrency smash
+ * He did the bash, it caught on in a flash
+ * He did the bash, he did the future bash
+ */
+ public void testFutureBash() {
+ final CyclicBarrier barrier = new CyclicBarrier(
+ 6 // for the setter threads
+ + 50 // for the listeners
+ + 50 // for the blocking get threads,
+ + 1); // for the main thread
+ final ExecutorService executor = Executors.newFixedThreadPool(barrier.getParties());
+ final AtomicReference<AbstractFuture<String>> currentFuture = Atomics.newReference();
+ final AtomicInteger numSuccessfulSetCalls = new AtomicInteger();
+ Callable<Void> completeSucessFullyRunnable = new Callable<Void>() {
+ @Override public Void call() {
+ if (currentFuture.get().set("set")) {
+ numSuccessfulSetCalls.incrementAndGet();
+ }
+ awaitUnchecked(barrier);
+ return null;
+ }
+ };
+ Callable<Void> completeExceptionallyRunnable = new Callable<Void>() {
+ Exception failureCause = new Exception("setException");
+ @Override public Void call() {
+ if (currentFuture.get().setException(failureCause)) {
+ numSuccessfulSetCalls.incrementAndGet();
+ }
+ awaitUnchecked(barrier);
+ return null;
+ }
+ };
+ Callable<Void> cancelRunnable = new Callable<Void>() {
+ @Override public Void call() {
+ if (currentFuture.get().cancel(true)) {
+ numSuccessfulSetCalls.incrementAndGet();
+ }
+ awaitUnchecked(barrier);
+ return null;
+ }
+ };
+ Callable<Void> setFutureCompleteSucessFullyRunnable = new Callable<Void>() {
+ ListenableFuture<String> future = Futures.immediateFuture("setFuture");
+ @Override public Void call() {
+ if (currentFuture.get().setFuture(future)) {
+ numSuccessfulSetCalls.incrementAndGet();
+ }
+ awaitUnchecked(barrier);
+ return null;
+ }
+ };
+ Callable<Void> setFutureCompleteExceptionallyRunnable = new Callable<Void>() {
+ ListenableFuture<String> future = Futures.immediateFailedFuture(new Exception("setFuture"));
+ @Override public Void call() {
+ if (currentFuture.get().setFuture(future)) {
+ numSuccessfulSetCalls.incrementAndGet();
+ }
+ awaitUnchecked(barrier);
+ return null;
+ }
+ };
+ Callable<Void> setFutureCancelRunnable = new Callable<Void>() {
+ ListenableFuture<String> future = Futures.immediateCancelledFuture();
+ @Override public Void call() {
+ if (currentFuture.get().setFuture(future)) {
+ numSuccessfulSetCalls.incrementAndGet();
+ }
+ awaitUnchecked(barrier);
+ return null;
+ }
+ };
+ final Set<Object> finalResults = Collections.synchronizedSet(Sets.newIdentityHashSet());
+ Runnable collectResultsRunnable = new Runnable() {
+ @Override public void run() {
+ try {
+ String result = Uninterruptibles.getUninterruptibly(currentFuture.get());
+ finalResults.add(result);
+ } catch (ExecutionException e) {
+ finalResults.add(e.getCause());
+ } catch (CancellationException e) {
+ finalResults.add(e.getCause());
+ } finally {
+ awaitUnchecked(barrier);
+ }
+ }
+ };
+ Runnable collectResultsTimedGetRunnable = new Runnable() {
+ @Override public void run() {
+ Future<String> future = currentFuture.get();
+ while (true) {
+ try {
+ String result = Uninterruptibles.getUninterruptibly(future, 0, TimeUnit.SECONDS);
+ finalResults.add(result);
+ break;
+ } catch (ExecutionException e) {
+ finalResults.add(e.getCause());
+ break;
+ } catch (CancellationException e) {
+ finalResults.add(e.getCause());
+ break;
+ } catch (TimeoutException e) {
+ // loop
+ }
+ }
+ awaitUnchecked(barrier);
+ }
+ };
+ List<Callable<?>> allTasks = new ArrayList<Callable<?>>();
+ allTasks.add(completeSucessFullyRunnable);
+ allTasks.add(completeExceptionallyRunnable);
+ allTasks.add(cancelRunnable);
+ allTasks.add(setFutureCompleteSucessFullyRunnable);
+ allTasks.add(setFutureCompleteExceptionallyRunnable);
+ allTasks.add(setFutureCancelRunnable);
+ for (int k = 0; k < 50; k++) {
+ // For each listener we add a task that submits it to the executor directly for the blocking
+ // get usecase and another task that adds it as a listener to the future to exercise both
+ // racing addListener calls and addListener calls completing after the future completes.
+ final Runnable listener = k % 2 == 0
+ ? collectResultsRunnable
+ : collectResultsTimedGetRunnable;
+ allTasks.add(Executors.callable(listener));
+ allTasks.add(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ currentFuture.get().addListener(listener, executor);
+ return null;
+ }
+ });
+ }
+ assertEquals(allTasks.size() + 1, barrier.getParties());
+ for (int i = 0; i < 1000; i++) {
+ Collections.shuffle(allTasks);
+ final AbstractFuture<String> future = new AbstractFuture<String>() {};
+ currentFuture.set(future);
+ for (Callable<?> task : allTasks) {
+ executor.submit(task);
+ }
+ awaitUnchecked(barrier);
+ assertThat(future.isDone()).isTrue();
+ // inspect state and ensure it is correct!
+ // asserts that all get calling threads received the same value
+ Object result = Iterables.getOnlyElement(finalResults);
+ if (result instanceof CancellationException) {
+ assertTrue(future.isCancelled());
+ if (future.wasInterrupted()) {
+ // We were cancelled, it is possible that setFuture could have succeeded to.
+ assertThat(numSuccessfulSetCalls.get()).isIn(Range.closed(1, 2));
+ } else {
+ assertThat(numSuccessfulSetCalls.get()).isEqualTo(1);
+ }
+ } else {
+ assertThat(numSuccessfulSetCalls.get()).isEqualTo(1);
+ }
+ // reset for next iteration
+ numSuccessfulSetCalls.set(0);
+ finalResults.clear();
+ }
+ executor.shutdown();
+ }
+
+ // setFuture and cancel() interact in more complicated ways than the other setters.
+ public void testSetFutureCancelBash() {
+ final CyclicBarrier barrier = new CyclicBarrier(
+ 2 // for the setter threads
+ + 50 // for the listeners
+ + 50 // for the blocking get threads,
+ + 1); // for the main thread
+ final ExecutorService executor = Executors.newFixedThreadPool(barrier.getParties());
+ final AtomicReference<AbstractFuture<String>> currentFuture = Atomics.newReference();
+ final AtomicReference<AbstractFuture<String>> setFutureFuture = Atomics.newReference();
+ final AtomicBoolean setFutureSetSucess = new AtomicBoolean();
+ final AtomicBoolean setFutureCompletionSucess = new AtomicBoolean();
+ final AtomicBoolean cancellationSucess = new AtomicBoolean();
+ Callable<Void> cancelRunnable = new Callable<Void>() {
+ @Override public Void call() {
+ cancellationSucess.set(currentFuture.get().cancel(true));
+ awaitUnchecked(barrier);
+ return null;
+ }
+ };
+ Callable<Void> setFutureCompleteSucessFullyRunnable = new Callable<Void>() {
+ @Override public Void call() {
+ AbstractFuture<String> future = setFutureFuture.get();
+ setFutureSetSucess.set(currentFuture.get().setFuture(future));
+ setFutureCompletionSucess.set(future.set("hello-async-world"));
+ awaitUnchecked(barrier);
+ return null;
+ }
+ };
+ final Set<Object> finalResults = Collections.synchronizedSet(Sets.newIdentityHashSet());
+ Runnable collectResultsRunnable = new Runnable() {
+ @Override public void run() {
+ try {
+ String result = Uninterruptibles.getUninterruptibly(currentFuture.get());
+ finalResults.add(result);
+ } catch (ExecutionException e) {
+ finalResults.add(e.getCause());
+ } catch (CancellationException e) {
+ finalResults.add(CancellationException.class);
+ } finally {
+ awaitUnchecked(barrier);
+ }
+ }
+ };
+ Runnable collectResultsTimedGetRunnable = new Runnable() {
+ @Override public void run() {
+ Future<String> future = currentFuture.get();
+ while (true) {
+ try {
+ String result = Uninterruptibles.getUninterruptibly(future, 0, TimeUnit.SECONDS);
+ finalResults.add(result);
+ break;
+ } catch (ExecutionException e) {
+ finalResults.add(e.getCause());
+ break;
+ } catch (CancellationException e) {
+ finalResults.add(CancellationException.class);
+ break;
+ } catch (TimeoutException e) {
+ // loop
+ }
+ }
+ awaitUnchecked(barrier);
+ }
+ };
+ List<Callable<?>> allTasks = new ArrayList<Callable<?>>();
+ allTasks.add(cancelRunnable);
+ allTasks.add(setFutureCompleteSucessFullyRunnable);
+ for (int k = 0; k < 50; k++) {
+ // For each listener we add a task that submits it to the executor directly for the blocking
+ // get usecase and another task that adds it as a listener to the future to exercise both
+ // racing addListener calls and addListener calls completing after the future completes.
+ final Runnable listener = k % 2 == 0
+ ? collectResultsRunnable
+ : collectResultsTimedGetRunnable;
+ allTasks.add(Executors.callable(listener));
+ allTasks.add(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ currentFuture.get().addListener(listener, executor);
+ return null;
+ }
+ });
+ }
+ assertEquals(allTasks.size() + 1, barrier.getParties()); // sanity check
+ for (int i = 0; i < 1000; i++) {
+ Collections.shuffle(allTasks);
+ final AbstractFuture<String> future = new AbstractFuture<String>() {};
+ final AbstractFuture<String> setFuture = new AbstractFuture<String>() {};
+ currentFuture.set(future);
+ setFutureFuture.set(setFuture);
+ for (Callable<?> task : allTasks) {
+ executor.submit(task);
+ }
+ awaitUnchecked(barrier);
+ assertThat(future.isDone()).isTrue();
+ // inspect state and ensure it is correct!
+ // asserts that all get calling threads received the same value
+ Object result = Iterables.getOnlyElement(finalResults);
+ if (result == CancellationException.class) {
+ assertTrue(future.isCancelled());
+ assertTrue(cancellationSucess.get());
+ // cancellation can interleave in 3 ways
+ // 1. prior to setFuture
+ // 2. after setFuture before set() on the future assigned
+ // 3. after setFuture and set() are called but before the listener completes.
+ if (!setFutureSetSucess.get() || !setFutureCompletionSucess.get()) {
+ // If setFuture fails or set on the future fails then it must be because that future was
+ // cancelled
+ assertTrue(setFuture.isCancelled());
+ assertTrue(setFuture.wasInterrupted()); // we only call cancel(true)
+ }
+ } else {
+ // set on the future completed
+ assertFalse(cancellationSucess.get());
+ assertTrue(setFutureSetSucess.get());
+ assertTrue(setFutureCompletionSucess.get());
+ }
+ // reset for next iteration
+ setFutureSetSucess.set(false);
+ setFutureCompletionSucess.set(false);
+ cancellationSucess.set(false);
+ finalResults.clear();
+ }
+ executor.shutdown();
+ }
+
+ // Test to ensure that when calling setFuture with a done future only setFuture or cancel can
+ // return true.
+ public void testSetFutureCancelBash_withDoneFuture() {
+ final CyclicBarrier barrier = new CyclicBarrier(
+ 2 // for the setter threads
+ + 1 // for the blocking get thread,
+ + 1); // for the main thread
+ final ExecutorService executor = Executors.newFixedThreadPool(barrier.getParties());
+ final AtomicReference<AbstractFuture<String>> currentFuture = Atomics.newReference();
+ final AtomicBoolean setFutureSuccess = new AtomicBoolean();
+ final AtomicBoolean cancellationSucess = new AtomicBoolean();
+ Callable<Void> cancelRunnable = new Callable<Void>() {
+ @Override public Void call() {
+ cancellationSucess.set(currentFuture.get().cancel(true));
+ awaitUnchecked(barrier);
+ return null;
+ }
+ };
+ Callable<Void> setFutureCompleteSucessFullyRunnable = new Callable<Void>() {
+ final ListenableFuture<String> future = Futures.immediateFuture("hello");
+ @Override public Void call() {
+ setFutureSuccess.set(currentFuture.get().setFuture(future));
+ awaitUnchecked(barrier);
+ return null;
+ }
+ };
+ final Set<Object> finalResults = Collections.synchronizedSet(Sets.newIdentityHashSet());
+ final Runnable collectResultsRunnable = new Runnable() {
+ @Override public void run() {
+ try {
+ String result = Uninterruptibles.getUninterruptibly(currentFuture.get());
+ finalResults.add(result);
+ } catch (ExecutionException e) {
+ finalResults.add(e.getCause());
+ } catch (CancellationException e) {
+ finalResults.add(CancellationException.class);
+ } finally {
+ awaitUnchecked(barrier);
+ }
+ }
+ };
+ List<Callable<?>> allTasks = new ArrayList<Callable<?>>();
+ allTasks.add(cancelRunnable);
+ allTasks.add(setFutureCompleteSucessFullyRunnable);
+ allTasks.add(Executors.callable(collectResultsRunnable));
+ assertEquals(allTasks.size() + 1, barrier.getParties()); // sanity check
+ for (int i = 0; i < 1000; i++) {
+ Collections.shuffle(allTasks);
+ final AbstractFuture<String> future = new AbstractFuture<String>() {};
+ currentFuture.set(future);
+ for (Callable<?> task : allTasks) {
+ executor.submit(task);
+ }
+ awaitUnchecked(barrier);
+ assertThat(future.isDone()).isTrue();
+ // inspect state and ensure it is correct!
+ // asserts that all get calling threads received the same value
+ Object result = Iterables.getOnlyElement(finalResults);
+ if (result == CancellationException.class) {
+ assertTrue(future.isCancelled());
+ assertTrue(cancellationSucess.get());
+ assertFalse(setFutureSuccess.get());
+ } else {
+ assertTrue(setFutureSuccess.get());
+ assertFalse(cancellationSucess.get());
+ }
+ // reset for next iteration
+ setFutureSuccess.set(false);
+ cancellationSucess.set(false);
+ finalResults.clear();
+ }
+ executor.shutdown();
+ }
+
+ private int awaitUnchecked(final CyclicBarrier barrier) {
+ try {
+ return barrier.await();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
private void checkStackTrace(ExecutionException e) {
// Our call site for get() should be in the trace.
int index = findStackFrame(
@@ -190,6 +655,61 @@ public class AbstractFutureTest extends TestCase {
return null;
}
+ private final class WaiterThread extends Thread {
+ private final AbstractFuture<String> future;
+
+ private WaiterThread(AbstractFuture<String> future) {
+ this.future = future;
+ }
+
+ @Override public void run() {
+ try {
+ future.get();
+ } catch (Exception e) {
+ // nothing
+ }
+ }
+
+ void awaitWaiting() {
+ while (LockSupport.getBlocker(this) != future) {
+ if (getState() == State.TERMINATED) {
+ throw new RuntimeException("Thread exited");
+ }
+ Thread.yield();
+ }
+ }
+ }
+
+ private final class PollingThread extends Thread {
+ private final AbstractFuture<String> future;
+ private final CountDownLatch completedIteration = new CountDownLatch(10);
+
+ private PollingThread(AbstractFuture<String> future) {
+ this.future = future;
+ }
+
+ @Override public void run() {
+ while (true) {
+ try {
+ future.get(0, TimeUnit.SECONDS);
+ return;
+ } catch (InterruptedException e) {
+ return;
+ } catch (ExecutionException e) {
+ return;
+ } catch (TimeoutException e) {
+ // do nothing
+ } finally {
+ completedIteration.countDown();
+ }
+ }
+ }
+
+ void awaitInLoop() {
+ Uninterruptibles.awaitUninterruptibly(completedIteration);
+ }
+ }
+
private static final class InterruptibleFuture
extends AbstractFuture<String> {
boolean interruptTaskWasCalled;
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractIdleServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractIdleServiceTest.java
index 2dfad5c..fbfa404 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractIdleServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractIdleServiceTest.java
@@ -94,7 +94,7 @@ public class AbstractIdleServiceTest extends TestCase {
service.startAsync().awaitRunning();
assertEquals(1, service.startUpCalled);
assertEquals(Service.State.RUNNING, service.state());
- assertThat(service.transitionStates).has().exactly(Service.State.STARTING).inOrder();
+ assertThat(service.transitionStates).containsExactly(Service.State.STARTING);
}
public void testStart_failed() {
@@ -114,7 +114,7 @@ public class AbstractIdleServiceTest extends TestCase {
}
assertEquals(1, service.startUpCalled);
assertEquals(Service.State.FAILED, service.state());
- assertThat(service.transitionStates).has().exactly(Service.State.STARTING).inOrder();
+ assertThat(service.transitionStates).containsExactly(Service.State.STARTING);
}
public void testStop_withoutStart() {
@@ -136,7 +136,7 @@ public class AbstractIdleServiceTest extends TestCase {
assertEquals(1, service.shutDownCalled);
assertEquals(Service.State.TERMINATED, service.state());
assertThat(service.transitionStates)
- .has().exactly(Service.State.STARTING, Service.State.STOPPING).inOrder();
+ .containsExactly(Service.State.STARTING, Service.State.STOPPING).inOrder();
}
public void testStop_failed() {
@@ -160,7 +160,7 @@ public class AbstractIdleServiceTest extends TestCase {
assertEquals(1, service.shutDownCalled);
assertEquals(Service.State.FAILED, service.state());
assertThat(service.transitionStates)
- .has().exactly(Service.State.STARTING, Service.State.STOPPING).inOrder();
+ .containsExactly(Service.State.STARTING, Service.State.STOPPING).inOrder();
}
public void testServiceToString() {
@@ -180,12 +180,16 @@ public class AbstractIdleServiceTest extends TestCase {
@Override public void execute(Runnable command) {}
};
}
+
+ @Override protected String serviceName() {
+ return "Foo";
+ }
};
try {
service.startAsync().awaitRunning(1, TimeUnit.MILLISECONDS);
fail("Expected timeout");
} catch (TimeoutException e) {
- assertThat(e.getMessage()).contains(Service.State.STARTING.toString());
+ assertThat(e).hasMessage("Timed out waiting for Foo [STARTING] to reach the RUNNING state.");
}
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractListeningExecutorServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractListeningExecutorServiceTest.java
index df96535..7742dbb 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractListeningExecutorServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractListeningExecutorServiceTest.java
@@ -16,6 +16,8 @@
package com.google.common.util.concurrent;
+import static com.google.common.truth.Truth.assertThat;
+
import com.google.common.collect.ImmutableList;
import junit.framework.TestCase;
@@ -33,26 +35,26 @@ public class AbstractListeningExecutorServiceTest extends TestCase {
public void testSubmit() throws Exception {
/*
- * Mostly just tests that ListenableFutureTasks are created and run; tests for
- * ListenableFutureTask should ensure that listeners are called correctly.
+ * Mostly just tests that TrustedListenableFutureTask are created and run; tests for
+ * TrustedListenableFutureTask should ensure that listeners are called correctly.
*/
TestListeningExecutorService e = new TestListeningExecutorService();
TestRunnable runnable = new TestRunnable();
ListenableFuture<?> runnableFuture = e.submit(runnable);
- assertTrue(runnableFuture instanceof ListenableFutureTask);
+ assertThat(runnableFuture).isInstanceOf(TrustedListenableFutureTask.class);
assertTrue(runnableFuture.isDone());
assertTrue(runnable.run);
ListenableFuture<String> callableFuture = e.submit(new TestCallable());
- assertTrue(callableFuture instanceof ListenableFutureTask);
+ assertThat(callableFuture).isInstanceOf(TrustedListenableFutureTask.class);
assertTrue(callableFuture.isDone());
assertEquals("foo", callableFuture.get());
TestRunnable runnable2 = new TestRunnable();
ListenableFuture<Integer> runnableFuture2 = e.submit(runnable2, 3);
- assertTrue(runnableFuture2 instanceof ListenableFutureTask);
+ assertThat(runnableFuture2).isInstanceOf(TrustedListenableFutureTask.class);
assertTrue(runnableFuture2.isDone());
assertTrue(runnable2.run);
assertEquals((Integer) 3, runnableFuture2.get());
@@ -81,7 +83,7 @@ public class AbstractListeningExecutorServiceTest extends TestCase {
@Override
public void execute(Runnable runnable) {
- assertTrue(runnable instanceof ListenableFutureTask);
+ assertThat(runnable).isInstanceOf(TrustedListenableFutureTask.class);
runnable.run();
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractScheduledServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractScheduledServiceTest.java
index 7c01d41..599c1ab 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractScheduledServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractScheduledServiceTest.java
@@ -16,19 +16,28 @@
package com.google.common.util.concurrent;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.util.concurrent.AbstractScheduledService.Scheduler.newFixedDelaySchedule;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
import com.google.common.util.concurrent.AbstractScheduledService.Scheduler;
import com.google.common.util.concurrent.Service.State;
+import com.google.common.util.concurrent.testing.TestingExecutors;
import junit.framework.TestCase;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -41,7 +50,7 @@ import java.util.concurrent.atomic.AtomicReference;
public class AbstractScheduledServiceTest extends TestCase {
- volatile Scheduler configuration = Scheduler.newFixedDelaySchedule(0, 10, TimeUnit.MILLISECONDS);
+ volatile Scheduler configuration = newFixedDelaySchedule(0, 10, TimeUnit.MILLISECONDS);
volatile ScheduledFuture<?> future = null;
volatile boolean atFixedRateCalled = false;
@@ -79,11 +88,11 @@ public class AbstractScheduledServiceTest extends TestCase {
try {
future.get();
fail();
- } catch (ExecutionException e) {
- // An execution exception holds a runtime exception (from throwables.propogate) that holds our
- // original exception.
- assertEquals(service.runException, e.getCause().getCause());
+ } catch (CancellationException expected) {
}
+ // An execution exception holds a runtime exception (from throwables.propogate) that holds our
+ // original exception.
+ assertEquals(service.runException, service.failureCause());
assertEquals(service.state(), Service.State.FAILED);
}
@@ -100,6 +109,27 @@ public class AbstractScheduledServiceTest extends TestCase {
assertEquals(Service.State.FAILED, service.state());
}
+ public void testFailOnErrorFromStartUpListener() throws InterruptedException {
+ final Error error = new Error();
+ final CountDownLatch latch = new CountDownLatch(1);
+ TestService service = new TestService();
+ service.addListener(new Service.Listener() {
+ @Override public void running() {
+ throw error;
+ }
+ @Override public void failed(State from, Throwable failure) {
+ assertEquals(State.RUNNING, from);
+ assertEquals(error, failure);
+ latch.countDown();
+ }
+ }, directExecutor());
+ service.startAsync();
+ latch.await();
+
+ assertEquals(0, service.numberOfTimesRunCalled.get());
+ assertEquals(Service.State.FAILED, service.state());
+ }
+
public void testFailOnExceptionFromShutDown() throws Exception {
TestService service = new TestService();
service.shutDownException = new Exception();
@@ -159,7 +189,7 @@ public class AbstractScheduledServiceTest extends TestCase {
}
@Override protected Scheduler scheduler() {
- return Scheduler.newFixedDelaySchedule(0, 1, TimeUnit.MILLISECONDS);
+ return newFixedDelaySchedule(0, 1, TimeUnit.MILLISECONDS);
}
};
@@ -186,7 +216,7 @@ public class AbstractScheduledServiceTest extends TestCase {
}
@Override protected Scheduler scheduler() {
- return Scheduler.newFixedDelaySchedule(0, 1, TimeUnit.MILLISECONDS);
+ return newFixedDelaySchedule(0, 1, TimeUnit.MILLISECONDS);
}
};
@@ -216,6 +246,31 @@ public class AbstractScheduledServiceTest extends TestCase {
assertEquals(1, service.numberOfTimesSchedulerCalled.get());
}
+ public void testTimeout() {
+ // Create a service whose executor will never run its commands
+ Service service = new AbstractScheduledService() {
+ @Override protected Scheduler scheduler() {
+ return Scheduler.newFixedDelaySchedule(0, 1, TimeUnit.NANOSECONDS);
+ }
+
+ @Override protected ScheduledExecutorService executor() {
+ return TestingExecutors.noOpScheduledExecutor();
+ }
+
+ @Override protected void runOneIteration() throws Exception {}
+
+ @Override protected String serviceName() {
+ return "Foo";
+ }
+ };
+ try {
+ service.startAsync().awaitRunning(1, TimeUnit.MILLISECONDS);
+ fail("Expected timeout");
+ } catch (TimeoutException e) {
+ assertThat(e).hasMessage("Timed out waiting for Foo [STARTING] to reach the RUNNING state.");
+ }
+ }
+
private class TestService extends AbstractScheduledService {
CyclicBarrier runFirstBarrier = new CyclicBarrier(2);
CyclicBarrier runSecondBarrier = new CyclicBarrier(2);
@@ -311,7 +366,7 @@ public class AbstractScheduledServiceTest extends TestCase {
}
public void testFixedDelaySchedule() {
- Scheduler schedule = Scheduler.newFixedDelaySchedule(initialDelay, delay, unit);
+ Scheduler schedule = newFixedDelaySchedule(initialDelay, delay, unit);
schedule.schedule(null, new ScheduledThreadPoolExecutor(10) {
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,
@@ -323,6 +378,47 @@ public class AbstractScheduledServiceTest extends TestCase {
assertTrue(called);
}
+ public void testFixedDelayScheduleFarFuturePotentiallyOverflowingScheduleIsNeverReached()
+ throws Exception {
+ TestAbstractScheduledCustomService service = new TestAbstractScheduledCustomService() {
+ @Override protected Scheduler scheduler() {
+ return newFixedDelaySchedule(Long.MAX_VALUE, Long.MAX_VALUE, SECONDS);
+ }
+ };
+ service.startAsync().awaitRunning();
+ try {
+ service.firstBarrier.await(5, SECONDS);
+ fail();
+ } catch (TimeoutException expected) {
+ }
+ assertEquals(0, service.numIterations.get());
+ service.stopAsync();
+ service.awaitTerminated();
+ }
+
+ public void testCustomSchedulerFarFuturePotentiallyOverflowingScheduleIsNeverReached()
+ throws Exception {
+ TestAbstractScheduledCustomService service = new TestAbstractScheduledCustomService() {
+ @Override protected Scheduler scheduler() {
+ return new AbstractScheduledService.CustomScheduler() {
+ @Override
+ protected Schedule getNextSchedule() throws Exception {
+ return new Schedule(Long.MAX_VALUE, SECONDS);
+ }
+ };
+ }
+ };
+ service.startAsync().awaitRunning();
+ try {
+ service.firstBarrier.await(5, SECONDS);
+ fail();
+ } catch (TimeoutException expected) {
+ }
+ assertEquals(0, service.numIterations.get());
+ service.stopAsync();
+ service.awaitTerminated();
+ }
+
private class TestCustomScheduler extends AbstractScheduledService.CustomScheduler {
public AtomicInteger scheduleCounter = new AtomicInteger(0);
@Override
@@ -373,6 +469,31 @@ public class AbstractScheduledServiceTest extends TestCase {
assertEquals(1, service.numIterations.get());
}
+ public void testCustomScheduler_deadlock() throws InterruptedException, BrokenBarrierException {
+ final CyclicBarrier inGetNextSchedule = new CyclicBarrier(2);
+ // This will flakily deadlock, so run it multiple times to increase the flake likelihood
+ for (int i = 0; i < 1000; i++) {
+ Service service = new AbstractScheduledService() {
+ @Override protected void runOneIteration() {}
+ @Override protected Scheduler scheduler() {
+ return new CustomScheduler() {
+ @Override protected Schedule getNextSchedule() throws Exception {
+ if (state() != State.STARTING) {
+ inGetNextSchedule.await();
+ Thread.yield();
+ throw new RuntimeException("boom");
+ }
+ return new Schedule(0, TimeUnit.NANOSECONDS);
+ }
+ };
+ }
+ };
+ service.startAsync().awaitRunning();
+ inGetNextSchedule.await();
+ service.stopAsync();
+ }
+ }
+
public void testBig() throws Exception {
TestAbstractScheduledCustomService service = new TestAbstractScheduledCustomService() {
@Override protected Scheduler scheduler() {
@@ -417,10 +538,6 @@ public class AbstractScheduledServiceTest extends TestCase {
return Executors.newScheduledThreadPool(10);
}
- @Override protected void startUp() throws Exception {}
-
- @Override protected void shutDown() throws Exception {}
-
@Override protected Scheduler scheduler() {
return new CustomScheduler() {
@Override
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractServiceTest.java
index 1fdac38..a6eeaa9 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractServiceTest.java
@@ -16,6 +16,7 @@
package com.google.common.util.concurrent;
+import static com.google.common.truth.Truth.assertThat;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static java.lang.Thread.currentThread;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -380,7 +381,7 @@ public class AbstractServiceTest extends TestCase {
assertEquals(State.FAILED, service.state());
waiter.join(LONG_TIMEOUT_MILLIS);
assertFalse(waiter.isAlive());
- assertTrue(exception.get() instanceof IllegalStateException);
+ assertThat(exception.get()).isInstanceOf(IllegalStateException.class);
assertEquals(EXCEPTION, exception.get().getCause());
}
@@ -460,12 +461,12 @@ public class AbstractServiceTest extends TestCase {
service.startAsync();
service.notifyFailed(new Exception("1"));
service.notifyFailed(new Exception("2"));
- assertEquals("1", service.failureCause().getMessage());
+ assertThat(service.failureCause()).hasMessage("1");
try {
service.awaitRunning();
fail();
} catch (IllegalStateException e) {
- assertEquals("1", e.getCause().getMessage());
+ assertThat(e.getCause()).hasMessage("1");
}
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/AsyncSettableFutureTest.java b/guava-tests/test/com/google/common/util/concurrent/AsyncSettableFutureTest.java
deleted file mode 100644
index 1ffd307..0000000
--- a/guava-tests/test/com/google/common/util/concurrent/AsyncSettableFutureTest.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2012 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.util.concurrent;
-
-import junit.framework.TestCase;
-
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Tests that {@code AsyncSettableFuture} is a valid {@link ListenableFuture}
- * that behaves itself as expected.
- */
-
-public class AsyncSettableFutureTest extends TestCase {
-
- private static class Foo {}
- private static class FooChild extends Foo {}
-
- /** Tests the initial state of the future. */
- public void testCreate() throws Exception {
- AsyncSettableFuture<Integer> future = AsyncSettableFuture.create();
- assertFalse(future.isSet());
- assertFalse(future.isDone());
- assertFalse(future.isCancelled());
- }
-
- public void testSetValue() throws Exception {
- AsyncSettableFuture<Integer> future = AsyncSettableFuture.create();
- assertTrue(future.setValue(42));
- assertTrue(future.isSet());
- // Later attempts to set the future should return false.
- assertFalse(future.setValue(23));
- assertFalse(future.setException(new Exception("bar")));
- assertFalse(future.setFuture(SettableFuture.<Integer>create()));
- // Check that the future has been set properly.
- assertTrue(future.isDone());
- assertFalse(future.isCancelled());
- assertEquals(42, (int) future.get());
- }
-
- public void testSetException() throws Exception {
- AsyncSettableFuture<Object> future = AsyncSettableFuture.create();
- Exception e = new Exception("foobarbaz");
- assertTrue(future.setException(e));
- assertTrue(future.isSet());
- // Later attempts to set the future should return false.
- assertFalse(future.setValue(23));
- assertFalse(future.setException(new Exception("quux")));
- assertFalse(future.setFuture(SettableFuture.create()));
- // Check that the future has been set properly.
- assertTrue(future.isDone());
- assertFalse(future.isCancelled());
- try {
- future.get();
- fail("Expected ExecutionException");
- } catch (ExecutionException ee) {
- assertSame(e, ee.getCause());
- }
- }
-
- public void testSetFuture() throws Exception {
- AsyncSettableFuture<String> future = AsyncSettableFuture.create();
- SettableFuture<String> nested = SettableFuture.create();
- assertTrue(future.setFuture(nested));
- assertTrue(future.isSet());
- // Later attempts to set the future should return false.
- assertFalse(future.setValue("x"));
- assertFalse(future.setException(new Exception("bar")));
- assertFalse(future.setFuture(SettableFuture.<String>create()));
- // Check that the future has been set properly.
- assertFalse(future.isDone());
- assertFalse(future.isCancelled());
- try {
- future.get(0, TimeUnit.MILLISECONDS);
- fail("Expected TimeoutException");
- } catch (TimeoutException expected) { /* expected */ }
- nested.set("foo");
- assertTrue(future.isDone());
- assertFalse(future.isCancelled());
- assertEquals("foo", future.get());
- }
-
- public void testSetFuture_genericsHierarchy() throws Exception {
- AsyncSettableFuture<Foo> future = AsyncSettableFuture.create();
- SettableFuture<FooChild> nested = SettableFuture.create();
- assertTrue(future.setFuture(nested));
- assertTrue(future.isSet());
- // Later attempts to set the future should return false.
- assertFalse(future.setValue(new Foo()));
- assertFalse(future.setException(new Exception("bar")));
- assertFalse(future.setFuture(SettableFuture.<Foo>create()));
- // Check that the future has been set properly.
- assertFalse(future.isDone());
- assertFalse(future.isCancelled());
- try {
- future.get(0, TimeUnit.MILLISECONDS);
- fail("Expected TimeoutException");
- } catch (TimeoutException expected) { /* expected */ }
- FooChild value = new FooChild();
- nested.set(value);
- assertTrue(future.isDone());
- assertFalse(future.isCancelled());
- assertSame(value, future.get());
- }
-
- public void testCancel_innerCancelsAsync() throws Exception {
- AsyncSettableFuture<Object> async = AsyncSettableFuture.create();
- SettableFuture<Object> inner = SettableFuture.create();
- async.setFuture(inner);
- inner.cancel(true);
- assertTrue(async.isCancelled());
- try {
- async.get();
- fail("Expected CancellationException");
- } catch (CancellationException expected) { /* expected */ }
- }
-
- public void testCancel_resultCancelsInner_interrupted() throws Exception {
- AsyncSettableFuture<Object> async = AsyncSettableFuture.create();
- MyFuture<Object> inner = new MyFuture<Object>();
- async.setFuture(inner);
- async.cancel(true);
- assertTrue(inner.isCancelled());
- assertTrue(inner.myWasInterrupted());
- try {
- inner.get();
- fail("Expected CancellationException");
- } catch (CancellationException expected) { /* expected */ }
- }
-
- public void testCancel_resultCancelsInner() throws Exception {
- AsyncSettableFuture<Object> async = AsyncSettableFuture.create();
- MyFuture<Object> inner = new MyFuture<Object>();
- async.setFuture(inner);
- async.cancel(false);
- assertTrue(inner.isCancelled());
- assertFalse(inner.myWasInterrupted());
- try {
- inner.get();
- fail("Expected CancellationException");
- } catch (CancellationException expected) { /* expected */ }
- }
-
- public void testCancel_beforeSet() throws Exception {
- AsyncSettableFuture<Object> async = AsyncSettableFuture.create();
- async.cancel(true);
- assertFalse(async.setValue(42));
- }
-
- public void testCancel_multipleBeforeSetFuture_noInterruptFirst() throws Exception {
- AsyncSettableFuture<Object> async = AsyncSettableFuture.create();
- async.cancel(false);
- async.cancel(true);
- MyFuture<Object> inner = new MyFuture<Object>();
- assertFalse(async.setFuture(inner));
- assertTrue(inner.isCancelled());
- assertFalse(inner.myWasInterrupted());
- }
-
- public void testCancel_multipleBeforeSetFuture_interruptFirst() throws Exception {
- AsyncSettableFuture<Object> async = AsyncSettableFuture.create();
- async.cancel(true);
- async.cancel(false);
- MyFuture<Object> inner = new MyFuture<Object>();
- assertFalse(async.setFuture(inner));
- assertTrue(inner.isCancelled());
- assertTrue(inner.myWasInterrupted());
- }
-
- private static class MyFuture<V> extends AbstractFuture<V> {
- boolean myWasInterrupted() {
- // we need a new method since wasInterrupted is final, so we can't increase its visibility.
- return wasInterrupted();
- }
- }
-}
diff --git a/guava-tests/test/com/google/common/util/concurrent/CallablesTest.java b/guava-tests/test/com/google/common/util/concurrent/CallablesTest.java
index 885b73c..b024206 100644
--- a/guava-tests/test/com/google/common/util/concurrent/CallablesTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/CallablesTest.java
@@ -16,6 +16,8 @@
package com.google.common.util.concurrent;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
@@ -29,6 +31,7 @@ import java.util.concurrent.Callable;
*
* @author Isaac Shum
*/
+ at GwtCompatible(emulated = true)
public class CallablesTest extends TestCase {
public void testReturning() throws Exception {
@@ -41,6 +44,7 @@ public class CallablesTest extends TestCase {
assertSame(value, callable.call());
}
+ @GwtIncompatible("threads")
public void testRenaming() throws Exception {
String oldName = Thread.currentThread().getName();
final Supplier<String> newName = Suppliers.ofInstance("MyCrazyThreadName");
@@ -54,6 +58,7 @@ public class CallablesTest extends TestCase {
assertEquals(oldName, Thread.currentThread().getName());
}
+ @GwtIncompatible("threads")
public void testRenaming_exceptionalReturn() throws Exception {
String oldName = Thread.currentThread().getName();
final Supplier<String> newName = Suppliers.ofInstance("MyCrazyThreadName");
@@ -71,6 +76,8 @@ public class CallablesTest extends TestCase {
assertEquals(oldName, Thread.currentThread().getName());
}
+ @GwtIncompatible("threads")
+
public void testRenaming_noPermissions() throws Exception {
System.setSecurityManager(new SecurityManager() {
@Override public void checkAccess(Thread t) {
diff --git a/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTester.java b/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTester.java
index edc48a9..4cfd36c 100644
--- a/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTester.java
+++ b/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTester.java
@@ -16,14 +16,16 @@
package com.google.common.util.concurrent;
+import static org.mockito.Answers.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.ForwardingObject;
import com.google.common.collect.Iterables;
import com.google.common.testing.ForwardingWrapperTester;
-import org.easymock.EasyMock;
-
import java.lang.reflect.Method;
import java.util.Arrays;
@@ -57,16 +59,13 @@ final class ForwardingObjectTester {
Iterables.getOnlyElement(Arrays.asList(forwarderClass.getInterfaces()));
new ForwardingWrapperTester().testForwarding(interfaceType, new Function<Object, T>() {
@Override public T apply(Object delegate) {
- T mock = EasyMock.createMockBuilder(forwarderClass)
- .addMockedMethod(DELEGATE_METHOD)
- .createMock();
+ T mock = mock(forwarderClass, CALLS_REAL_METHODS.get());
try {
- DELEGATE_METHOD.invoke(mock);
+ T stubber = doReturn(delegate).when(mock);
+ DELEGATE_METHOD.invoke(stubber);
} catch (Exception e) {
throw Throwables.propagate(e);
}
- EasyMock.expectLastCall().andStubReturn(delegate);
- EasyMock.replay(mock);
return mock;
}
});
diff --git a/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTesterTest.java b/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTesterTest.java
index eae45bc..0b68e9a 100644
--- a/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTesterTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/ForwardingObjectTesterTest.java
@@ -32,10 +32,13 @@ public class ForwardingObjectTesterTest extends TestCase {
ForwardingObjectTester.testForwardingObject(FailToForward.class);
} catch (AssertionError expected) {
return;
+ } catch (UnsupportedOperationException expectedOnAndroid) {
+ return;
}
fail("Should have thrown");
}
+ @SuppressUnderAndroid // TODO(cpovirk): java.lang.IllegalAccessError: superclass not accessible
public void testSuccessfulForwarding() {
ForwardingObjectTester.testForwardingObject(ForwardToDelegate.class);
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java b/guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java
index 14e0179..a98f4a6 100644
--- a/guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/FutureCallbackTest.java
@@ -16,6 +16,10 @@
package com.google.common.util.concurrent;
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Preconditions;
import junit.framework.TestCase;
@@ -34,6 +38,7 @@ import javax.annotation.Nullable;
*
* @author Anthony Zana
*/
+ at GwtCompatible(emulated = true)
public class FutureCallbackTest extends TestCase {
public void testSameThreadSuccess() {
SettableFuture<String> f = SettableFuture.create();
@@ -65,6 +70,7 @@ public class FutureCallbackTest extends TestCase {
FutureCallback<String> callback =
new FutureCallback<String>() {
private boolean called = false;
+
@Override
public void onSuccess(String result) {
fail("Was not expecting onSuccess() to be called.");
@@ -73,7 +79,7 @@ public class FutureCallbackTest extends TestCase {
@Override
public synchronized void onFailure(Throwable t) {
assertFalse(called);
- assertTrue(t instanceof CancellationException);
+ assertThat(t).isInstanceOf(CancellationException.class);
called = true;
}
};
@@ -95,6 +101,7 @@ public class FutureCallbackTest extends TestCase {
Futures.addCallback(f, callback);
}
+ @GwtIncompatible("Mockito")
public void testOnSuccessThrowsRuntimeException() throws Exception {
RuntimeException exception = new RuntimeException();
String result = "result";
@@ -109,6 +116,7 @@ public class FutureCallbackTest extends TestCase {
Mockito.verifyNoMoreInteractions(callback);
}
+ @GwtIncompatible("Mockito")
public void testOnSuccessThrowsError() throws Exception {
class TestError extends Error {}
TestError error = new TestError();
diff --git a/guava-tests/test/com/google/common/util/concurrent/FuturesGetCheckedInputs.java b/guava-tests/test/com/google/common/util/concurrent/FuturesGetCheckedInputs.java
new file mode 100644
index 0000000..db192e7
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/FuturesGetCheckedInputs.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
+
+import com.google.common.util.concurrent.ForwardingFuture.SimpleForwardingFuture;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Classes and futures used in {@link FuturesGetCheckedTest} and {@link FuturesGetUncheckedTest}.
+ */
+final class FuturesGetCheckedInputs {
+ static final Exception CHECKED_EXCEPTION = new Exception("mymessage");
+ static final Future<String> FAILED_FUTURE_CHECKED_EXCEPTION =
+ immediateFailedFuture(CHECKED_EXCEPTION);
+ static final RuntimeException UNCHECKED_EXCEPTION = new RuntimeException("mymessage");
+ static final Future<String> FAILED_FUTURE_UNCHECKED_EXCEPTION =
+ immediateFailedFuture(UNCHECKED_EXCEPTION);
+ static final RuntimeException RUNTIME_EXCEPTION = new RuntimeException();
+ static final OtherThrowable OTHER_THROWABLE = new OtherThrowable();
+ static final Future<String> FAILED_FUTURE_OTHER_THROWABLE =
+ immediateFailedFuture(OTHER_THROWABLE);
+ static final Error ERROR = new Error("mymessage");
+ static final Future<String> FAILED_FUTURE_ERROR = immediateFailedFuture(ERROR);
+ static final Future<String> RUNTIME_EXCEPTION_FUTURE =
+ new SimpleForwardingFuture<String>(FAILED_FUTURE_CHECKED_EXCEPTION) {
+ @Override
+ public String get() {
+ throw RUNTIME_EXCEPTION;
+ }
+
+ @Override
+ public String get(long timeout, TimeUnit unit) {
+ throw RUNTIME_EXCEPTION;
+ }
+ };
+
+ public static final class TwoArgConstructorException extends Exception {
+ public TwoArgConstructorException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
+
+ public static final class TwoArgConstructorRuntimeException extends RuntimeException {
+ public TwoArgConstructorRuntimeException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
+
+ public static final class ExceptionWithPrivateConstructor extends Exception {
+ private ExceptionWithPrivateConstructor(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
+
+ @SuppressWarnings("unused") // we're testing that they're not used
+ public static final class ExceptionWithSomePrivateConstructors extends Exception {
+ private ExceptionWithSomePrivateConstructors(String a) {}
+
+ private ExceptionWithSomePrivateConstructors(String a, String b) {}
+
+ public ExceptionWithSomePrivateConstructors(String a, String b, String c) {}
+
+ private ExceptionWithSomePrivateConstructors(String a, String b, String c, String d) {}
+
+ private ExceptionWithSomePrivateConstructors(
+ String a, String b, String c, String d, String e) {}
+ }
+
+ public static final class ExceptionWithManyConstructors extends Exception {
+ boolean usedExpectedConstructor;
+
+ public ExceptionWithManyConstructors() {}
+
+ public ExceptionWithManyConstructors(Integer i) {}
+
+ public ExceptionWithManyConstructors(Throwable a) {}
+
+ public ExceptionWithManyConstructors(Throwable a, Throwable b) {}
+
+ public ExceptionWithManyConstructors(String s, Throwable b) {
+ usedExpectedConstructor = true;
+ }
+
+ public ExceptionWithManyConstructors(Throwable a, Throwable b, Throwable c) {}
+
+ public ExceptionWithManyConstructors(Throwable a, Throwable b, Throwable c, Throwable d) {}
+
+ public ExceptionWithManyConstructors(
+ Throwable a, Throwable b, Throwable c, Throwable d, Throwable e) {}
+
+ public ExceptionWithManyConstructors(
+ Throwable a, Throwable b, Throwable c, Throwable d, Throwable e, String s, Integer i) {}
+ }
+
+ public static final class ExceptionWithoutThrowableConstructor extends Exception {
+ public ExceptionWithoutThrowableConstructor(String s) {
+ super(s);
+ }
+ }
+
+ public static final class ExceptionWithWrongTypesConstructor extends Exception {
+ public ExceptionWithWrongTypesConstructor(Integer i, String s) {
+ super(s);
+ }
+ }
+
+ static final class ExceptionWithGoodAndBadConstructor extends Exception {
+ public ExceptionWithGoodAndBadConstructor(String message, Throwable cause) {
+ throw new RuntimeException("bad constructor");
+ }
+
+ public ExceptionWithGoodAndBadConstructor(Throwable cause) {
+ super(cause);
+ }
+ }
+
+ static final class ExceptionWithBadConstructor extends Exception {
+ public ExceptionWithBadConstructor(String message, Throwable cause) {
+ throw new RuntimeException("bad constructor");
+ }
+ }
+
+ static final class OtherThrowable extends Throwable {}
+
+ private FuturesGetCheckedInputs() {}
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/FuturesGetCheckedTest.java b/guava-tests/test/com/google/common/util/concurrent/FuturesGetCheckedTest.java
new file mode 100644
index 0000000..11a9844
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/FuturesGetCheckedTest.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.util.concurrent.Futures.getChecked;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.CHECKED_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.ERROR;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_CHECKED_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_ERROR;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_OTHER_THROWABLE;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_UNCHECKED_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.OTHER_THROWABLE;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.RUNTIME_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.RUNTIME_EXCEPTION_FUTURE;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.UNCHECKED_EXCEPTION;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import com.google.common.testing.GcFinalization;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithBadConstructor;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithGoodAndBadConstructor;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithManyConstructors;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithPrivateConstructor;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithSomePrivateConstructors;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithWrongTypesConstructor;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.ExceptionWithoutThrowableConstructor;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.TwoArgConstructorException;
+import com.google.common.util.concurrent.FuturesGetCheckedInputs.TwoArgConstructorRuntimeException;
+
+import junit.framework.TestCase;
+
+import java.lang.ref.WeakReference;
+import java.net.URLClassLoader;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Unit tests for {@link Futures#getChecked(Future, Class)}.
+ */
+public class FuturesGetCheckedTest extends TestCase {
+ // Boring untimed-get tests:
+
+ public void testGetCheckedUntimed_success() throws TwoArgConstructorException {
+ assertEquals("foo", getChecked(immediateFuture("foo"), TwoArgConstructorException.class));
+ }
+
+ public void testGetCheckedUntimed_interrupted() {
+ SettableFuture<String> future = SettableFuture.create();
+ Thread.currentThread().interrupt();
+ try {
+ getChecked(future, TwoArgConstructorException.class);
+ fail();
+ } catch (TwoArgConstructorException expected) {
+ assertThat(expected.getCause()).isInstanceOf(InterruptedException.class);
+ assertTrue(Thread.currentThread().isInterrupted());
+ } finally {
+ Thread.interrupted();
+ }
+ }
+
+ public void testGetCheckedUntimed_cancelled() throws TwoArgConstructorException {
+ SettableFuture<String> future = SettableFuture.create();
+ future.cancel(true);
+ try {
+ getChecked(future, TwoArgConstructorException.class);
+ fail();
+ } catch (CancellationException expected) {
+ }
+ }
+
+ public void testGetCheckedUntimed_ExecutionExceptionChecked() {
+ try {
+ getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, TwoArgConstructorException.class);
+ fail();
+ } catch (TwoArgConstructorException expected) {
+ assertEquals(CHECKED_EXCEPTION, expected.getCause());
+ }
+ }
+
+ public void testGetCheckedUntimed_ExecutionExceptionUnchecked()
+ throws TwoArgConstructorException {
+ try {
+ getChecked(FAILED_FUTURE_UNCHECKED_EXCEPTION, TwoArgConstructorException.class);
+ fail();
+ } catch (UncheckedExecutionException expected) {
+ assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
+ }
+ }
+
+ public void testGetCheckedUntimed_ExecutionExceptionError() throws TwoArgConstructorException {
+ try {
+ getChecked(FAILED_FUTURE_ERROR, TwoArgConstructorException.class);
+ fail();
+ } catch (ExecutionError expected) {
+ assertEquals(ERROR, expected.getCause());
+ }
+ }
+
+ public void testGetCheckedUntimed_ExecutionExceptionOtherThrowable() {
+ try {
+ getChecked(FAILED_FUTURE_OTHER_THROWABLE, TwoArgConstructorException.class);
+ fail();
+ } catch (TwoArgConstructorException expected) {
+ assertEquals(OTHER_THROWABLE, expected.getCause());
+ }
+ }
+
+ public void testGetCheckedUntimed_RuntimeException() throws TwoArgConstructorException {
+ try {
+ getChecked(RUNTIME_EXCEPTION_FUTURE, TwoArgConstructorException.class);
+ fail();
+ } catch (RuntimeException expected) {
+ assertEquals(RUNTIME_EXCEPTION, expected);
+ }
+ }
+
+ public void testGetCheckedUntimed_badExceptionConstructor_failsEvenForSuccessfulInput()
+ throws Exception {
+ try {
+ getChecked(immediateFuture("x"), ExceptionWithBadConstructor.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testGetCheckedUntimed_badExceptionConstructor_wrapsOriginalChecked()
+ throws Exception {
+ try {
+ getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithBadConstructor.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testGetCheckedUntimed_withGoodAndBadExceptionConstructor() throws Exception {
+ try {
+ getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithGoodAndBadConstructor.class);
+ fail();
+ } catch (ExceptionWithGoodAndBadConstructor expected) {
+ assertSame(CHECKED_EXCEPTION, expected.getCause());
+ }
+ }
+
+ // Boring timed-get tests:
+
+ public void testGetCheckedTimed_success() throws TwoArgConstructorException {
+ assertEquals(
+ "foo", getChecked(immediateFuture("foo"), TwoArgConstructorException.class, 0, SECONDS));
+ }
+
+ public void testGetCheckedTimed_interrupted() {
+ SettableFuture<String> future = SettableFuture.create();
+ Thread.currentThread().interrupt();
+ try {
+ getChecked(future, TwoArgConstructorException.class, 0, SECONDS);
+ fail();
+ } catch (TwoArgConstructorException expected) {
+ assertThat(expected.getCause()).isInstanceOf(InterruptedException.class);
+ assertTrue(Thread.currentThread().isInterrupted());
+ } finally {
+ Thread.interrupted();
+ }
+ }
+
+ public void testGetCheckedTimed_cancelled() throws TwoArgConstructorException {
+ SettableFuture<String> future = SettableFuture.create();
+ future.cancel(true);
+ try {
+ getChecked(future, TwoArgConstructorException.class, 0, SECONDS);
+ fail();
+ } catch (CancellationException expected) {
+ }
+ }
+
+ public void testGetCheckedTimed_ExecutionExceptionChecked() {
+ try {
+ getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, TwoArgConstructorException.class, 0, SECONDS);
+ fail();
+ } catch (TwoArgConstructorException expected) {
+ assertEquals(CHECKED_EXCEPTION, expected.getCause());
+ }
+ }
+
+ public void testGetCheckedTimed_ExecutionExceptionUnchecked() throws TwoArgConstructorException {
+ try {
+ getChecked(FAILED_FUTURE_UNCHECKED_EXCEPTION, TwoArgConstructorException.class, 0, SECONDS);
+ fail();
+ } catch (UncheckedExecutionException expected) {
+ assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
+ }
+ }
+
+ public void testGetCheckedTimed_ExecutionExceptionError() throws TwoArgConstructorException {
+ try {
+ getChecked(FAILED_FUTURE_ERROR, TwoArgConstructorException.class, 0, SECONDS);
+ fail();
+ } catch (ExecutionError expected) {
+ assertEquals(ERROR, expected.getCause());
+ }
+ }
+
+ public void testGetCheckedTimed_ExecutionExceptionOtherThrowable() {
+ try {
+ getChecked(FAILED_FUTURE_OTHER_THROWABLE, TwoArgConstructorException.class, 0, SECONDS);
+ fail();
+ } catch (TwoArgConstructorException expected) {
+ assertEquals(OTHER_THROWABLE, expected.getCause());
+ }
+ }
+
+ public void testGetCheckedTimed_RuntimeException() throws TwoArgConstructorException {
+ try {
+ getChecked(RUNTIME_EXCEPTION_FUTURE, TwoArgConstructorException.class, 0, SECONDS);
+ fail();
+ } catch (RuntimeException expected) {
+ assertEquals(RUNTIME_EXCEPTION, expected);
+ }
+ }
+
+ public void testGetCheckedTimed_TimeoutException() {
+ SettableFuture<String> future = SettableFuture.create();
+ try {
+ getChecked(future, TwoArgConstructorException.class, 0, SECONDS);
+ fail();
+ } catch (TwoArgConstructorException expected) {
+ assertThat(expected.getCause()).isInstanceOf(TimeoutException.class);
+ }
+ }
+
+ public void testGetCheckedTimed_badExceptionConstructor_failsEvenForSuccessfulInput()
+ throws Exception {
+ try {
+ getChecked(immediateFuture("x"), ExceptionWithBadConstructor.class, 1, TimeUnit.SECONDS);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testGetCheckedTimed_badExceptionConstructor_wrapsOriginalChecked() throws Exception {
+ try {
+ getChecked(
+ FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithBadConstructor.class, 1, TimeUnit.SECONDS);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testGetCheckedTimed_withGoodAndBadExceptionConstructor() throws Exception {
+ try {
+ getChecked(
+ FAILED_FUTURE_CHECKED_EXCEPTION,
+ ExceptionWithGoodAndBadConstructor.class,
+ 1,
+ TimeUnit.SECONDS);
+ fail();
+ } catch (ExceptionWithGoodAndBadConstructor expected) {
+ assertSame(CHECKED_EXCEPTION, expected.getCause());
+ }
+ }
+
+ // Edge case tests of the exception-construction code through untimed get():
+
+ @SuppressWarnings("FuturesGetCheckedIllegalExceptionType")
+ public void testGetCheckedUntimed_exceptionClassIsRuntimeException() {
+ try {
+ getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, TwoArgConstructorRuntimeException.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testGetCheckedUntimed_exceptionClassSomePrivateConstructors() {
+ try {
+ getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithSomePrivateConstructors.class);
+ fail();
+ } catch (ExceptionWithSomePrivateConstructors expected) {
+ }
+ }
+
+ @SuppressWarnings("FuturesGetCheckedIllegalExceptionType")
+ public void testGetCheckedUntimed_exceptionClassNoPublicConstructor()
+ throws ExceptionWithPrivateConstructor {
+ try {
+ getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithPrivateConstructor.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @SuppressWarnings("FuturesGetCheckedIllegalExceptionType")
+ public void testGetCheckedUntimed_exceptionClassPublicConstructorWrongType()
+ throws ExceptionWithWrongTypesConstructor {
+ try {
+ getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithWrongTypesConstructor.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testGetCheckedUntimed_exceptionClassPrefersStringConstructor() {
+ try {
+ getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithManyConstructors.class);
+ fail();
+ } catch (ExceptionWithManyConstructors expected) {
+ assertTrue(expected.usedExpectedConstructor);
+ }
+ }
+
+ public void testGetCheckedUntimed_exceptionClassUsedInitCause() {
+ try {
+ getChecked(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithoutThrowableConstructor.class);
+ fail();
+ } catch (ExceptionWithoutThrowableConstructor expected) {
+ assertThat(expected.getMessage()).contains("mymessage");
+ assertEquals(CHECKED_EXCEPTION, expected.getCause());
+ }
+ }
+
+ // Class unloading test:
+
+ public static final class WillBeUnloadedException extends Exception {}
+
+ public void testGetChecked_classUnloading() throws Exception {
+ WeakReference<?> classUsedByGetChecked = doTestClassUnloading();
+ GcFinalization.awaitClear(classUsedByGetChecked);
+ }
+
+ /**
+ * Loads {@link WillBeUnloadedException} in a separate {@code ClassLoader}, calls {@code
+ * getChecked(future, WillBeUnloadedException.class)}, and returns the loader. The caller can then
+ * test that the {@code ClassLoader} can still be GCed. The test amounts to a test that {@code
+ * getChecked} holds no strong references to the class.
+ */
+ private WeakReference<?> doTestClassUnloading() throws Exception {
+ URLClassLoader myLoader = (URLClassLoader) getClass().getClassLoader();
+ URLClassLoader shadowLoader = new URLClassLoader(myLoader.getURLs(), null);
+ @SuppressWarnings("unchecked")
+ Class<WillBeUnloadedException> shadowClass =
+ (Class<WillBeUnloadedException>)
+ Class.forName(WillBeUnloadedException.class.getName(), false, shadowLoader);
+ assertNotSame(shadowClass, WillBeUnloadedException.class);
+ getChecked(immediateFuture("foo"), shadowClass);
+ return new WeakReference<ClassLoader>(shadowLoader);
+ }
+
+ /*
+ * TODO(cpovirk): It would be great to run all these tests (including class unloading) in an
+ * environment that forces Futures.getChecked to its fallback WeakSetValidator. One awful way of
+ * doing so would be to derive a separate test library by using remove_from_jar to strip out
+ * ClassValueValidator.
+ */
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/FuturesGetUncheckedTest.java b/guava-tests/test/com/google/common/util/concurrent/FuturesGetUncheckedTest.java
new file mode 100644
index 0000000..b9db395
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/FuturesGetUncheckedTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.util.concurrent.Futures.getUnchecked;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.CHECKED_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.ERROR;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_CHECKED_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_ERROR;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_OTHER_THROWABLE;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.FAILED_FUTURE_UNCHECKED_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.OTHER_THROWABLE;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.RUNTIME_EXCEPTION;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.RUNTIME_EXCEPTION_FUTURE;
+import static com.google.common.util.concurrent.FuturesGetCheckedInputs.UNCHECKED_EXCEPTION;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.Future;
+
+/**
+ * Unit tests for {@link Futures#getUnchecked(Future)}.
+ */
+public class FuturesGetUncheckedTest extends TestCase {
+ public void testGetUnchecked_success() {
+ assertEquals("foo", getUnchecked(immediateFuture("foo")));
+ }
+
+ public void testGetUnchecked_interrupted() {
+ Thread.currentThread().interrupt();
+ try {
+ assertEquals("foo", getUnchecked(immediateFuture("foo")));
+ assertTrue(Thread.currentThread().isInterrupted());
+ } finally {
+ Thread.interrupted();
+ }
+ }
+
+ public void testGetUnchecked_cancelled() {
+ SettableFuture<String> future = SettableFuture.create();
+ future.cancel(true);
+ try {
+ getUnchecked(future);
+ fail();
+ } catch (CancellationException expected) {
+ }
+ }
+
+ public void testGetUnchecked_ExecutionExceptionChecked() {
+ try {
+ getUnchecked(FAILED_FUTURE_CHECKED_EXCEPTION);
+ fail();
+ } catch (UncheckedExecutionException expected) {
+ assertEquals(CHECKED_EXCEPTION, expected.getCause());
+ }
+ }
+
+ public void testGetUnchecked_ExecutionExceptionUnchecked() {
+ try {
+ getUnchecked(FAILED_FUTURE_UNCHECKED_EXCEPTION);
+ fail();
+ } catch (UncheckedExecutionException expected) {
+ assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
+ }
+ }
+
+ public void testGetUnchecked_ExecutionExceptionError() {
+ try {
+ getUnchecked(FAILED_FUTURE_ERROR);
+ fail();
+ } catch (ExecutionError expected) {
+ assertEquals(ERROR, expected.getCause());
+ }
+ }
+
+ public void testGetUnchecked_ExecutionExceptionOtherThrowable() {
+ try {
+ getUnchecked(FAILED_FUTURE_OTHER_THROWABLE);
+ fail();
+ } catch (UncheckedExecutionException expected) {
+ assertEquals(OTHER_THROWABLE, expected.getCause());
+ }
+ }
+
+ public void testGetUnchecked_RuntimeException() {
+ try {
+ getUnchecked(RUNTIME_EXCEPTION_FUTURE);
+ fail();
+ } catch (RuntimeException expected) {
+ assertEquals(RUNTIME_EXCEPTION, expected);
+ }
+ }
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/FuturesTest.java b/guava-tests/test/com/google/common/util/concurrent/FuturesTest.java
index b39dac0..7329064 100644
--- a/guava-tests/test/com/google/common/util/concurrent/FuturesTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/FuturesTest.java
@@ -17,23 +17,26 @@
package com.google.common.util.concurrent;
import static com.google.common.base.Throwables.propagateIfInstanceOf;
+import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.util.concurrent.Futures.allAsList;
-import static com.google.common.util.concurrent.Futures.get;
-import static com.google.common.util.concurrent.Futures.getUnchecked;
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static com.google.common.util.concurrent.Futures.successfulAsList;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static com.google.common.util.concurrent.MoreExecutors.newDirectExecutorService;
+import static com.google.common.util.concurrent.TestPlatform.clearInterrupt;
+import static com.google.common.util.concurrent.Uninterruptibles.awaitUninterruptibly;
+import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.easymock.EasyMock.expect;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@@ -41,14 +44,11 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.testing.ClassSanityTester;
import com.google.common.testing.TestLogHandler;
-import com.google.common.util.concurrent.ForwardingFuture.SimpleForwardingFuture;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
-import org.easymock.EasyMock;
-import org.easymock.IMocksControl;
-
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
@@ -64,6 +64,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
@@ -73,36 +74,35 @@ import javax.annotation.Nullable;
/**
* Unit tests for {@link Futures}.
*
- * TODO: Add tests for other Futures methods
- *
* @author Nishant Thakkar
*/
+ at SuppressWarnings("CheckReturnValue")
+ at GwtCompatible(emulated = true)
public class FuturesTest extends TestCase {
- private static final Logger combinedFutureLogger = Logger.getLogger(
- "com.google.common.util.concurrent.Futures$CombinedFuture");
- private final TestLogHandler combinedFutureLogHandler = new TestLogHandler();
+ private static final Logger aggregateFutureLogger =
+ Logger.getLogger(AggregateFuture.class.getName());
+ private final TestLogHandler aggregateFutureLogHandler = new TestLogHandler();
private static final String DATA1 = "data";
private static final String DATA2 = "more data";
private static final String DATA3 = "most data";
- private IMocksControl mocksControl;
-
- @Override protected void setUp() throws Exception {
+ @Override
+ protected void setUp() throws Exception {
super.setUp();
- combinedFutureLogger.addHandler(combinedFutureLogHandler);
- mocksControl = EasyMock.createControl();
+ aggregateFutureLogger.addHandler(aggregateFutureLogHandler);
}
- @Override protected void tearDown() throws Exception {
+ @Override
+ protected void tearDown() throws Exception {
/*
* Clear interrupt for future tests.
*
* (Ideally we would perform interrupts only in threads that we create, but
* it's hard to imagine that anything will break in practice.)
*/
- Thread.interrupted();
- combinedFutureLogger.removeHandler(combinedFutureLogHandler);
+ clearInterrupt();
+ aggregateFutureLogger.removeHandler(aggregateFutureLogHandler);
super.tearDown();
}
@@ -151,14 +151,60 @@ public class FuturesTest extends TestCase {
}
}
+ @GwtIncompatible("immediateCancelledFuture")
public void testImmediateCancelledFuture() throws Exception {
- ListenableFuture<String> future =
- Futures.immediateCancelledFuture();
+ ListenableFuture<String> future = CallerClass1.immediateCancelledFuture();
assertTrue(future.isCancelled());
+
+ try {
+ CallerClass2.get(future);
+ fail();
+ } catch (CancellationException e) {
+ // There should be two CancellationException chained together. The outer one should have the
+ // stack trace of where the get() call was made, and the inner should have the stack trace of
+ // where the immediateCancelledFuture() call was made.
+ List<StackTraceElement> stackTrace = ImmutableList.copyOf(e.getStackTrace());
+ assertFalse(Iterables.any(stackTrace, hasClassName(CallerClass1.class)));
+ assertTrue(Iterables.any(stackTrace, hasClassName(CallerClass2.class)));
+
+ assertThat(e.getCause()).isInstanceOf(CancellationException.class);
+ stackTrace = ImmutableList.copyOf(e.getCause().getStackTrace());
+ assertTrue(Iterables.any(stackTrace, hasClassName(CallerClass1.class)));
+ assertFalse(Iterables.any(stackTrace, hasClassName(CallerClass2.class)));
+ }
+ }
+
+ @GwtIncompatible("used only in GwtIncompatible tests")
+ private static Predicate<StackTraceElement> hasClassName(final Class<?> clazz) {
+ return new Predicate<StackTraceElement>() {
+ @Override
+ public boolean apply(StackTraceElement element) {
+ return element.getClassName().equals(clazz.getName());
+ }
+ };
+ }
+
+ @GwtIncompatible("used only in GwtIncompatible tests")
+ private static final class CallerClass1 {
+
+ static ListenableFuture<String> immediateCancelledFuture() {
+ return Futures.immediateCancelledFuture();
+ }
+ }
+
+ @GwtIncompatible("used only in GwtIncompatible tests")
+ private static final class CallerClass2 {
+
+ static <V> V get(ListenableFuture<V> future) throws ExecutionException, InterruptedException {
+ return future.get();
+ }
}
- private static class MyException extends Exception {}
+ private static class MyException extends Exception {
+
+ }
+ @GwtIncompatible("immediateCheckedFuture")
public void testImmediateCheckedFuture() throws Exception {
CheckedFuture<String, MyException> future = Futures.immediateCheckedFuture(
DATA1);
@@ -168,6 +214,7 @@ public class FuturesTest extends TestCase {
assertSame(DATA1, future.checkedGet(0L, TimeUnit.MILLISECONDS));
}
+ @GwtIncompatible("immediateCheckedFuture")
public void testMultipleImmediateCheckedFutures() throws Exception {
CheckedFuture<String, MyException> future1 = Futures.immediateCheckedFuture(
DATA1);
@@ -181,6 +228,7 @@ public class FuturesTest extends TestCase {
assertSame(DATA2, future2.checkedGet(0L, TimeUnit.MILLISECONDS));
}
+ @GwtIncompatible("immediateFailedCheckedFuture")
public void testImmediateFailedCheckedFuture() throws Exception {
MyException exception = new MyException();
CheckedFuture<String, MyException> future =
@@ -204,10 +252,21 @@ public class FuturesTest extends TestCase {
}
// Class hierarchy for generics sanity checks
- private static class Foo {}
- private static class FooChild extends Foo {}
- private static class Bar {}
- private static class BarChild extends Bar {}
+ private static class Foo {
+
+ }
+
+ private static class FooChild extends Foo {
+
+ }
+
+ private static class Bar {
+
+ }
+
+ private static class BarChild extends Bar {
+
+ }
public void testTransform_genericsNull() throws Exception {
ListenableFuture<?> nullFuture = Futures.immediateFuture(null);
@@ -220,7 +279,8 @@ public class FuturesTest extends TestCase {
ListenableFuture<FooChild> future = Futures.immediateFuture(null);
final BarChild barChild = new BarChild();
Function<Foo, BarChild> function = new Function<Foo, BarChild>() {
- @Override public BarChild apply(Foo unused) {
+ @Override
+ public BarChild apply(Foo unused) {
return barChild;
}
};
@@ -231,7 +291,8 @@ public class FuturesTest extends TestCase {
public void testTransform_cancelPropagatesToInput() throws Exception {
SettableFuture<Foo> input = SettableFuture.create();
AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
- @Override public ListenableFuture<Bar> apply(Foo unused) {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
throw new AssertionFailedError("Unexpeted call to apply.");
}
};
@@ -243,7 +304,8 @@ public class FuturesTest extends TestCase {
public void testTransform_interruptPropagatesToInput() throws Exception {
SettableFuture<Foo> input = SettableFuture.create();
AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
- @Override public ListenableFuture<Bar> apply(Foo unused) {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
throw new AssertionFailedError("Unexpeted call to apply.");
}
};
@@ -256,7 +318,8 @@ public class FuturesTest extends TestCase {
ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
final SettableFuture<Bar> secondary = SettableFuture.create();
AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
- @Override public ListenableFuture<Bar> apply(Foo unused) {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
return secondary;
}
};
@@ -270,7 +333,8 @@ public class FuturesTest extends TestCase {
ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
final SettableFuture<Bar> secondary = SettableFuture.create();
AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
- @Override public ListenableFuture<Bar> apply(Foo unused) {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
return secondary;
}
};
@@ -279,6 +343,100 @@ public class FuturesTest extends TestCase {
assertTrue(secondary.wasInterrupted());
}
+ public void testTransformAsync_cancelPropagatesToInput() throws Exception {
+ SettableFuture<Foo> input = SettableFuture.create();
+ AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
+ throw new AssertionFailedError("Unexpeted call to apply.");
+ }
+ };
+ assertTrue(Futures.transformAsync(input, function).cancel(false));
+ assertTrue(input.isCancelled());
+ assertFalse(input.wasInterrupted());
+ }
+
+ public void testTransformAsync_interruptPropagatesToInput() throws Exception {
+ SettableFuture<Foo> input = SettableFuture.create();
+ AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
+ throw new AssertionFailedError("Unexpeted call to apply.");
+ }
+ };
+ assertTrue(Futures.transformAsync(input, function).cancel(true));
+ assertTrue(input.isCancelled());
+ assertTrue(input.wasInterrupted());
+ }
+
+ @GwtIncompatible("threads")
+
+ public void testTransformAsync_interruptPropagatesToTransformingThread() throws Exception {
+ SettableFuture<String> input = SettableFuture.create();
+ final CountDownLatch inFunction = new CountDownLatch(1);
+ final CountDownLatch shouldCompleteFunction = new CountDownLatch(1);
+ final CountDownLatch gotException = new CountDownLatch(1);
+ AsyncFunction<String, String> function = new AsyncFunction<String, String>() {
+ @Override
+ public ListenableFuture<String> apply(String s) throws Exception {
+ inFunction.countDown();
+ try {
+ shouldCompleteFunction.await();
+ } catch (InterruptedException expected) {
+ gotException.countDown();
+ throw expected;
+ }
+ return immediateFuture("a");
+ }
+ };
+
+ ListenableFuture<String> futureResult =
+ Futures.transformAsync(input, function, newSingleThreadExecutor());
+
+ input.set("value");
+ inFunction.await();
+ futureResult.cancel(true);
+ shouldCompleteFunction.countDown();
+ try {
+ futureResult.get();
+ fail();
+ } catch (CancellationException expected) {}
+ // TODO(cpovirk): implement interruption, updating this test:
+ // https://github.com/google/guava/issues/1989
+ assertEquals(1, gotException.getCount());
+ // gotException.await();
+ }
+
+ public void testTransformAsync_cancelPropagatesToAsyncOutput() throws Exception {
+ ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
+ final SettableFuture<Bar> secondary = SettableFuture.create();
+ AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
+ return secondary;
+ }
+ };
+ assertTrue(Futures.transformAsync(immediate, function).cancel(false));
+ assertTrue(secondary.isCancelled());
+ assertFalse(secondary.wasInterrupted());
+ }
+
+ public void testTransformAsync_interruptPropagatesToAsyncOutput()
+ throws Exception {
+ ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
+ final SettableFuture<Bar> secondary = SettableFuture.create();
+ AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
+ @Override
+ public ListenableFuture<Bar> apply(Foo unused) {
+ return secondary;
+ }
+ };
+ assertTrue(Futures.transformAsync(immediate, function).cancel(true));
+ assertTrue(secondary.isCancelled());
+ assertTrue(secondary.wasInterrupted());
+ }
+
+ @GwtIncompatible("newDirectExecutorService")
public void testTransform_rejectionPropagatesToOutput()
throws Exception {
SettableFuture<Foo> input = SettableFuture.create();
@@ -291,23 +449,24 @@ public class FuturesTest extends TestCase {
transformed.get(5, TimeUnit.SECONDS);
fail();
} catch (ExecutionException expected) {
- assertTrue(expected.getCause() instanceof RejectedExecutionException);
+ assertThat(expected.getCause()).isInstanceOf(RejectedExecutionException.class);
}
}
/**
- * Tests that the function is invoked only once, even if it throws an
- * exception.
+ * Tests that the function is invoked only once, even if it throws an exception.
*/
public void testTransformValueRemainsMemoized() throws Exception {
class Holder {
+
int value = 2;
}
final Holder holder = new Holder();
// This function adds the holder's value to the input value.
Function<Integer, Integer> adder = new Function<Integer, Integer>() {
- @Override public Integer apply(Integer from) {
+ @Override
+ public Integer apply(Integer from) {
return from + holder.value;
}
};
@@ -343,14 +502,19 @@ public class FuturesTest extends TestCase {
1000, TimeUnit.SECONDS).intValue());
}
- static class MyError extends Error {}
- static class MyRuntimeException extends RuntimeException {}
+ static class MyError extends Error {
+
+ }
+
+ static class MyRuntimeException extends RuntimeException {
+
+ }
/**
- * Test that the function is invoked only once, even if it throws an
- * exception. Also, test that that function's result is wrapped in an
- * ExecutionException.
+ * Test that the function is invoked only once, even if it throws an exception. Also, test that
+ * that function's result is wrapped in an ExecutionException.
*/
+ @GwtIncompatible("reflection")
public void testTransformExceptionRemainsMemoized() throws Throwable {
// We need to test with two input futures since ExecutionList.execute
// doesn't catch Errors and we cannot depend on the order that our
@@ -381,6 +545,7 @@ public class FuturesTest extends TestCase {
runGetIdempotencyTest(errorComposedFuture, MyError.class);
}
+ @GwtIncompatible("reflection")
private static void runGetIdempotencyTest(Future<Integer> transformedFuture,
Class<? extends Throwable> expectedExceptionClass) throws Throwable {
for (int i = 0; i < 5; i++) {
@@ -395,11 +560,13 @@ public class FuturesTest extends TestCase {
}
}
+ @GwtIncompatible("used only in GwtIncompatible tests")
private static Function<Integer, Integer> newOneTimeExceptionThrower() {
return new Function<Integer, Integer>() {
int calls = 0;
- @Override public Integer apply(Integer from) {
+ @Override
+ public Integer apply(Integer from) {
if (++calls > 1) {
fail();
}
@@ -408,11 +575,13 @@ public class FuturesTest extends TestCase {
};
}
+ @GwtIncompatible("used only in GwtIncompatible tests")
private static Function<Integer, Integer> newOneTimeErrorThrower() {
return new Function<Integer, Integer>() {
int calls = 0;
- @Override public Integer apply(Integer from) {
+ @Override
+ public Integer apply(Integer from) {
if (++calls > 1) {
fail();
}
@@ -423,6 +592,7 @@ public class FuturesTest extends TestCase {
// TODO(cpovirk): top-level class?
static class ExecutorSpy implements Executor {
+
Executor delegate;
boolean wasExecuted;
@@ -430,7 +600,8 @@ public class FuturesTest extends TestCase {
this.delegate = delegate;
}
- @Override public void execute(Runnable command) {
+ @Override
+ public void execute(Runnable command) {
delegate.execute(command);
wasExecuted = true;
}
@@ -450,22 +621,25 @@ public class FuturesTest extends TestCase {
assertTrue(spy.wasExecuted);
}
+ @GwtIncompatible("lazyTransform")
public void testLazyTransform() throws Exception {
FunctionSpy<Object, String> spy =
new FunctionSpy<Object, String>(Functions.constant("bar"));
Future<String> input = Futures.immediateFuture("foo");
Future<String> transformed = Futures.lazyTransform(input, spy);
- assertEquals(0, spy.getApplyCount());
+ spy.verifyCallCount(0);
assertEquals("bar", transformed.get());
- assertEquals(1, spy.getApplyCount());
+ spy.verifyCallCount(1);
assertEquals("bar", transformed.get());
- assertEquals(2, spy.getApplyCount());
+ spy.verifyCallCount(2);
}
+ @GwtIncompatible("lazyTransform")
public void testLazyTransform_exception() throws Exception {
final RuntimeException exception = new RuntimeException("deliberate");
Function<Integer, String> function = new Function<Integer, String>() {
- @Override public String apply(Integer input) {
+ @Override
+ public String apply(Integer input) {
throw exception;
}
};
@@ -498,33 +672,116 @@ public class FuturesTest extends TestCase {
return delegate.apply(input);
}
- public int getApplyCount() {
- return applyCount;
+ void verifyCallCount(int expected) {
+ assertThat(applyCount).isEqualTo(expected);
}
}
- @SuppressWarnings("unchecked")
+ private static <I, O> FunctionSpy<I, O> spy(Function<I, O> delegate) {
+ return new FunctionSpy<I, O>(delegate);
+ }
+
+ private static <X extends Throwable, V> Function<X, V> unexpectedFunction() {
+ return new Function<X, V>() {
+ @Override
+ public V apply(X t) {
+ throw newAssertionError("Unexpected fallback", t);
+ }
+ };
+ }
+
+ private static class FutureFallbackSpy<V> implements FutureFallback<V> {
+
+ private int count;
+ private final FutureFallback<V> delegate;
+
+ public FutureFallbackSpy(FutureFallback<V> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public final ListenableFuture<V> create(Throwable t) throws Exception {
+ count++;
+ return delegate.create(t);
+ }
+
+ void verifyCallCount(int expected) {
+ assertThat(count).isEqualTo(expected);
+ }
+ }
+
+ private static <V> FutureFallbackSpy<V> spy(FutureFallback<V> delegate) {
+ return new FutureFallbackSpy<V>(delegate);
+ }
+
+ private static <V> FutureFallback<V> unexpectedFallback() {
+ return new FutureFallback<V>() {
+ @Override
+ public ListenableFuture<V> create(Throwable t) {
+ throw newAssertionError("Unexpected fallback", t);
+ }
+ };
+ }
+
+ private static class AsyncFunctionSpy<X extends Throwable, V> implements AsyncFunction<X, V> {
+ private int count;
+ private final AsyncFunction<X, V> delegate;
+
+ public AsyncFunctionSpy(AsyncFunction<X, V> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public final ListenableFuture<V> apply(X t) throws Exception {
+ count++;
+ return delegate.apply(t);
+ }
+
+ void verifyCallCount(int expected) {
+ assertThat(count).isEqualTo(expected);
+ }
+ }
+
+ private static <X extends Throwable, V> AsyncFunctionSpy<X, V> spy(AsyncFunction<X, V> delegate) {
+ return new AsyncFunctionSpy<X, V>(delegate);
+ }
+
+ private static <X extends Throwable, V> AsyncFunction<X, V> unexpectedAsyncFunction() {
+ return new AsyncFunction<X, V>() {
+ @Override
+ public ListenableFuture<V> apply(X t) {
+ throw newAssertionError("Unexpected fallback", t);
+ }
+ };
+ }
+
+ /** Alternative to AssertionError(String, Throwable), which doesn't exist in GWT 2.6.1. */
+ private static AssertionError newAssertionError(String message, Throwable cause) {
+ AssertionError e = new AssertionError(message);
+ e.initCause(cause);
+ return e;
+ }
+
public void testWithFallback_inputDoesNotRaiseException() throws Exception {
- FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
+ FutureFallback<Integer> fallback = unexpectedFallback();
ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
-
- mocksControl.replay();
ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(originalFuture, fallback);
assertEquals(7, faultToleranteFuture.get().intValue());
- mocksControl.verify();
}
- @SuppressWarnings("unchecked")
public void testWithFallback_inputRaisesException() throws Exception {
- FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
- RuntimeException raisedException = new RuntimeException();
- expect(fallback.create(raisedException)).andReturn(Futures.immediateFuture(20));
+ final RuntimeException raisedException = new RuntimeException();
+ FutureFallbackSpy<Integer> fallback = spy(new FutureFallback<Integer>() {
+ @Override
+ public ListenableFuture<Integer> create(Throwable t) throws Exception {
+ assertThat(t).isSameAs(raisedException);
+ return Futures.immediateFuture(20);
+ }
+ });
ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
-
- mocksControl.replay();
- ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(failingFuture, fallback);
- assertEquals(20, faultToleranteFuture.get().intValue());
- mocksControl.verify();
+ ListenableFuture<Integer> faultTolerantFuture = Futures.withFallback(failingFuture, fallback);
+ assertEquals(20, faultTolerantFuture.get().intValue());
+ fallback.verifyCallCount(1);
}
public void testWithFallback_fallbackGeneratesRuntimeException() throws Exception {
@@ -533,15 +790,16 @@ public class FuturesTest extends TestCase {
}
public void testWithFallback_fallbackGeneratesCheckedException() throws Exception {
- Exception expectedException = new Exception() {};
+ Exception expectedException = new Exception() {
+ };
runExpectedExceptionFallbackTest(expectedException, false);
}
- @SuppressWarnings("unchecked")
public void testWithFallback_fallbackGeneratesError() throws Exception {
final Error error = new Error("deliberate");
FutureFallback<Integer> fallback = new FutureFallback<Integer>() {
- @Override public ListenableFuture<Integer> create(Throwable t) throws Exception {
+ @Override
+ public ListenableFuture<Integer> create(Throwable t) throws Exception {
throw error;
}
};
@@ -560,27 +818,26 @@ public class FuturesTest extends TestCase {
}
public void testWithFallback_fallbackReturnsCheckedException() throws Exception {
- Exception expectedException = new Exception() {};
+ Exception expectedException = new Exception() {
+ };
runExpectedExceptionFallbackTest(expectedException, true);
}
- @SuppressWarnings("unchecked")
private void runExpectedExceptionFallbackTest(
- Throwable expectedException, boolean wrapInFuture) throws Exception {
- FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
- RuntimeException raisedException = new RuntimeException();
- if (!wrapInFuture) {
- // Exception is thrown in the body of the "fallback" method.
- expect(fallback.create(raisedException)).andThrow(expectedException);
- } else {
- // Exception is wrapped in a future and returned.
- expect(fallback.create(raisedException)).andReturn(
- Futures.<Integer>immediateFailedFuture(expectedException));
- }
+ final Exception expectedException, final boolean wrapInFuture) throws Exception {
+ FutureFallbackSpy<Integer> fallback = spy(new FutureFallback<Integer>() {
+ @Override
+ public ListenableFuture<Integer> create(Throwable t) throws Exception {
+ if (!wrapInFuture) {
+ throw expectedException;
+ } else {
+ return Futures.immediateFailedFuture(expectedException);
+ }
+ }
+ });
- ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
- mocksControl.replay();
ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(failingFuture, fallback);
try {
faultToleranteFuture.get();
@@ -588,7 +845,7 @@ public class FuturesTest extends TestCase {
} catch (ExecutionException ee) {
assertSame(expectedException, ee.getCause());
}
- mocksControl.verify();
+ fallback.verifyCallCount(1);
}
public void testWithFallback_fallbackNotReady() throws Exception {
@@ -605,122 +862,567 @@ public class FuturesTest extends TestCase {
assertEquals(1, (int) derived.get());
}
- @SuppressWarnings("unchecked")
public void testWithFallback_resultInterruptedBeforeFallback() throws Exception {
SettableFuture<Integer> primary = SettableFuture.create();
- FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
-
- mocksControl.replay();
+ FutureFallback<Integer> fallback = unexpectedFallback();
ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
derived.cancel(true);
assertTrue(primary.isCancelled());
assertTrue(primary.wasInterrupted());
- mocksControl.verify();
}
- @SuppressWarnings("unchecked")
public void testWithFallback_resultCancelledBeforeFallback() throws Exception {
SettableFuture<Integer> primary = SettableFuture.create();
- FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
-
- mocksControl.replay();
+ FutureFallback<Integer> fallback = unexpectedFallback();
ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
derived.cancel(false);
assertTrue(primary.isCancelled());
assertFalse(primary.wasInterrupted());
- mocksControl.verify();
}
+ @GwtIncompatible("mocks")
@SuppressWarnings("unchecked")
public void testWithFallback_resultCancelledAfterFallback() throws Exception {
- SettableFuture<Integer> secondary = SettableFuture.create();
- FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
- RuntimeException raisedException = new RuntimeException();
- expect(fallback.create(raisedException)).andReturn(secondary);
+ final SettableFuture<Integer> secondary = SettableFuture.create();
+ final RuntimeException raisedException = new RuntimeException();
+ FutureFallbackSpy<Integer> fallback = spy(new FutureFallback<Integer>() {
+ @Override
+ public ListenableFuture<Integer> create(Throwable t) throws Exception {
+ assertThat(t).isSameAs(raisedException);
+ return secondary;
+ }
+ });
+
ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
- mocksControl.replay();
ListenableFuture<Integer> derived = Futures.withFallback(failingFuture, fallback);
derived.cancel(false);
assertTrue(secondary.isCancelled());
assertFalse(secondary.wasInterrupted());
- mocksControl.verify();
+ fallback.verifyCallCount(1);
}
- public void testTransform_genericsWildcard_AsyncFunction() throws Exception {
- ListenableFuture<?> nullFuture = Futures.immediateFuture(null);
+ public void testWithFallback_nullInsteadOfFuture() throws Exception {
+ ListenableFuture<Integer> inputFuture = immediateFailedFuture(new Exception());
ListenableFuture<?> chainedFuture =
- Futures.transform(nullFuture, constantAsyncFunction(nullFuture));
- assertNull(chainedFuture.get());
+ Futures.withFallback(inputFuture, new FutureFallback<Integer>() {
+ @Override
+ public ListenableFuture<Integer> create(Throwable t) {
+ return null;
+ }
+ });
+ try {
+ chainedFuture.get();
+ fail();
+ } catch (ExecutionException expected) {
+ NullPointerException cause = (NullPointerException) expected.getCause();
+ assertThat(cause).hasMessage("FutureFallback.create returned null instead of a Future. "
+ + "Did you mean to return immediateFuture(null)?");
+ }
}
- private static <I, O> AsyncFunction<I, O> constantAsyncFunction(
- final ListenableFuture<O> output) {
- return new AsyncFunction<I, O>() {
+ // catchingAsync tests cloned from the old withFallback tests:
+
+ public void testCatchingAsync_inputDoesNotRaiseException() throws Exception {
+ AsyncFunction<Throwable, Integer> fallback = unexpectedAsyncFunction();
+ ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
+ ListenableFuture<Integer> faultToleranteFuture =
+ Futures.catchingAsync(originalFuture, Throwable.class, fallback);
+ assertEquals(7, faultToleranteFuture.get().intValue());
+ }
+
+ public void testCatchingAsync_inputRaisesException() throws Exception {
+ final RuntimeException raisedException = new RuntimeException();
+ AsyncFunctionSpy<Throwable, Integer> fallback = spy(new AsyncFunction<Throwable, Integer>() {
@Override
- public ListenableFuture<O> apply(I input) {
- return output;
+ public ListenableFuture<Integer> apply(Throwable t) throws Exception {
+ assertThat(t).isSameAs(raisedException);
+ return Futures.immediateFuture(20);
}
- };
+ });
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+ ListenableFuture<Integer> faultTolerantFuture =
+ Futures.catchingAsync(failingFuture, Throwable.class, fallback);
+ assertEquals(20, faultTolerantFuture.get().intValue());
+ fallback.verifyCallCount(1);
}
- public void testTransform_genericsHierarchy_AsyncFunction() throws Exception {
- ListenableFuture<FooChild> future = Futures.immediateFuture(null);
- final BarChild barChild = new BarChild();
- AsyncFunction<Foo, BarChild> function =
- new AsyncFunction<Foo, BarChild>() {
- @Override public AbstractFuture<BarChild> apply(Foo unused) {
- AbstractFuture<BarChild> future = new AbstractFuture<BarChild>() {};
- future.set(barChild);
- return future;
- }
- };
- Bar bar = Futures.transform(future, function).get();
- assertSame(barChild, bar);
+ public void testCatchingAsync_fallbackGeneratesRuntimeException() throws Exception {
+ RuntimeException expectedException = new RuntimeException();
+ runExpectedExceptionCatchingAsyncTest(expectedException, false);
}
- public void testTransform_asyncFunction_timeout()
- throws InterruptedException, ExecutionException {
- AsyncFunction<String, Integer> function = constantAsyncFunction(Futures.immediateFuture(1));
- ListenableFuture<Integer> future = Futures.transform(
- SettableFuture.<String>create(), function);
- try {
- future.get(1, TimeUnit.MILLISECONDS);
- fail();
- } catch (TimeoutException expected) {}
+ public void testCatchingAsync_fallbackGeneratesCheckedException() throws Exception {
+ Exception expectedException = new Exception() {
+ };
+ runExpectedExceptionCatchingAsyncTest(expectedException, false);
}
- public void testTransform_asyncFunction_error() throws InterruptedException {
+ public void testCatchingAsync_fallbackGeneratesError() throws Exception {
final Error error = new Error("deliberate");
- AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
- @Override public ListenableFuture<Integer> apply(String input) {
+ AsyncFunction<Throwable, Integer> fallback = new AsyncFunction<Throwable, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(Throwable t) throws Exception {
throw error;
}
};
- SettableFuture<String> inputFuture = SettableFuture.create();
- ListenableFuture<Integer> outputFuture = Futures.transform(inputFuture, function);
- inputFuture.set("value");
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
try {
- outputFuture.get();
- fail("should have thrown error");
- } catch (ExecutionException e) {
- assertSame(error, e.getCause());
+ Futures.catchingAsync(failingFuture, Throwable.class, fallback).get();
+ fail("An Exception should have been thrown!");
+ } catch (ExecutionException expected) {
+ assertSame(error, expected.getCause());
}
}
- public void testTransform_asyncFunction_cancelledWhileApplyingFunction()
- throws InterruptedException, ExecutionException {
- final CountDownLatch inFunction = new CountDownLatch(1);
- final CountDownLatch functionDone = new CountDownLatch(1);
- final SettableFuture<Integer> resultFuture = SettableFuture.create();
- AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
- @Override public ListenableFuture<Integer> apply(String input) throws Exception {
- inFunction.countDown();
- functionDone.await();
- return resultFuture;
- }
- };
- SettableFuture<String> inputFuture = SettableFuture.create();
+ public void testCatchingAsync_fallbackReturnsRuntimeException() throws Exception {
+ RuntimeException expectedException = new RuntimeException();
+ runExpectedExceptionCatchingAsyncTest(expectedException, true);
+ }
+
+ public void testCatchingAsync_fallbackReturnsCheckedException() throws Exception {
+ Exception expectedException = new Exception() {
+ };
+ runExpectedExceptionCatchingAsyncTest(expectedException, true);
+ }
+
+ private void runExpectedExceptionCatchingAsyncTest(
+ final Exception expectedException, final boolean wrapInFuture) throws Exception {
+ AsyncFunctionSpy<Throwable, Integer> fallback = spy(new AsyncFunction<Throwable, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(Throwable t) throws Exception {
+ if (!wrapInFuture) {
+ throw expectedException;
+ } else {
+ return Futures.immediateFailedFuture(expectedException);
+ }
+ }
+ });
+
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+
+ ListenableFuture<Integer> faultToleranteFuture =
+ Futures.catchingAsync(failingFuture, Throwable.class, fallback);
+ try {
+ faultToleranteFuture.get();
+ fail("An Exception should have been thrown!");
+ } catch (ExecutionException ee) {
+ assertSame(expectedException, ee.getCause());
+ }
+ fallback.verifyCallCount(1);
+ }
+
+ public void testCatchingAsync_fallbackNotReady() throws Exception {
+ ListenableFuture<Integer> primary = immediateFailedFuture(new Exception());
+ final SettableFuture<Integer> secondary = SettableFuture.create();
+ AsyncFunction<Throwable, Integer> fallback = new AsyncFunction<Throwable, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(Throwable t) {
+ return secondary;
+ }
+ };
+ ListenableFuture<Integer> derived = Futures.catchingAsync(primary, Throwable.class, fallback);
+ secondary.set(1);
+ assertEquals(1, (int) derived.get());
+ }
+
+ public void testCatchingAsync_resultInterruptedBeforeFallback() throws Exception {
+ SettableFuture<Integer> primary = SettableFuture.create();
+ AsyncFunction<Throwable, Integer> fallback = unexpectedAsyncFunction();
+ ListenableFuture<Integer> derived = Futures.catchingAsync(primary, Throwable.class, fallback);
+ derived.cancel(true);
+ assertTrue(primary.isCancelled());
+ assertTrue(primary.wasInterrupted());
+ }
+
+ public void testCatchingAsync_resultCancelledBeforeFallback() throws Exception {
+ SettableFuture<Integer> primary = SettableFuture.create();
+ AsyncFunction<Throwable, Integer> fallback = unexpectedAsyncFunction();
+ ListenableFuture<Integer> derived = Futures.catchingAsync(primary, Throwable.class, fallback);
+ derived.cancel(false);
+ assertTrue(primary.isCancelled());
+ assertFalse(primary.wasInterrupted());
+ }
+
+ @GwtIncompatible("mocks")
+ @SuppressWarnings("unchecked")
+ public void testCatchingAsync_resultCancelledAfterFallback() throws Exception {
+ final SettableFuture<Integer> secondary = SettableFuture.create();
+ final RuntimeException raisedException = new RuntimeException();
+ AsyncFunctionSpy<Throwable, Integer> fallback = spy(new AsyncFunction<Throwable, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(Throwable t) throws Exception {
+ assertThat(t).isSameAs(raisedException);
+ return secondary;
+ }
+ });
+
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+
+ ListenableFuture<Integer> derived =
+ Futures.catchingAsync(failingFuture, Throwable.class, fallback);
+ derived.cancel(false);
+ assertTrue(secondary.isCancelled());
+ assertFalse(secondary.wasInterrupted());
+ fallback.verifyCallCount(1);
+ }
+
+ public void testCatchingAsync_nullInsteadOfFuture() throws Exception {
+ ListenableFuture<Integer> inputFuture = immediateFailedFuture(new Exception());
+ ListenableFuture<?> chainedFuture = Futures.catchingAsync(inputFuture, Throwable.class,
+ new AsyncFunction<Throwable, Integer>() {
+ @Override
+ @SuppressWarnings("AsyncFunctionReturnsNull")
+ public ListenableFuture<Integer> apply(Throwable t) {
+ return null;
+ }
+ });
+ try {
+ chainedFuture.get();
+ fail();
+ } catch (ExecutionException expected) {
+ NullPointerException cause = (NullPointerException) expected.getCause();
+ assertThat(cause).hasMessage("AsyncFunction.apply returned null instead of a Future. "
+ + "Did you mean to return immediateFuture(null)?");
+ }
+ }
+
+ @GwtIncompatible("threads")
+
+ public void testCatchingAsync_interruptPropagatesToTransformingThread() throws Exception {
+ SettableFuture<String> input = SettableFuture.create();
+ final CountDownLatch inFunction = new CountDownLatch(1);
+ final CountDownLatch shouldCompleteFunction = new CountDownLatch(1);
+ final CountDownLatch gotException = new CountDownLatch(1);
+ AsyncFunction<Throwable, String> function = new AsyncFunction<Throwable, String>() {
+ @Override
+ public ListenableFuture<String> apply(Throwable t) throws Exception {
+ inFunction.countDown();
+ try {
+ shouldCompleteFunction.await();
+ } catch (InterruptedException expected) {
+ gotException.countDown();
+ throw expected;
+ }
+ return immediateFuture("a");
+ }
+ };
+
+ ListenableFuture<String> futureResult =
+ Futures.catchingAsync(input, Exception.class, function, newSingleThreadExecutor());
+
+ input.setException(new Exception());
+ inFunction.await();
+ futureResult.cancel(true);
+ shouldCompleteFunction.countDown();
+ try {
+ futureResult.get();
+ fail();
+ } catch (CancellationException expected) {}
+ // TODO(cpovirk): implement interruption, updating this test:
+ // https://github.com/google/guava/issues/1989
+ assertEquals(1, gotException.getCount());
+ // gotException.await();
+ }
+
+ // catching tests cloned from the old withFallback tests:
+
+ public void testCatching_inputDoesNotRaiseException() throws Exception {
+ Function<Throwable, Integer> fallback = unexpectedFunction();
+ ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
+ ListenableFuture<Integer> faultToleranteFuture =
+ Futures.catching(originalFuture, Throwable.class, fallback);
+ assertEquals(7, faultToleranteFuture.get().intValue());
+ }
+
+ public void testCatching_inputRaisesException() throws Exception {
+ final RuntimeException raisedException = new RuntimeException();
+ FunctionSpy<Throwable, Integer> fallback = spy(new Function<Throwable, Integer>() {
+ @Override
+ public Integer apply(Throwable t) {
+ assertThat(t).isSameAs(raisedException);
+ return 20;
+ }
+ });
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
+ ListenableFuture<Integer> faultTolerantFuture =
+ Futures.catching(failingFuture, Throwable.class, fallback);
+ assertEquals(20, faultTolerantFuture.get().intValue());
+ fallback.verifyCallCount(1);
+ }
+
+ public void testCatching_fallbackGeneratesRuntimeException() throws Exception {
+ RuntimeException expectedException = new RuntimeException();
+ runExpectedExceptionCatchingTest(expectedException);
+ }
+
+ /*
+ * catching() uses a plain Function, so there's no
+ * testCatching_fallbackGeneratesCheckedException().
+ */
+
+ public void testCatching_fallbackGeneratesError() throws Exception {
+ final Error error = new Error("deliberate");
+ Function<Throwable, Integer> fallback = new Function<Throwable, Integer>() {
+ @Override
+ public Integer apply(Throwable t) {
+ throw error;
+ }
+ };
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+ try {
+ Futures.catching(failingFuture, Throwable.class, fallback).get();
+ fail("An Exception should have been thrown!");
+ } catch (ExecutionException expected) {
+ assertSame(error, expected.getCause());
+ }
+ }
+
+ /*
+ * catching() uses a plain Function, so there's no testCatching_fallbackReturnsRuntimeException()
+ * or testCatching_fallbackReturnsCheckedException().
+ */
+
+ private void runExpectedExceptionCatchingTest(final RuntimeException expectedException)
+ throws Exception {
+ FunctionSpy<Throwable, Integer> fallback = spy(new Function<Throwable, Integer>() {
+ @Override
+ public Integer apply(Throwable t) {
+ throw expectedException;
+ }
+ });
+
+ ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
+
+ ListenableFuture<Integer> faultToleranteFuture =
+ Futures.catching(failingFuture, Throwable.class, fallback);
+ try {
+ faultToleranteFuture.get();
+ fail("An Exception should have been thrown!");
+ } catch (ExecutionException ee) {
+ assertSame(expectedException, ee.getCause());
+ }
+ fallback.verifyCallCount(1);
+ }
+
+ // catching() uses a plain Function, so there's no testCatching_fallbackNotReady().
+
+ public void testCatching_resultInterruptedBeforeFallback() throws Exception {
+ SettableFuture<Integer> primary = SettableFuture.create();
+ Function<Throwable, Integer> fallback = unexpectedFunction();
+ ListenableFuture<Integer> derived = Futures.catching(primary, Throwable.class, fallback);
+ derived.cancel(true);
+ assertTrue(primary.isCancelled());
+ assertTrue(primary.wasInterrupted());
+ }
+
+ public void testCatching_resultCancelledBeforeFallback() throws Exception {
+ SettableFuture<Integer> primary = SettableFuture.create();
+ Function<Throwable, Integer> fallback = unexpectedFunction();
+ ListenableFuture<Integer> derived = Futures.catching(primary, Throwable.class, fallback);
+ derived.cancel(false);
+ assertTrue(primary.isCancelled());
+ assertFalse(primary.wasInterrupted());
+ }
+
+ // catching() uses a plain Function, so there's no testCatching_resultCancelledAfterFallback().
+
+ // catching() uses a plain Function, so there's no testCatching_nullInsteadOfFuture().
+
+ // Some tests of the exceptionType parameter:
+
+ public void testCatching_Throwable() throws Exception {
+ Function<Throwable, Integer> fallback = functionReturningOne();
+ ListenableFuture<Integer> originalFuture = immediateFailedFuture(new IOException());
+ ListenableFuture<Integer> faultTolerantFuture =
+ Futures.catching(originalFuture, Throwable.class, fallback);
+ assertEquals(1, (int) faultTolerantFuture.get());
+ }
+
+ @GwtIncompatible("non-Throwable exceptionType")
+ public void testCatching_customTypeMatch() throws Exception {
+ Function<IOException, Integer> fallback = functionReturningOne();
+ ListenableFuture<Integer> originalFuture = immediateFailedFuture(new FileNotFoundException());
+ ListenableFuture<Integer> faultTolerantFuture =
+ Futures.catching(originalFuture, IOException.class, fallback);
+ assertEquals(1, (int) faultTolerantFuture.get());
+ }
+
+ @GwtIncompatible("non-Throwable exceptionType")
+ public void testCatching_customTypeNoMatch() throws Exception {
+ Function<IOException, Integer> fallback = functionReturningOne();
+ ListenableFuture<Integer> originalFuture = immediateFailedFuture(new RuntimeException());
+ ListenableFuture<Integer> faultTolerantFuture =
+ Futures.catching(originalFuture, IOException.class, fallback);
+ try {
+ faultTolerantFuture.get();
+ fail();
+ } catch (ExecutionException expected) {
+ assertThat(expected.getCause()).isInstanceOf(RuntimeException.class);
+ }
+ }
+
+ public void testCatchingAsync_Throwable() throws Exception {
+ AsyncFunction<Throwable, Integer> fallback = asyncFunctionReturningOne();
+ ListenableFuture<Integer> originalFuture = immediateFailedFuture(new IOException());
+ ListenableFuture<Integer> faultTolerantFuture =
+ Futures.catchingAsync(originalFuture, Throwable.class, fallback);
+ assertEquals(1, (int) faultTolerantFuture.get());
+ }
+
+ @GwtIncompatible("non-Throwable exceptionType")
+ public void testCatchingAsync_customTypeMatch() throws Exception {
+ AsyncFunction<IOException, Integer> fallback = asyncFunctionReturningOne();
+ ListenableFuture<Integer> originalFuture = immediateFailedFuture(new FileNotFoundException());
+ ListenableFuture<Integer> faultTolerantFuture =
+ Futures.catchingAsync(originalFuture, IOException.class, fallback);
+ assertEquals(1, (int) faultTolerantFuture.get());
+ }
+
+ @GwtIncompatible("non-Throwable exceptionType")
+ public void testCatchingAsync_customTypeNoMatch() throws Exception {
+ AsyncFunction<IOException, Integer> fallback = asyncFunctionReturningOne();
+ ListenableFuture<Integer> originalFuture = immediateFailedFuture(new RuntimeException());
+ ListenableFuture<Integer> faultTolerantFuture =
+ Futures.catchingAsync(originalFuture, IOException.class, fallback);
+ try {
+ faultTolerantFuture.get();
+ fail();
+ } catch (ExecutionException expected) {
+ assertThat(expected.getCause()).isInstanceOf(RuntimeException.class);
+ }
+ }
+
+ @GwtIncompatible("newDirectExecutorService")
+ public void testCatchingAsync_rejectionPropagatesToOutput() throws Exception {
+ SettableFuture<String> input = SettableFuture.create();
+ ExecutorService executor = newDirectExecutorService();
+ ListenableFuture<String> transformed =
+ Futures.catching(input, Throwable.class, Functions.toStringFunction(), executor);
+ executor.shutdown();
+ input.setException(new Exception());
+ try {
+ transformed.get(5, TimeUnit.SECONDS);
+ fail();
+ } catch (ExecutionException expected) {
+ assertThat(expected.getCause()).isInstanceOf(RejectedExecutionException.class);
+ }
+ }
+
+ private <X extends Throwable> Function<X, Integer> functionReturningOne() {
+ return new Function<X, Integer>() {
+ @Override
+ public Integer apply(X t) {
+ return 1;
+ }
+ };
+ }
+
+ private <X extends Throwable> AsyncFunction<X, Integer> asyncFunctionReturningOne() {
+ return new AsyncFunction<X, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(X t) {
+ return immediateFuture(1);
+ }
+ };
+ }
+
+ private static <I, O> AsyncFunction<I, O> constantAsyncFunction(
+ final ListenableFuture<O> output) {
+ return new AsyncFunction<I, O>() {
+ @Override
+ public ListenableFuture<O> apply(I input) {
+ return output;
+ }
+ };
+ }
+
+ public void testTransform_genericsWildcard_AsyncFunction() throws Exception {
+ ListenableFuture<?> nullFuture = immediateFuture(null);
+ ListenableFuture<?> chainedFuture =
+ Futures.transform(nullFuture, constantAsyncFunction(nullFuture));
+ assertNull(chainedFuture.get());
+ }
+
+ public void testTransform_genericsHierarchy_AsyncFunction() throws Exception {
+ ListenableFuture<FooChild> future = Futures.immediateFuture(null);
+ final BarChild barChild = new BarChild();
+ AsyncFunction<Foo, BarChild> function =
+ new AsyncFunction<Foo, BarChild>() {
+ @Override
+ public AbstractFuture<BarChild> apply(Foo unused) {
+ AbstractFuture<BarChild> future = new AbstractFuture<BarChild>() {
+ };
+ future.set(barChild);
+ return future;
+ }
+ };
+ Bar bar = Futures.transform(future, function).get();
+ assertSame(barChild, bar);
+ }
+
+ @GwtIncompatible("get() timeout")
+ public void testTransform_asyncFunction_timeout()
+ throws InterruptedException, ExecutionException {
+ AsyncFunction<String, Integer> function = constantAsyncFunction(Futures.immediateFuture(1));
+ ListenableFuture<Integer> future = Futures.transform(
+ SettableFuture.<String>create(), function);
+ try {
+ future.get(1, TimeUnit.MILLISECONDS);
+ fail();
+ } catch (TimeoutException expected) {
+ }
+ }
+
+ public void testTransform_asyncFunction_error() throws InterruptedException {
+ final Error error = new Error("deliberate");
+ AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(String input) {
+ throw error;
+ }
+ };
+ SettableFuture<String> inputFuture = SettableFuture.create();
+ ListenableFuture<Integer> outputFuture = Futures.transform(inputFuture, function);
+ inputFuture.set("value");
+ try {
+ outputFuture.get();
+ fail("should have thrown error");
+ } catch (ExecutionException e) {
+ assertSame(error, e.getCause());
+ }
+ }
+
+ public void testTransform_asyncFunction_nullInsteadOfFuture() throws Exception {
+ ListenableFuture<?> inputFuture = immediateFuture("a");
+ ListenableFuture<?> chainedFuture =
+ Futures.transform(inputFuture, constantAsyncFunction(null));
+ try {
+ chainedFuture.get();
+ fail();
+ } catch (ExecutionException expected) {
+ NullPointerException cause = (NullPointerException) expected.getCause();
+ assertThat(cause).hasMessage("AsyncFunction.apply returned null instead of a Future. "
+ + "Did you mean to return immediateFuture(null)?");
+ }
+ }
+
+ @GwtIncompatible("threads")
+
+ public void testTransform_asyncFunction_cancelledWhileApplyingFunction()
+ throws InterruptedException, ExecutionException {
+ final CountDownLatch inFunction = new CountDownLatch(1);
+ final CountDownLatch functionDone = new CountDownLatch(1);
+ final SettableFuture<Integer> resultFuture = SettableFuture.create();
+ AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(String input) throws Exception {
+ inFunction.countDown();
+ functionDone.await();
+ return resultFuture;
+ }
+ };
+ SettableFuture<String> inputFuture = SettableFuture.create();
ListenableFuture<Integer> future = Futures.transform(
inputFuture, function, Executors.newSingleThreadExecutor());
inputFuture.set("value");
@@ -730,11 +1432,154 @@ public class FuturesTest extends TestCase {
try {
future.get();
fail();
- } catch (CancellationException expected) {}
+ } catch (CancellationException expected) {
+ }
try {
resultFuture.get();
fail();
- } catch (CancellationException expected) {}
+ } catch (CancellationException expected) {
+ }
+ }
+
+ @GwtIncompatible("threads")
+
+ public void testTransform_asyncFunction_cancelledBeforeApplyingFunction()
+ throws InterruptedException {
+ final AtomicBoolean functionCalled = new AtomicBoolean();
+ AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(String input) throws Exception {
+ functionCalled.set(true);
+ return Futures.immediateFuture(1);
+ }
+ };
+ SettableFuture<String> inputFuture = SettableFuture.create();
+ ExecutorService executor = newSingleThreadExecutor();
+ ListenableFuture<Integer> future = Futures.transform(
+ inputFuture, function, executor);
+
+ // Pause the executor.
+ final CountDownLatch beforeFunction = new CountDownLatch(1);
+ executor.submit(new Runnable() {
+ @Override
+ public void run() {
+ awaitUninterruptibly(beforeFunction);
+ }
+ });
+
+ // Cancel the future after making input available.
+ inputFuture.set("value");
+ future.cancel(false);
+
+ // Unpause the executor.
+ beforeFunction.countDown();
+ executor.awaitTermination(5, TimeUnit.SECONDS);
+
+ assertFalse(functionCalled.get());
+ }
+
+ public void testTransformAsync_genericsWildcard_AsyncFunction() throws Exception {
+ ListenableFuture<?> nullFuture = immediateFuture(null);
+ ListenableFuture<?> chainedFuture =
+ Futures.transformAsync(nullFuture, constantAsyncFunction(nullFuture));
+ assertNull(chainedFuture.get());
+ }
+
+ public void testTransformAsync_genericsHierarchy_AsyncFunction() throws Exception {
+ ListenableFuture<FooChild> future = Futures.immediateFuture(null);
+ final BarChild barChild = new BarChild();
+ AsyncFunction<Foo, BarChild> function =
+ new AsyncFunction<Foo, BarChild>() {
+ @Override
+ public AbstractFuture<BarChild> apply(Foo unused) {
+ AbstractFuture<BarChild> future = new AbstractFuture<BarChild>() {
+ };
+ future.set(barChild);
+ return future;
+ }
+ };
+ Bar bar = Futures.transformAsync(future, function).get();
+ assertSame(barChild, bar);
+ }
+
+ @GwtIncompatible("get() timeout")
+ public void testTransformAsync_asyncFunction_timeout()
+ throws InterruptedException, ExecutionException {
+ AsyncFunction<String, Integer> function = constantAsyncFunction(Futures.immediateFuture(1));
+ ListenableFuture<Integer> future = Futures.transformAsync(
+ SettableFuture.<String>create(), function);
+ try {
+ future.get(1, TimeUnit.MILLISECONDS);
+ fail();
+ } catch (TimeoutException expected) {
+ }
+ }
+
+ public void testTransformAsync_asyncFunction_error() throws InterruptedException {
+ final Error error = new Error("deliberate");
+ AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(String input) {
+ throw error;
+ }
+ };
+ SettableFuture<String> inputFuture = SettableFuture.create();
+ ListenableFuture<Integer> outputFuture = Futures.transformAsync(inputFuture, function);
+ inputFuture.set("value");
+ try {
+ outputFuture.get();
+ fail("should have thrown error");
+ } catch (ExecutionException e) {
+ assertSame(error, e.getCause());
+ }
+ }
+
+ public void testTransformAsync_asyncFunction_nullInsteadOfFuture() throws Exception {
+ ListenableFuture<?> inputFuture = immediateFuture("a");
+ ListenableFuture<?> chainedFuture =
+ Futures.transformAsync(inputFuture, constantAsyncFunction(null));
+ try {
+ chainedFuture.get();
+ fail();
+ } catch (ExecutionException expected) {
+ NullPointerException cause = (NullPointerException) expected.getCause();
+ assertThat(cause).hasMessage("AsyncFunction.apply returned null instead of a Future. "
+ + "Did you mean to return immediateFuture(null)?");
+ }
+ }
+
+ @GwtIncompatible("threads")
+
+ public void testTransformAsync_asyncFunction_cancelledWhileApplyingFunction()
+ throws InterruptedException, ExecutionException {
+ final CountDownLatch inFunction = new CountDownLatch(1);
+ final CountDownLatch functionDone = new CountDownLatch(1);
+ final SettableFuture<Integer> resultFuture = SettableFuture.create();
+ AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
+ @Override
+ public ListenableFuture<Integer> apply(String input) throws Exception {
+ inFunction.countDown();
+ functionDone.await();
+ return resultFuture;
+ }
+ };
+ SettableFuture<String> inputFuture = SettableFuture.create();
+ ListenableFuture<Integer> future = Futures.transformAsync(
+ inputFuture, function, Executors.newSingleThreadExecutor());
+ inputFuture.set("value");
+ inFunction.await();
+ future.cancel(false);
+ functionDone.countDown();
+ try {
+ future.get();
+ fail();
+ } catch (CancellationException expected) {
+ }
+ try {
+ resultFuture.get();
+ fail();
+ } catch (CancellationException expected) {
+ }
}
public void testDereference_genericsWildcard() throws Exception {
@@ -784,16 +1629,17 @@ public class FuturesTest extends TestCase {
}
/**
- * Runnable which can be called a single time, and only after
- * {@link #expectCall} is called.
+ * Runnable which can be called a single time, and only after {@link #expectCall} is called.
*/
// TODO(cpovirk): top-level class?
static class SingleCallListener implements Runnable {
+
private boolean expectCall = false;
private final CountDownLatch calledCountDown =
new CountDownLatch(1);
- @Override public void run() {
+ @Override
+ public void run() {
assertTrue("Listener called before it was expected", expectCall);
assertFalse("Listener called more than once", wasCalled());
calledCountDown.countDown();
@@ -820,7 +1666,7 @@ public class FuturesTest extends TestCase {
SettableFuture<String> future2 = SettableFuture.create();
SettableFuture<String> future3 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.allAsList(future1, future2, future3);
// Attach a listener
@@ -839,9 +1685,10 @@ public class FuturesTest extends TestCase {
assertTrue(listener.wasCalled());
List<String> results = compound.get();
- assertThat(results).has().exactly(DATA1, DATA2, DATA3).inOrder();
+ assertThat(results).containsExactly(DATA1, DATA2, DATA3).inOrder();
}
+ @GwtIncompatible("allAsList")
public void testAllAsList_emptyList() throws Exception {
SingleCallListener listener = new SingleCallListener();
listener.expectCall();
@@ -857,7 +1704,7 @@ public class FuturesTest extends TestCase {
SingleCallListener listener = new SingleCallListener();
listener.expectCall();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound = Futures.allAsList();
+ ListenableFuture<List<String>> compound = Futures.allAsList();
compound.addListener(listener, directExecutor());
assertTrue(compound.isDone());
assertTrue(compound.get().isEmpty());
@@ -869,7 +1716,7 @@ public class FuturesTest extends TestCase {
SettableFuture<String> future1 = SettableFuture.create();
SettableFuture<String> future2 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.allAsList(future1, future2);
compound.addListener(listener, directExecutor());
@@ -888,6 +1735,7 @@ public class FuturesTest extends TestCase {
}
}
+ @GwtIncompatible("allAsList")
public void testAllAsList_singleFailure() throws Exception {
Throwable exception = new Throwable("failed");
ListenableFuture<String> future = Futures.immediateFailedFuture(exception);
@@ -901,6 +1749,7 @@ public class FuturesTest extends TestCase {
}
}
+ @GwtIncompatible("allAsList")
public void testAllAsList_immediateFailure() throws Exception {
Throwable exception = new Throwable("failed");
ListenableFuture<String> future1 = Futures.immediateFailedFuture(exception);
@@ -915,6 +1764,7 @@ public class FuturesTest extends TestCase {
}
}
+ @GwtIncompatible("allAsList")
public void testAllAsList_error() throws Exception {
Error error = new Error("deliberate");
SettableFuture<String> future1 = SettableFuture.create();
@@ -935,7 +1785,7 @@ public class FuturesTest extends TestCase {
SettableFuture<String> future1 = SettableFuture.create();
SettableFuture<String> future2 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.allAsList(future1, future2);
compound.addListener(listener, directExecutor());
@@ -957,7 +1807,7 @@ public class FuturesTest extends TestCase {
SettableFuture<String> future1 = SettableFuture.create();
SettableFuture<String> future2 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.allAsList(future1, future2);
future2.set(DATA2);
@@ -968,11 +1818,46 @@ public class FuturesTest extends TestCase {
assertFalse(future1.wasInterrupted());
}
+ public void testAllAsList_resultCancelledInterrupted_withSecondaryListFuture()
+ throws Exception {
+ SettableFuture<String> future1 = SettableFuture.create();
+ SettableFuture<String> future2 = SettableFuture.create();
+ ListenableFuture<List<String>> compound =
+ Futures.allAsList(future1, future2);
+ // There was a bug where the event listener for the combined future would
+ // result in the sub-futures being cancelled without being interrupted.
+ ListenableFuture<List<String>> otherCompound =
+ Futures.allAsList(future1, future2);
+
+ assertTrue(compound.cancel(true));
+ assertTrue(future1.isCancelled());
+ assertTrue(future1.wasInterrupted());
+ assertTrue(future2.isCancelled());
+ assertTrue(future2.wasInterrupted());
+ assertTrue(otherCompound.isCancelled());
+ }
+
+ public void testAllAsList_resultCancelled_withSecondaryListFuture()
+ throws Exception {
+ SettableFuture<String> future1 = SettableFuture.create();
+ SettableFuture<String> future2 = SettableFuture.create();
+ ListenableFuture<List<String>> compound =
+ Futures.allAsList(future1, future2);
+ // This next call is "unused," but it is an important part of the test. Don't remove it!
+ Futures.allAsList(future1, future2);
+
+ assertTrue(compound.cancel(false));
+ assertTrue(future1.isCancelled());
+ assertFalse(future1.wasInterrupted());
+ assertTrue(future2.isCancelled());
+ assertFalse(future2.wasInterrupted());
+ }
+
public void testAllAsList_resultInterrupted() throws Exception {
SettableFuture<String> future1 = SettableFuture.create();
SettableFuture<String> future2 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.allAsList(future1, future2);
future2.set(DATA2);
@@ -984,11 +1869,10 @@ public class FuturesTest extends TestCase {
}
/**
- * Test the case where the futures are fulfilled prior to
- * constructing the ListFuture. There was a bug where the
- * loop that connects a Listener to each of the futures would die
- * on the last loop-check as done() on ListFuture nulled out the
- * variable being looped over (the list of futures).
+ * Test the case where the futures are fulfilled prior to constructing the ListFuture. There was
+ * a bug where the loop that connects a Listener to each of the futures would die on the last
+ * loop-check as done() on ListFuture nulled out the variable being looped over (the list of
+ * futures).
*/
public void testAllAsList_doneFutures() throws Exception {
// Create input and output
@@ -1002,7 +1886,7 @@ public class FuturesTest extends TestCase {
future3.set(DATA3);
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.allAsList(future1, future2, future3);
// Attach a listener
@@ -1014,7 +1898,7 @@ public class FuturesTest extends TestCase {
assertTrue(listener.wasCalled());
List<String> results = compound.get();
- assertThat(results).has().exactly(DATA1, DATA2, DATA3).inOrder();
+ assertThat(results).containsExactly(DATA1, DATA2, DATA3).inOrder();
}
/**
@@ -1023,45 +1907,166 @@ public class FuturesTest extends TestCase {
@SuppressWarnings("unchecked")
public void testAllAsList_logging_exception() throws Exception {
try {
- Futures.allAsList(immediateFailedFuture(new MyException())).get();
+ Futures.allAsList(immediateFailedFuture(new MyException())).get();
+ fail();
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isInstanceOf(MyException.class);
+ assertEquals(
+ "Nothing should be logged", 0, aggregateFutureLogHandler.getStoredLogRecords().size());
+ }
+ }
+
+ /**
+ * Ensure that errors are always logged.
+ */
+ @SuppressWarnings("unchecked")
+ public void testAllAsList_logging_error() throws Exception {
+ try {
+ Futures.allAsList(immediateFailedFuture(new MyError())).get();
+ fail();
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isInstanceOf(MyError.class);
+ List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+ assertThat(logged).hasSize(1); // errors are always logged
+ assertThat(logged.get(0).getThrown()).isInstanceOf(MyError.class);
+ }
+ }
+
+ /**
+ * All as list will log extra exceptions that have already occurred.
+ */
+ @SuppressWarnings("unchecked")
+ public void testAllAsList_logging_multipleExceptions_alreadyDone() throws Exception {
+ try {
+ Futures.allAsList(immediateFailedFuture(new MyException()),
+ immediateFailedFuture(new MyException())).get();
+ fail();
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isInstanceOf(MyException.class);
+ List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+ assertThat(logged).hasSize(1); // the second failure is logged
+ assertThat(logged.get(0).getThrown()).isInstanceOf(MyException.class);
+ }
+ }
+
+ /**
+ * All as list will log extra exceptions that occur later.
+ */
+ @SuppressWarnings("unchecked")
+ public void testAllAsList_logging_multipleExceptions_doneLater() throws Exception {
+ SettableFuture<Object> future1 = SettableFuture.create();
+ SettableFuture<Object> future2 = SettableFuture.create();
+ SettableFuture<Object> future3 = SettableFuture.create();
+ ListenableFuture<List<Object>> all = Futures.allAsList(future1, future2, future3);
+
+ future1.setException(new MyException());
+ future2.setException(new MyException());
+ future3.setException(new MyException());
+
+ try {
+ all.get();
+ } catch (ExecutionException e) {
+ List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+ assertThat(logged).hasSize(2); // failures after the first are logged
+ assertThat(logged.get(0).getThrown()).isInstanceOf(MyException.class);
+ assertThat(logged.get(1).getThrown()).isInstanceOf(MyException.class);
+ }
+ }
+
+ /**
+ * The same exception happening on multiple futures should not be logged.
+ */
+ @SuppressWarnings("unchecked")
+ public void testAllAsList_logging_same_exception() throws Exception {
+ try {
+ MyException sameInstance = new MyException();
+ Futures.allAsList(immediateFailedFuture(sameInstance),
+ immediateFailedFuture(sameInstance)).get();
+ fail();
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isInstanceOf(MyException.class);
+ assertEquals(
+ "Nothing should be logged", 0, aggregateFutureLogHandler.getStoredLogRecords().size());
+ }
+ }
+
+ public void testAllAsList_logging_seenExceptionUpdateRace() throws Exception {
+ final MyException sameInstance = new MyException();
+ SettableFuture<Object> firstFuture = SettableFuture.create();
+ final SettableFuture<Object> secondFuture = SettableFuture.create();
+ ListenableFuture<List<Object>> bulkFuture = allAsList(firstFuture, secondFuture);
+
+ bulkFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ /*
+ * firstFuture just completed, but AggregateFuture hasn't yet had time to record the
+ * exception in seenExceptions. When we complete secondFuture with the same exception,
+ * we want for AggregateFuture to still detect that it's been previously seen.
+ */
+ secondFuture.setException(sameInstance);
+ }
+ }, directExecutor());
+ firstFuture.setException(sameInstance);
+
+ try {
+ bulkFuture.get();
fail();
- } catch (ExecutionException e) {
- assertTrue(e.getCause() instanceof MyException);
- assertEquals("Nothing should be logged", 0,
- combinedFutureLogHandler.getStoredLogRecords().size());
+ } catch (ExecutionException expected) {
+ assertThat(expected.getCause()).isInstanceOf(MyException.class);
+ assertThat(aggregateFutureLogHandler.getStoredLogRecords()).isEmpty();
}
}
- /**
- * Ensure that errors are always logged.
- */
- @SuppressWarnings("unchecked")
- public void testAllAsList_logging_error() throws Exception {
+ public void testAllAsList_logging_seenExceptionUpdateCancelRace() throws Exception {
+ final MyException subsequentFailure = new MyException();
+ SettableFuture<Object> firstFuture = SettableFuture.create();
+ final SettableFuture<Object> secondFuture = SettableFuture.create();
+ ListenableFuture<List<Object>> bulkFuture = allAsList(firstFuture, secondFuture);
+
+ bulkFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ /*
+ * This is similar to the above test, but this time we're making sure that we recognize that
+ * the output Future is done early not because of an exception but because of a
+ * cancellation.
+ */
+ secondFuture.setException(subsequentFailure);
+ }
+ }, directExecutor());
+ firstFuture.cancel(false);
+
try {
- Futures.allAsList(immediateFailedFuture(new MyError())).get();
+ bulkFuture.get();
fail();
- } catch (ExecutionException e) {
- assertTrue(e.getCause() instanceof MyError);
- List<LogRecord> logged = combinedFutureLogHandler.getStoredLogRecords();
- assertEquals(1, logged.size()); // errors are always logged
- assertTrue(logged.get(0).getThrown() instanceof MyError);
+ } catch (CancellationException expected) {
+ assertThat(getOnlyElement(aggregateFutureLogHandler.getStoredLogRecords()).getThrown())
+ .isSameAs(subsequentFailure);
}
}
/**
- * All as list will log extra exceptions that occur after failure.
+ * Different exceptions happening on multiple futures with the same cause should not be logged.
*/
@SuppressWarnings("unchecked")
- public void testAllAsList_logging_multipleExceptions() throws Exception {
- try {
- Futures.allAsList(immediateFailedFuture(new MyException()),
- immediateFailedFuture(new MyException())).get();
+ public void testAllAsList_logging_same_cause() throws Exception {
+ try {
+ MyException exception1 = new MyException();
+ MyException exception2 = new MyException();
+ MyException exception3 = new MyException();
+
+ MyException sameInstance = new MyException();
+ exception1.initCause(sameInstance);
+ exception2.initCause(sameInstance);
+ exception3.initCause(exception2);
+ Futures.allAsList(immediateFailedFuture(exception1),
+ immediateFailedFuture(exception3)).get();
fail();
} catch (ExecutionException e) {
- assertTrue(e.getCause() instanceof MyException);
- List<LogRecord> logged = combinedFutureLogHandler.getStoredLogRecords();
- assertEquals(1, logged.size()); // the second failure is logged
- assertTrue(logged.get(0).getThrown() instanceof MyException);
+ assertThat(e.getCause()).isInstanceOf(MyException.class);
+ assertEquals(
+ "Nothing should be logged", 0, aggregateFutureLogHandler.getStoredLogRecords().size());
}
}
@@ -1073,13 +2078,15 @@ public class FuturesTest extends TestCase {
* TODO(cpovirk): maybe pass around TestFuture instances instead of
* ListenableFuture instances
*/
+
/**
- * A future in {@link TestFutureBatch} that also has a name for debugging
- * purposes and a {@code finisher}, a task that will complete the future in
- * some fashion when it is called, allowing for testing both before and after
- * the completion of the future.
+ * A future in {@link TestFutureBatch} that also has a name for debugging purposes and a {@code
+ * finisher}, a task that will complete the future in some fashion when it is called, allowing for
+ * testing both before and after the completion of the future.
*/
+ @GwtIncompatible("used only in GwtIncompatible tests")
private static final class TestFuture {
+
final ListenableFuture<String> future;
final String name;
final Runnable finisher;
@@ -1093,20 +2100,21 @@ public class FuturesTest extends TestCase {
}
/**
- * A collection of several futures, covering cancellation, success, and
- * failure (both {@link ExecutionException} and {@link RuntimeException}),
- * both immediate and delayed. We use each possible pair of these futures in
- * {@link FuturesTest#runExtensiveMergerTest}.
+ * A collection of several futures, covering cancellation, success, and failure (both {@link
+ * ExecutionException} and {@link RuntimeException}), both immediate and delayed. We use each
+ * possible pair of these futures in {@link FuturesTest#runExtensiveMergerTest}.
*
- * <p>Each test requires a new {@link TestFutureBatch} because we need new
- * delayed futures each time, as the old delayed futures were completed as
- * part of the old test.
+ * <p>Each test requires a new {@link TestFutureBatch} because we need new delayed futures each
+ * time, as the old delayed futures were completed as part of the old test.
*/
+ @GwtIncompatible("used only in GwtIncompatible tests")
private static final class TestFutureBatch {
+
final ListenableFuture<String> doneSuccess = immediateFuture("a");
final ListenableFuture<String> doneFailed =
immediateFailedFuture(new Exception());
final SettableFuture<String> doneCancelled = SettableFuture.create();
+
{
doneCancelled.cancel(true);
}
@@ -1130,7 +2138,7 @@ public class FuturesTest extends TestCase {
public String get(long timeout, TimeUnit unit) {
throw new RuntimeException();
}
- };
+ };
final SettableFuture<String> delayedSuccess = SettableFuture.create();
final SettableFuture<String> delayedFailed = SettableFuture.create();
@@ -1157,7 +2165,7 @@ public class FuturesTest extends TestCase {
delegateForDelayedRuntimeException.get(timeout, unit);
throw new RuntimeException();
}
- };
+ };
final Runnable doNothing = new Runnable() {
@Override
@@ -1190,8 +2198,7 @@ public class FuturesTest extends TestCase {
};
/**
- * All the futures, together with human-readable names for use by
- * {@link #smartToString}.
+ * All the futures, together with human-readable names for use by {@link #smartToString}.
*/
final ImmutableList<TestFuture> allFutures =
ImmutableList.of(new TestFuture(doneSuccess, "doneSuccess", doNothing),
@@ -1207,26 +2214,25 @@ public class FuturesTest extends TestCase {
finishRuntimeException));
final Function<ListenableFuture<String>, String> nameGetter =
- new Function<ListenableFuture<String>, String>() {
- @Override
- public String apply(ListenableFuture<String> input) {
- for (TestFuture future : allFutures) {
- if (future.future == input) {
- return future.name;
+ new Function<ListenableFuture<String>, String>() {
+ @Override
+ public String apply(ListenableFuture<String> input) {
+ for (TestFuture future : allFutures) {
+ if (future.future == input) {
+ return future.name;
+ }
}
+ throw new IllegalArgumentException(input.toString());
}
- throw new IllegalArgumentException(input.toString());
- }
- };
+ };
static boolean intersect(Set<?> a, Set<?> b) {
return !Sets.intersection(a, b).isEmpty();
}
/**
- * Like {@code inputs.toString()}, but with the nonsense {@code toString}
- * representations replaced with the name of each future from
- * {@link #allFutures}.
+ * Like {@code inputs.toString()}, but with the nonsense {@code toString} representations
+ * replaced with the name of each future from {@link #allFutures}.
*/
String smartToString(ImmutableSet<ListenableFuture<String>> inputs) {
Iterable<String> inputNames = Iterables.transform(inputs, nameGetter);
@@ -1236,7 +2242,7 @@ public class FuturesTest extends TestCase {
void smartAssertTrue(ImmutableSet<ListenableFuture<String>> inputs,
Exception cause, boolean expression) {
if (!expression) {
- failWithCause(cause, smartToString(inputs));
+ throw failureWithCause(cause, smartToString(inputs));
}
}
@@ -1283,11 +2289,12 @@ public class FuturesTest extends TestCase {
}
/**
- * {@link Futures#allAsList(Iterable)} or
- * {@link Futures#successfulAsList(Iterable)}, hidden behind a common
- * interface for testing.
+ * {@link Futures#allAsList(Iterable)} or {@link Futures#successfulAsList(Iterable)}, hidden
+ * behind a common interface for testing.
*/
+ @GwtIncompatible("used only in GwtIncompatible tests")
private interface Merger {
+
ListenableFuture<List<String>> merged(
ListenableFuture<String> a, ListenableFuture<String> b);
@@ -1308,15 +2315,16 @@ public class FuturesTest extends TestCase {
}
/**
- * Very rough equivalent of a timed get, produced by calling the no-arg get
- * method in another thread and waiting a short time for it.
+ * Very rough equivalent of a timed get, produced by calling the no-arg get method in another
+ * thread and waiting a short time for it.
*
- * <p>We need this to test the behavior of no-arg get methods without hanging
- * the main test thread forever in the case of failure.
+ * <p>We need this to test the behavior of no-arg get methods without hanging the main test thread
+ * forever in the case of failure.
*/
- private static <V> V pseudoTimedGet(
+ @GwtIncompatible("threads")
+ static <V> V pseudoTimedGetUninterruptibly(
final Future<V> input, long timeout, TimeUnit unit)
- throws InterruptedException, ExecutionException, TimeoutException {
+ throws ExecutionException, TimeoutException {
ExecutorService executor = newSingleThreadExecutor();
Future<V> waiter = executor.submit(new Callable<V>() {
@Override
@@ -1326,33 +2334,31 @@ public class FuturesTest extends TestCase {
});
try {
- return waiter.get(timeout, unit);
+ return getUninterruptibly(waiter, timeout, unit);
} catch (ExecutionException e) {
propagateIfInstanceOf(e.getCause(), ExecutionException.class);
propagateIfInstanceOf(e.getCause(), CancellationException.class);
- AssertionFailedError error =
- new AssertionFailedError("Unexpected exception");
- error.initCause(e);
- throw error;
+ throw failureWithCause(e, "Unexpected exception");
} finally {
executor.shutdownNow();
- assertTrue(executor.awaitTermination(10, SECONDS));
+ // TODO(cpovirk: assertTrue(awaitTerminationUninterruptibly(executor, 10, SECONDS));
}
}
/**
- * For each possible pair of futures from {@link TestFutureBatch}, for each
- * possible completion order of those futures, test that various get calls
- * (timed before future completion, untimed before future completion, and
- * untimed after future completion) return or throw the proper values.
+ * For each possible pair of futures from {@link TestFutureBatch}, for each possible completion
+ * order of those futures, test that various get calls (timed before future completion, untimed
+ * before future completion, and untimed after future completion) return or throw the proper
+ * values.
*/
+ @GwtIncompatible("used only in GwtIncompatible tests")
private static void runExtensiveMergerTest(Merger merger)
throws InterruptedException {
int inputCount = new TestFutureBatch().allFutures.size();
for (int i = 0; i < inputCount; i++) {
for (int j = 0; j < inputCount; j++) {
- for (boolean iBeforeJ : new boolean[] { true, false }) {
+ for (boolean iBeforeJ : new boolean[]{true, false}) {
TestFutureBatch inputs = new TestFutureBatch();
ListenableFuture<String> iFuture = inputs.allFutures.get(i).future;
ListenableFuture<String> jFuture = inputs.allFutures.get(j).future;
@@ -1376,7 +2382,7 @@ public class FuturesTest extends TestCase {
// Same tests with pseudoTimedGet.
try {
- List<String> result = conditionalPseudoTimedGet(
+ List<String> result = conditionalPseudoTimedGetUninterruptibly(
inputs, iFuture, jFuture, future, 20, MILLISECONDS);
assertTrue("Got " + result,
Arrays.asList("a", null).containsAll(result));
@@ -1412,58 +2418,59 @@ public class FuturesTest extends TestCase {
}
/**
- * Call the non-timed {@link Future#get()} in a way that allows us to abort if
- * it's expected to hang forever. More precisely, if it's expected to return,
- * we simply call it[*], but if it's expected to hang (because one of the
- * input futures that we know makes it up isn't done yet), then we call it in
- * a separate thread (using pseudoTimedGet). The result is that we wait as
- * long as necessary when the method is expected to return (at the cost of
- * hanging forever if there is a bug in the class under test) but that we time
- * out fairly promptly when the method is expected to hang (possibly too
- * quickly, but too-quick failures should be very unlikely, given that we used
- * to bail after 20ms during the expected-successful tests, and there we saw a
- * failure rate of ~1/5000, meaning that the other thread's get() call nearly
- * always completes within 20ms if it's going to complete at all).
+ * Call the non-timed {@link Future#get()} in a way that allows us to abort if it's expected to
+ * hang forever. More precisely, if it's expected to return, we simply call it[*], but if it's
+ * expected to hang (because one of the input futures that we know makes it up isn't done yet),
+ * then we call it in a separate thread (using pseudoTimedGet). The result is that we wait as long
+ * as necessary when the method is expected to return (at the cost of hanging forever if there is
+ * a bug in the class under test) but that we time out fairly promptly when the method is expected
+ * to hang (possibly too quickly, but too-quick failures should be very unlikely, given that we
+ * used to bail after 20ms during the expected-successful tests, and there we saw a failure rate
+ * of ~1/5000, meaning that the other thread's get() call nearly always completes within 20ms if
+ * it's going to complete at all).
*
- * [*] To avoid hangs, I've disabled the in-thread calls. This makes the test
- * take (very roughly) 2.5s longer. (2.5s is also the maximum length of time
- * we will wait for a timed get that is expected to succeed; the fact that the
- * numbers match is only a coincidence.) See the comment below for how to
- * restore the fast but hang-y version.
+ * [*] To avoid hangs, I've disabled the in-thread calls. This makes the test take (very roughly)
+ * 2.5s longer. (2.5s is also the maximum length of time we will wait for a timed get that is
+ * expected to succeed; the fact that the numbers match is only a coincidence.) See the comment
+ * below for how to restore the fast but hang-y version.
*/
- private static List<String> conditionalPseudoTimedGet(
+ @GwtIncompatible("used only in GwtIncompatible tests")
+ private static List<String> conditionalPseudoTimedGetUninterruptibly(
TestFutureBatch inputs,
ListenableFuture<String> iFuture,
ListenableFuture<String> jFuture,
ListenableFuture<List<String>> future,
int timeout,
TimeUnit unit)
- throws InterruptedException, ExecutionException, TimeoutException {
+ throws ExecutionException, TimeoutException {
/*
* For faster tests (that may hang indefinitely if the class under test has
* a bug!), switch the second branch to call untimed future.get() instead of
* pseudoTimedGet.
*/
return (inputs.hasDelayed(iFuture, jFuture))
- ? pseudoTimedGet(future, timeout, unit)
- : pseudoTimedGet(future, 2500, MILLISECONDS);
+ ? pseudoTimedGetUninterruptibly(future, timeout, unit)
+ : pseudoTimedGetUninterruptibly(future, 2500, MILLISECONDS);
}
+ @GwtIncompatible("allAsList")
public void testAllAsList_extensive() throws InterruptedException {
runExtensiveMergerTest(Merger.allMerger);
}
+ @GwtIncompatible("successfulAsList")
public void testSuccessfulAsList_extensive() throws InterruptedException {
runExtensiveMergerTest(Merger.successMerger);
}
+ @GwtIncompatible("successfulAsList")
public void testSuccessfulAsList() throws Exception {
// Create input and output
SettableFuture<String> future1 = SettableFuture.create();
SettableFuture<String> future2 = SettableFuture.create();
SettableFuture<String> future3 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.successfulAsList(future1, future2, future3);
// Attach a listener
@@ -1482,9 +2489,10 @@ public class FuturesTest extends TestCase {
assertTrue(listener.wasCalled());
List<String> results = compound.get();
- assertThat(results).has().exactly(DATA1, DATA2, DATA3).inOrder();
+ assertThat(results).containsExactly(DATA1, DATA2, DATA3).inOrder();
}
+ @GwtIncompatible("successfulAsList")
public void testSuccessfulAsList_emptyList() throws Exception {
SingleCallListener listener = new SingleCallListener();
listener.expectCall();
@@ -1496,23 +2504,25 @@ public class FuturesTest extends TestCase {
assertTrue(listener.wasCalled());
}
+ @GwtIncompatible("successfulAsList")
public void testSuccessfulAsList_emptyArray() throws Exception {
SingleCallListener listener = new SingleCallListener();
listener.expectCall();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound = Futures.successfulAsList();
+ ListenableFuture<List<String>> compound = Futures.successfulAsList();
compound.addListener(listener, directExecutor());
assertTrue(compound.isDone());
assertTrue(compound.get().isEmpty());
assertTrue(listener.wasCalled());
}
+ @GwtIncompatible("successfulAsList")
public void testSuccessfulAsList_partialFailure() throws Exception {
SingleCallListener listener = new SingleCallListener();
SettableFuture<String> future1 = SettableFuture.create();
SettableFuture<String> future2 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.successfulAsList(future1, future2);
compound.addListener(listener, directExecutor());
@@ -1525,15 +2535,16 @@ public class FuturesTest extends TestCase {
assertTrue(listener.wasCalled());
List<String> results = compound.get();
- assertThat(results).has().exactly(null, DATA2).inOrder();
+ assertThat(results).containsExactly(null, DATA2).inOrder();
}
+ @GwtIncompatible("successfulAsList")
public void testSuccessfulAsList_totalFailure() throws Exception {
SingleCallListener listener = new SingleCallListener();
SettableFuture<String> future1 = SettableFuture.create();
SettableFuture<String> future2 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.successfulAsList(future1, future2);
compound.addListener(listener, directExecutor());
@@ -1546,15 +2557,16 @@ public class FuturesTest extends TestCase {
assertTrue(listener.wasCalled());
List<String> results = compound.get();
- assertThat(results).has().exactly(null, null).inOrder();
+ assertThat(results).containsExactly(null, null).inOrder();
}
+ @GwtIncompatible("successfulAsList")
public void testSuccessfulAsList_cancelled() throws Exception {
SingleCallListener listener = new SingleCallListener();
SettableFuture<String> future1 = SettableFuture.create();
SettableFuture<String> future2 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.successfulAsList(future1, future2);
compound.addListener(listener, directExecutor());
@@ -1567,14 +2579,15 @@ public class FuturesTest extends TestCase {
assertTrue(listener.wasCalled());
List<String> results = compound.get();
- assertThat(results).has().exactly(null, DATA2).inOrder();
+ assertThat(results).containsExactly(null, DATA2).inOrder();
}
+ @GwtIncompatible("successfulAsList")
public void testSuccessfulAsList_resultCancelled() throws Exception {
SettableFuture<String> future1 = SettableFuture.create();
SettableFuture<String> future2 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.successfulAsList(future1, future2);
future2.set(DATA2);
@@ -1585,6 +2598,7 @@ public class FuturesTest extends TestCase {
assertFalse(future1.wasInterrupted());
}
+ @GwtIncompatible("successfulAsList")
public void testSuccessfulAsList_resultCancelledRacingInputDone()
throws Exception {
/*
@@ -1592,17 +2606,21 @@ public class FuturesTest extends TestCase {
* ExecutionList and logged rather than allowed to propagate. We need to
* turn that back into a failure.
*/
- Handler throwingHandler = new Handler() {
- @Override public void publish(@Nullable LogRecord record) {
- AssertionFailedError error = new AssertionFailedError();
- error.initCause(record.getThrown());
- throw error;
- }
+ Handler throwingHandler =
+ new Handler() {
+ @Override
+ public void publish(LogRecord record) {
+ AssertionFailedError error = new AssertionFailedError();
+ error.initCause(record.getThrown());
+ throw error;
+ }
- @Override public void flush() {}
+ @Override
+ public void flush() {}
- @Override public void close() {}
- };
+ @Override
+ public void close() {}
+ };
ExecutionList.log.addHandler(throwingHandler);
try {
@@ -1612,6 +2630,7 @@ public class FuturesTest extends TestCase {
}
}
+ @GwtIncompatible("successfulAsList")
private static void doTestSuccessfulAsList_resultCancelledRacingInputDone()
throws Exception {
// Simple (combined.cancel -> input.cancel -> setOneValue):
@@ -1626,11 +2645,12 @@ public class FuturesTest extends TestCase {
final SettableFuture<String> future1 = SettableFuture.create();
final SettableFuture<String> future2 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.successfulAsList(future1, future2);
future1.addListener(new Runnable() {
- @Override public void run() {
+ @Override
+ public void run() {
assertTrue(future1.isCancelled());
/*
* This test relies on behavior that's unspecified but currently
@@ -1656,11 +2676,12 @@ public class FuturesTest extends TestCase {
}
}
+ @GwtIncompatible("successfulAsList")
public void testSuccessfulAsList_resultInterrupted() throws Exception {
SettableFuture<String> future1 = SettableFuture.create();
SettableFuture<String> future2 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.successfulAsList(future1, future2);
future2.set(DATA2);
@@ -1671,13 +2692,14 @@ public class FuturesTest extends TestCase {
assertTrue(future1.wasInterrupted());
}
+ @GwtIncompatible("successfulAsList")
public void testSuccessfulAsList_mixed() throws Exception {
SingleCallListener listener = new SingleCallListener();
SettableFuture<String> future1 = SettableFuture.create();
SettableFuture<String> future2 = SettableFuture.create();
SettableFuture<String> future3 = SettableFuture.create();
@SuppressWarnings("unchecked") // array is never modified
- ListenableFuture<List<String>> compound =
+ ListenableFuture<List<String>> compound =
Futures.successfulAsList(future1, future2, future3);
compound.addListener(listener, directExecutor());
@@ -1693,17 +2715,19 @@ public class FuturesTest extends TestCase {
assertTrue(listener.wasCalled());
List<String> results = compound.get();
- assertThat(results).has().exactly(null, null, DATA3).inOrder();
+ assertThat(results).containsExactly(null, null, DATA3).inOrder();
}
- /** Non-Error exceptions are never logged. */
+ /**
+ * Non-Error exceptions are never logged.
+ */
@SuppressWarnings("unchecked")
public void testSuccessfulAsList_logging_exception() throws Exception {
assertEquals(Lists.newArrayList((Object) null),
Futures.successfulAsList(
immediateFailedFuture(new MyException())).get());
assertEquals("Nothing should be logged", 0,
- combinedFutureLogHandler.getStoredLogRecords().size());
+ aggregateFutureLogHandler.getStoredLogRecords().size());
// Not even if there are a bunch of failures.
assertEquals(Lists.newArrayList(null, null, null),
@@ -1712,7 +2736,7 @@ public class FuturesTest extends TestCase {
immediateFailedFuture(new MyException()),
immediateFailedFuture(new MyException())).get());
assertEquals("Nothing should be logged", 0,
- combinedFutureLogHandler.getStoredLogRecords().size());
+ aggregateFutureLogHandler.getStoredLogRecords().size());
}
/**
@@ -1723,11 +2747,12 @@ public class FuturesTest extends TestCase {
assertEquals(Lists.newArrayList((Object) null),
Futures.successfulAsList(
immediateFailedFuture(new MyError())).get());
- List<LogRecord> logged = combinedFutureLogHandler.getStoredLogRecords();
- assertEquals(1, logged.size()); // errors are always logged
- assertTrue(logged.get(0).getThrown() instanceof MyError);
+ List<LogRecord> logged = aggregateFutureLogHandler.getStoredLogRecords();
+ assertThat(logged).hasSize(1); // errors are always logged
+ assertThat(logged.get(0).getThrown()).isInstanceOf(MyError.class);
}
+ @GwtIncompatible("nonCancellationPropagating")
public void testNonCancellationPropagating_successful() throws Exception {
SettableFuture<Foo> input = SettableFuture.create();
ListenableFuture<Foo> wrapper = Futures.nonCancellationPropagating(input);
@@ -1739,6 +2764,7 @@ public class FuturesTest extends TestCase {
assertSame(foo, wrapper.get());
}
+ @GwtIncompatible("nonCancellationPropagating")
public void testNonCancellationPropagating_failure() throws Exception {
SettableFuture<Foo> input = SettableFuture.create();
ListenableFuture<Foo> wrapper = Futures.nonCancellationPropagating(input);
@@ -1755,6 +2781,7 @@ public class FuturesTest extends TestCase {
}
}
+ @GwtIncompatible("nonCancellationPropagating")
public void testNonCancellationPropagating_delegateCancelled() throws Exception {
SettableFuture<Foo> input = SettableFuture.create();
ListenableFuture<Foo> wrapper = Futures.nonCancellationPropagating(input);
@@ -1764,6 +2791,7 @@ public class FuturesTest extends TestCase {
assertTrue(wrapper.isCancelled());
}
+ @GwtIncompatible("nonCancellationPropagating")
public void testNonCancellationPropagating_doesNotPropagate() throws Exception {
SettableFuture<Foo> input = SettableFuture.create();
ListenableFuture<Foo> wrapper = Futures.nonCancellationPropagating(input);
@@ -1775,591 +2803,244 @@ public class FuturesTest extends TestCase {
assertFalse(input.isDone());
}
+ @GwtIncompatible("used only in GwtIncompatible tests")
private static class TestException extends Exception {
- TestException(@Nullable Throwable cause) {
- super(cause);
- }
- }
-
- private static final Function<Exception, TestException> mapper =
- new Function<Exception, TestException>() {
- @Override public TestException apply(Exception from) {
- if (from instanceof ExecutionException) {
- return new TestException(from.getCause());
- } else {
- assertTrue("got " + from.getClass(),
- from instanceof InterruptedException
- || from instanceof CancellationException);
- return new TestException(from);
- }
- }
- };
-
- public void testMakeChecked_mapsExecutionExceptions() throws Exception {
- SettableFuture<String> future = SettableFuture.create();
-
- CheckedFuture<String, TestException> checked = Futures.makeChecked(
- future, mapper);
-
- future.setException(new IOException("checked"));
-
- assertTrue(checked.isDone());
- assertFalse(checked.isCancelled());
-
- try {
- checked.get();
- fail();
- } catch (ExecutionException e) {
- assertTrue(e.getCause() instanceof IOException);
- }
-
- try {
- checked.get(5, TimeUnit.SECONDS);
- fail();
- } catch (ExecutionException e) {
- assertTrue(e.getCause() instanceof IOException);
- }
-
- try {
- checked.checkedGet();
- fail();
- } catch (TestException e) {
- assertTrue(e.getCause() instanceof IOException);
- }
-
- try {
- checked.checkedGet(5, TimeUnit.SECONDS);
- fail();
- } catch (TestException e) {
- assertTrue(e.getCause() instanceof IOException);
- }
- }
-
- public void testMakeChecked_mapsInterruption() throws Exception {
- SettableFuture<String> future = SettableFuture.create();
-
- CheckedFuture<String, TestException> checked = Futures.makeChecked(
- future, mapper);
-
- Thread.currentThread().interrupt();
-
- try {
- checked.get();
- fail();
- } catch (InterruptedException e) {
- // Expected.
- }
-
- Thread.currentThread().interrupt();
-
- try {
- checked.get(5, TimeUnit.SECONDS);
- fail();
- } catch (InterruptedException e) {
- // Expected.
- }
-
- Thread.currentThread().interrupt();
-
- try {
- checked.checkedGet();
- fail();
- } catch (TestException e) {
- assertTrue(e.getCause() instanceof InterruptedException);
- }
-
- Thread.currentThread().interrupt();
-
- try {
- checked.checkedGet(5, TimeUnit.SECONDS);
- fail();
- } catch (TestException e) {
- assertTrue(e.getCause() instanceof InterruptedException);
- }
- }
-
- public void testMakeChecked_mapsCancellation() throws Exception {
- SettableFuture<String> future = SettableFuture.create();
-
- CheckedFuture<String, TestException> checked = Futures.makeChecked(
- future, mapper);
-
- assertTrue(future.cancel(true)); // argument is ignored
-
- try {
- checked.get();
- fail();
- } catch (CancellationException expected) {}
-
- try {
- checked.get(5, TimeUnit.SECONDS);
- fail();
- } catch (CancellationException expected) {}
-
- try {
- checked.checkedGet();
- fail();
- } catch (TestException expected) {
- assertTrue(expected.getCause() instanceof CancellationException);
- }
-
- try {
- checked.checkedGet(5, TimeUnit.SECONDS);
- fail();
- } catch (TestException expected) {
- assertTrue(expected.getCause() instanceof CancellationException);
- }
- }
-
- public void testMakeChecked_propagatesFailedMappers() throws Exception {
- SettableFuture<String> future = SettableFuture.create();
-
- CheckedFuture<String, TestException> checked = Futures.makeChecked(
- future, new Function<Exception, TestException>() {
- @Override public TestException apply(Exception from) {
- throw new NullPointerException();
- }
- });
-
- future.setException(new Exception("failed"));
-
- try {
- checked.checkedGet();
- fail();
- } catch (NullPointerException expected) {}
-
- try {
- checked.checkedGet(5, TimeUnit.SECONDS);
- fail();
- } catch (NullPointerException expected) {}
- }
-
- public void testMakeChecked_listenersRunOnceCompleted() throws Exception {
- SettableFuture<String> future = SettableFuture.create();
-
- CheckedFuture<String, TestException> checked = Futures.makeChecked(
- future, new Function<Exception, TestException>() {
- @Override public TestException apply(Exception from) {
- throw new NullPointerException();
- }
- });
-
- ListenableFutureTester tester = new ListenableFutureTester(checked);
- tester.setUp();
- future.set(DATA1);
- tester.testCompletedFuture(DATA1);
- tester.tearDown();
- }
-
- public void testMakeChecked_listenersRunOnCancel() throws Exception {
- SettableFuture<String> future = SettableFuture.create();
-
- CheckedFuture<String, TestException> checked = Futures.makeChecked(
- future, new Function<Exception, TestException>() {
- @Override public TestException apply(Exception from) {
- throw new NullPointerException();
- }
- });
-
- ListenableFutureTester tester = new ListenableFutureTester(checked);
- tester.setUp();
- future.cancel(true); // argument is ignored
- tester.testCancelledFuture();
- tester.tearDown();
- }
-
- public void testMakeChecked_listenersRunOnFailure() throws Exception {
- SettableFuture<String> future = SettableFuture.create();
-
- CheckedFuture<String, TestException> checked = Futures.makeChecked(
- future, new Function<Exception, TestException>() {
- @Override public TestException apply(Exception from) {
- throw new NullPointerException();
- }
- });
-
- ListenableFutureTester tester = new ListenableFutureTester(checked);
- tester.setUp();
- future.setException(new Exception("failed"));
- tester.testFailedFuture("failed");
- tester.tearDown();
- }
-
- private interface MapperFunction extends Function<Throwable, Exception> {}
-
- private static final class OtherThrowable extends Throwable {}
-
- private static final Exception CHECKED_EXCEPTION = new Exception("mymessage");
- private static final Future<String> FAILED_FUTURE_CHECKED_EXCEPTION =
- immediateFailedFuture(CHECKED_EXCEPTION);
- private static final RuntimeException UNCHECKED_EXCEPTION =
- new RuntimeException("mymessage");
- private static final Future<String> FAILED_FUTURE_UNCHECKED_EXCEPTION =
- immediateFailedFuture(UNCHECKED_EXCEPTION);
- private static final RuntimeException RUNTIME_EXCEPTION =
- new RuntimeException();
- private static final OtherThrowable OTHER_THROWABLE = new OtherThrowable();
- private static final Future<String> FAILED_FUTURE_OTHER_THROWABLE =
- immediateFailedFuture(OTHER_THROWABLE);
- private static final Error ERROR = new Error("mymessage");
- private static final Future<String> FAILED_FUTURE_ERROR =
- immediateFailedFuture(ERROR);
- private static final Future<String> RUNTIME_EXCEPTION_FUTURE =
- new SimpleForwardingFuture<String>(FAILED_FUTURE_CHECKED_EXCEPTION) {
- @Override public String get() {
- throw RUNTIME_EXCEPTION;
- }
-
- @Override public String get(long timeout, TimeUnit unit) {
- throw RUNTIME_EXCEPTION;
- }
- };
- // Boring untimed-get tests:
-
- public void testGetUntimed_success()
- throws TwoArgConstructorException {
- assertEquals("foo",
- get(immediateFuture("foo"), TwoArgConstructorException.class));
- }
-
- public void testGetUntimed_interrupted() {
- SettableFuture<String> future = SettableFuture.create();
- Thread.currentThread().interrupt();
- try {
- get(future, TwoArgConstructorException.class);
- fail();
- } catch (TwoArgConstructorException expected) {
- assertTrue(expected.getCause() instanceof InterruptedException);
- assertTrue(Thread.currentThread().isInterrupted());
- } finally {
- Thread.interrupted();
+ TestException(@Nullable Throwable cause) {
+ super(cause);
}
}
- public void testGetUntimed_cancelled()
- throws TwoArgConstructorException {
+ @GwtIncompatible("used only in GwtIncompatible tests")
+ private static final Function<Exception, TestException> mapper =
+ new Function<Exception, TestException>() {
+ @Override
+ public TestException apply(Exception from) {
+ if (from instanceof ExecutionException) {
+ return new TestException(from.getCause());
+ } else {
+ assertTrue("got " + from.getClass(),
+ from instanceof InterruptedException
+ || from instanceof CancellationException);
+ return new TestException(from);
+ }
+ }
+ };
+
+ @GwtIncompatible("makeChecked")
+ public void testMakeChecked_mapsExecutionExceptions() throws Exception {
SettableFuture<String> future = SettableFuture.create();
- future.cancel(true);
- try {
- get(future, TwoArgConstructorException.class);
- fail();
- } catch (CancellationException expected) {
- }
- }
- public void testGetUntimed_ExecutionExceptionChecked() {
- try {
- get(FAILED_FUTURE_CHECKED_EXCEPTION, TwoArgConstructorException.class);
- fail();
- } catch (TwoArgConstructorException expected) {
- assertEquals(CHECKED_EXCEPTION, expected.getCause());
- }
- }
+ CheckedFuture<String, TestException> checked = Futures.makeChecked(
+ future, mapper);
- public void testGetUntimed_ExecutionExceptionUnchecked()
- throws TwoArgConstructorException {
- try {
- get(FAILED_FUTURE_UNCHECKED_EXCEPTION, TwoArgConstructorException.class);
- fail();
- } catch (UncheckedExecutionException expected) {
- assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
- }
- }
+ future.setException(new IOException("checked"));
- public void testGetUntimed_ExecutionExceptionError()
- throws TwoArgConstructorException {
- try {
- get(FAILED_FUTURE_ERROR, TwoArgConstructorException.class);
- fail();
- } catch (ExecutionError expected) {
- assertEquals(ERROR, expected.getCause());
- }
- }
+ assertTrue(checked.isDone());
+ assertFalse(checked.isCancelled());
- public void testGetUntimed_ExecutionExceptionOtherThrowable() {
try {
- get(FAILED_FUTURE_OTHER_THROWABLE, TwoArgConstructorException.class);
+ checked.get();
fail();
- } catch (TwoArgConstructorException expected) {
- assertEquals(OTHER_THROWABLE, expected.getCause());
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isInstanceOf(IOException.class);
}
- }
- public void testGetUntimed_RuntimeException()
- throws TwoArgConstructorException {
try {
- get(RUNTIME_EXCEPTION_FUTURE, TwoArgConstructorException.class);
+ checked.get(5, TimeUnit.SECONDS);
fail();
- } catch (RuntimeException expected) {
- assertEquals(RUNTIME_EXCEPTION, expected);
+ } catch (ExecutionException e) {
+ assertThat(e.getCause()).isInstanceOf(IOException.class);
}
- }
- public void testGetUntimed_badExceptionConstructor_wrapsOriginalChecked() throws Exception {
try {
- get(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithBadConstructor.class);
+ checked.checkedGet();
fail();
- } catch (IllegalArgumentException expected) {
- assertSame(CHECKED_EXCEPTION, expected.getCause());
+ } catch (TestException e) {
+ assertThat(e.getCause()).isInstanceOf(IOException.class);
}
- }
- public void testGetUntimed_withGoodAndBadExceptionConstructor() throws Exception {
try {
- get(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithGoodAndBadConstructor.class);
+ checked.checkedGet(5, TimeUnit.SECONDS);
fail();
- } catch (ExceptionWithGoodAndBadConstructor expected) {
- assertSame(CHECKED_EXCEPTION, expected.getCause());
+ } catch (TestException e) {
+ assertThat(e.getCause()).isInstanceOf(IOException.class);
}
}
- // Boring timed-get tests:
+ @GwtIncompatible("makeChecked")
+ public void testMakeChecked_mapsInterruption() throws Exception {
+ SettableFuture<String> future = SettableFuture.create();
- public void testGetTimed_success()
- throws TwoArgConstructorException {
- assertEquals("foo", get(
- immediateFuture("foo"), 0, SECONDS, TwoArgConstructorException.class));
- }
+ CheckedFuture<String, TestException> checked = Futures.makeChecked(
+ future, mapper);
- public void testGetTimed_interrupted() {
- SettableFuture<String> future = SettableFuture.create();
Thread.currentThread().interrupt();
- try {
- get(future, 0, SECONDS, TwoArgConstructorException.class);
- fail();
- } catch (TwoArgConstructorException expected) {
- assertTrue(expected.getCause() instanceof InterruptedException);
- assertTrue(Thread.currentThread().isInterrupted());
- } finally {
- Thread.interrupted();
- }
- }
- public void testGetTimed_cancelled()
- throws TwoArgConstructorException {
- SettableFuture<String> future = SettableFuture.create();
- future.cancel(true);
try {
- get(future, 0, SECONDS, TwoArgConstructorException.class);
+ checked.get();
fail();
- } catch (CancellationException expected) {
+ } catch (InterruptedException e) {
+ // Expected.
}
- }
- public void testGetTimed_ExecutionExceptionChecked() {
- try {
- get(FAILED_FUTURE_CHECKED_EXCEPTION, 0, SECONDS,
- TwoArgConstructorException.class);
- fail();
- } catch (TwoArgConstructorException expected) {
- assertEquals(CHECKED_EXCEPTION, expected.getCause());
- }
- }
+ Thread.currentThread().interrupt();
- public void testGetTimed_ExecutionExceptionUnchecked()
- throws TwoArgConstructorException {
try {
- get(FAILED_FUTURE_UNCHECKED_EXCEPTION, 0, SECONDS,
- TwoArgConstructorException.class);
+ checked.get(5, TimeUnit.SECONDS);
fail();
- } catch (UncheckedExecutionException expected) {
- assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
+ } catch (InterruptedException e) {
+ // Expected.
}
- }
- public void testGetTimed_ExecutionExceptionError()
- throws TwoArgConstructorException {
+ Thread.currentThread().interrupt();
+
try {
- get(FAILED_FUTURE_ERROR, 0, SECONDS, TwoArgConstructorException.class);
+ checked.checkedGet();
fail();
- } catch (ExecutionError expected) {
- assertEquals(ERROR, expected.getCause());
+ } catch (TestException e) {
+ assertThat(e.getCause()).isInstanceOf(InterruptedException.class);
}
- }
- public void testGetTimed_ExecutionExceptionOtherThrowable() {
+ Thread.currentThread().interrupt();
+
try {
- get(FAILED_FUTURE_OTHER_THROWABLE, 0, SECONDS,
- TwoArgConstructorException.class);
+ checked.checkedGet(5, TimeUnit.SECONDS);
fail();
- } catch (TwoArgConstructorException expected) {
- assertEquals(OTHER_THROWABLE, expected.getCause());
+ } catch (TestException e) {
+ assertThat(e.getCause()).isInstanceOf(InterruptedException.class);
}
}
- public void testGetTimed_RuntimeException()
- throws TwoArgConstructorException {
+ @GwtIncompatible("makeChecked")
+ public void testMakeChecked_mapsCancellation() throws Exception {
+ SettableFuture<String> future = SettableFuture.create();
+
+ CheckedFuture<String, TestException> checked = Futures.makeChecked(
+ future, mapper);
+
+ assertTrue(future.cancel(true)); // argument is ignored
+
try {
- get(RUNTIME_EXCEPTION_FUTURE, 0, SECONDS,
- TwoArgConstructorException.class);
+ checked.get();
fail();
- } catch (RuntimeException expected) {
- assertEquals(RUNTIME_EXCEPTION, expected);
+ } catch (CancellationException expected) {
}
- }
- public void testGetTimed_TimeoutException() {
- SettableFuture<String> future = SettableFuture.create();
try {
- get(future, 0, SECONDS, TwoArgConstructorException.class);
+ checked.get(5, TimeUnit.SECONDS);
fail();
- } catch (TwoArgConstructorException expected) {
- assertTrue(expected.getCause() instanceof TimeoutException);
+ } catch (CancellationException expected) {
}
- }
- public void testGetTimed_badExceptionConstructor_wrapsOriginalChecked() throws Exception {
try {
- get(FAILED_FUTURE_CHECKED_EXCEPTION, 1, TimeUnit.SECONDS, ExceptionWithBadConstructor.class);
+ checked.checkedGet();
fail();
- } catch (IllegalArgumentException expected) {
- assertSame(CHECKED_EXCEPTION, expected.getCause());
+ } catch (TestException expected) {
+ assertThat(expected.getCause()).isInstanceOf(CancellationException.class);
}
- }
- public void testGetTimed_withGoodAndBadExceptionConstructor() throws Exception {
try {
- get(FAILED_FUTURE_CHECKED_EXCEPTION, 1, TimeUnit.SECONDS,
- ExceptionWithGoodAndBadConstructor.class);
+ checked.checkedGet(5, TimeUnit.SECONDS);
fail();
- } catch (ExceptionWithGoodAndBadConstructor expected) {
- assertSame(CHECKED_EXCEPTION, expected.getCause());
+ } catch (TestException expected) {
+ assertThat(expected.getCause()).isInstanceOf(CancellationException.class);
}
}
- // Boring getUnchecked tests:
+ @GwtIncompatible("makeChecked")
+ public void testMakeChecked_propagatesFailedMappers() throws Exception {
+ SettableFuture<String> future = SettableFuture.create();
- public void testGetUnchecked_success() {
- assertEquals("foo", getUnchecked(immediateFuture("foo")));
- }
+ CheckedFuture<String, TestException> checked = Futures.makeChecked(
+ future, new Function<Exception, TestException>() {
+ @Override
+ public TestException apply(Exception from) {
+ throw new NullPointerException();
+ }
+ });
- public void testGetUnchecked_interrupted() {
- Thread.currentThread().interrupt();
- try {
- assertEquals("foo", getUnchecked(immediateFuture("foo")));
- assertTrue(Thread.currentThread().isInterrupted());
- } finally {
- Thread.interrupted();
- }
- }
+ future.setException(new Exception("failed"));
- public void testGetUnchecked_cancelled() {
- SettableFuture<String> future = SettableFuture.create();
- future.cancel(true);
try {
- getUnchecked(future);
+ checked.checkedGet();
fail();
- } catch (CancellationException expected) {
+ } catch (NullPointerException expected) {
}
- }
- public void testGetUnchecked_ExecutionExceptionChecked() {
try {
- getUnchecked(FAILED_FUTURE_CHECKED_EXCEPTION);
+ checked.checkedGet(5, TimeUnit.SECONDS);
fail();
- } catch (UncheckedExecutionException expected) {
- assertEquals(CHECKED_EXCEPTION, expected.getCause());
+ } catch (NullPointerException expected) {
}
}
- public void testGetUnchecked_ExecutionExceptionUnchecked() {
- try {
- getUnchecked(FAILED_FUTURE_UNCHECKED_EXCEPTION);
- fail();
- } catch (UncheckedExecutionException expected) {
- assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
- }
- }
+ @GwtIncompatible("makeChecked")
- public void testGetUnchecked_ExecutionExceptionError() {
- try {
- getUnchecked(FAILED_FUTURE_ERROR);
- fail();
- } catch (ExecutionError expected) {
- assertEquals(ERROR, expected.getCause());
- }
- }
+ public void testMakeChecked_listenersRunOnceCompleted() throws Exception {
+ SettableFuture<String> future = SettableFuture.create();
- public void testGetUnchecked_ExecutionExceptionOtherThrowable() {
- try {
- getUnchecked(FAILED_FUTURE_OTHER_THROWABLE);
- fail();
- } catch (UncheckedExecutionException expected) {
- assertEquals(OTHER_THROWABLE, expected.getCause());
- }
- }
+ CheckedFuture<String, TestException> checked = Futures.makeChecked(
+ future, new Function<Exception, TestException>() {
+ @Override
+ public TestException apply(Exception from) {
+ throw new NullPointerException();
+ }
+ });
- public void testGetUnchecked_RuntimeException() {
- try {
- getUnchecked(RUNTIME_EXCEPTION_FUTURE);
- fail();
- } catch (RuntimeException expected) {
- assertEquals(RUNTIME_EXCEPTION, expected);
- }
+ ListenableFutureTester tester = new ListenableFutureTester(checked);
+ tester.setUp();
+ future.set(DATA1);
+ tester.testCompletedFuture(DATA1);
+ tester.tearDown();
}
- // Edge case tests of the exception-construction code through untimed get():
+ @GwtIncompatible("makeChecked")
- public void testGetUntimed_exceptionClassIsRuntimeException() {
- try {
- get(FAILED_FUTURE_CHECKED_EXCEPTION,
- TwoArgConstructorRuntimeException.class);
- fail();
- } catch (IllegalArgumentException expected) {
- }
- }
+ public void testMakeChecked_listenersRunOnCancel() throws Exception {
+ SettableFuture<String> future = SettableFuture.create();
- public void testGetUntimed_exceptionClassSomePublicConstructors() {
- try {
- get(FAILED_FUTURE_CHECKED_EXCEPTION,
- ExceptionWithSomePrivateConstructors.class);
- fail();
- } catch (ExceptionWithSomePrivateConstructors expected) {
- }
- }
+ CheckedFuture<String, TestException> checked = Futures.makeChecked(
+ future, new Function<Exception, TestException>() {
+ @Override
+ public TestException apply(Exception from) {
+ throw new NullPointerException();
+ }
+ });
- public void testGetUntimed_exceptionClassNoPublicConstructor()
- throws ExceptionWithPrivateConstructor {
- try {
- get(FAILED_FUTURE_CHECKED_EXCEPTION,
- ExceptionWithPrivateConstructor.class);
- fail();
- } catch (IllegalArgumentException expected) {
- }
+ ListenableFutureTester tester = new ListenableFutureTester(checked);
+ tester.setUp();
+ future.cancel(true); // argument is ignored
+ tester.testCancelledFuture();
+ tester.tearDown();
}
- public void testGetUntimed_exceptionClassPublicConstructorWrongType()
- throws ExceptionWithWrongTypesConstructor {
- try {
- get(FAILED_FUTURE_CHECKED_EXCEPTION,
- ExceptionWithWrongTypesConstructor.class);
- fail();
- } catch (IllegalArgumentException expected) {
- }
- }
+ @GwtIncompatible("makeChecked")
- public void testGetUntimed_exceptionClassPrefersStringConstructor() {
- try {
- get(FAILED_FUTURE_CHECKED_EXCEPTION,
- ExceptionWithManyConstructors.class);
- fail();
- } catch (ExceptionWithManyConstructors expected) {
- assertTrue(expected.usedExpectedConstructor);
- }
+ public void testMakeChecked_listenersRunOnFailure() throws Exception {
+ SettableFuture<String> future = SettableFuture.create();
+
+ CheckedFuture<String, TestException> checked = Futures.makeChecked(
+ future, new Function<Exception, TestException>() {
+ @Override
+ public TestException apply(Exception from) {
+ throw new NullPointerException();
+ }
+ });
+
+ ListenableFutureTester tester = new ListenableFutureTester(checked);
+ tester.setUp();
+ future.setException(new Exception("failed"));
+ tester.testFailedFuture("failed");
+ tester.tearDown();
}
- public void testGetUntimed_exceptionClassUsedInitCause() {
- try {
- get(FAILED_FUTURE_CHECKED_EXCEPTION,
- ExceptionWithoutThrowableConstructor.class);
- fail();
- } catch (ExceptionWithoutThrowableConstructor expected) {
- assertThat(expected.getMessage()).contains("mymessage");
- assertEquals(CHECKED_EXCEPTION, expected.getCause());
- }
+ @GwtIncompatible("used only in GwtIncompatible tests")
+ private interface MapperFunction extends Function<Throwable, Exception> {
+
}
+ @GwtIncompatible("inCompletionOrder")
public void testCompletionOrder() throws Exception {
SettableFuture<Long> future1 = SettableFuture.create();
SettableFuture<Long> future2 = SettableFuture.create();
@@ -2382,6 +3063,7 @@ public class FuturesTest extends TestCase {
}
}
+ @GwtIncompatible("inCompletionOrder")
public void testCompletionOrderExceptionThrown() throws Exception {
SettableFuture<Long> future1 = SettableFuture.create();
SettableFuture<Long> future2 = SettableFuture.create();
@@ -2407,13 +3089,14 @@ public class FuturesTest extends TestCase {
fail();
} catch (ExecutionException e) {
// Expected
- assertEquals("2L", e.getCause().getMessage());
+ assertThat(e.getCause()).hasMessage("2L");
}
}
expected++;
}
}
+ @GwtIncompatible("inCompletionOrder")
public void testCompletionOrderFutureCancelled() throws Exception {
SettableFuture<Long> future1 = SettableFuture.create();
SettableFuture<Long> future2 = SettableFuture.create();
@@ -2445,6 +3128,7 @@ public class FuturesTest extends TestCase {
}
}
+ @GwtIncompatible("inCompletionOrder")
public void testCancellingADelegateDoesNotPropagate() throws Exception {
SettableFuture<Long> future1 = SettableFuture.create();
SettableFuture<Long> future2 = SettableFuture.create();
@@ -2464,6 +3148,7 @@ public class FuturesTest extends TestCase {
}
// Mostly an example of how it would look like to use a list of mixed types
+ @GwtIncompatible("inCompletionOrder")
public void testCompletionOrderMixedBagOTypes() throws Exception {
SettableFuture<Long> future1 = SettableFuture.create();
SettableFuture<String> future2 = SettableFuture.create();
@@ -2482,122 +3167,40 @@ public class FuturesTest extends TestCase {
}
}
- public static final class TwoArgConstructorException extends Exception {
- public TwoArgConstructorException(String message, Throwable cause) {
- super(message, cause);
- }
- }
-
- public static final class TwoArgConstructorRuntimeException
- extends RuntimeException {
- public TwoArgConstructorRuntimeException(String message, Throwable cause) {
- super(message, cause);
- }
- }
-
- public static final class ExceptionWithPrivateConstructor extends Exception {
- private ExceptionWithPrivateConstructor(String message, Throwable cause) {
- super(message, cause);
- }
- }
-
- @SuppressWarnings("unused") // we're testing that they're not used
- public static final class ExceptionWithSomePrivateConstructors
- extends Exception {
- private ExceptionWithSomePrivateConstructors(String a) {
- }
-
- private ExceptionWithSomePrivateConstructors(String a, String b) {
- }
-
- public ExceptionWithSomePrivateConstructors(
- String a, String b, String c) {
- }
-
- private ExceptionWithSomePrivateConstructors(
- String a, String b, String c, String d) {
- }
-
- private ExceptionWithSomePrivateConstructors(
- String a, String b, String c, String d, String e) {
- }
- }
-
- public static final class ExceptionWithManyConstructors extends Exception {
- boolean usedExpectedConstructor;
-
- public ExceptionWithManyConstructors() {
- }
-
- public ExceptionWithManyConstructors(Integer i) {
- }
-
- public ExceptionWithManyConstructors(Throwable a) {
- }
-
- public ExceptionWithManyConstructors(Throwable a, Throwable b) {
- }
-
- public ExceptionWithManyConstructors(String s, Throwable b) {
- usedExpectedConstructor = true;
- }
-
- public ExceptionWithManyConstructors(
- Throwable a, Throwable b, Throwable c) {
- }
-
- public ExceptionWithManyConstructors(
- Throwable a, Throwable b, Throwable c, Throwable d) {
- }
-
- public ExceptionWithManyConstructors(
- Throwable a, Throwable b, Throwable c, Throwable d, Throwable e) {
- }
-
- public ExceptionWithManyConstructors(Throwable a, Throwable b, Throwable c,
- Throwable d, Throwable e, String s, Integer i) {
- }
+ @GwtIncompatible("ClassSanityTester")
+ public void testFutures_nullChecks() throws Exception {
+ new ClassSanityTester()
+ .forAllPublicStaticMethods(Futures.class)
+ .thatReturn(Future.class)
+ .testNulls();
}
- public static final class ExceptionWithoutThrowableConstructor
- extends Exception {
- public ExceptionWithoutThrowableConstructor(String s) {
- super(s);
- }
+ static AssertionFailedError failureWithCause(Throwable cause, String message) {
+ AssertionFailedError failure = new AssertionFailedError(message);
+ failure.initCause(cause);
+ return failure;
}
- public static final class ExceptionWithWrongTypesConstructor
- extends Exception {
- public ExceptionWithWrongTypesConstructor(Integer i, String s) {
- super(s);
- }
- }
+ /**
+ * A future that throws a runtime exception from get.
+ */
+ static class BuggyFuture extends AbstractFuture<String> {
- private static final class ExceptionWithGoodAndBadConstructor extends Exception {
- public ExceptionWithGoodAndBadConstructor(String message, Throwable cause) {
- throw new RuntimeException("bad constructor");
- }
- public ExceptionWithGoodAndBadConstructor(Throwable cause) {
- super(cause);
+ @Override
+ public String get() {
+ throw new RuntimeException();
}
- }
- private static final class ExceptionWithBadConstructor extends Exception {
- public ExceptionWithBadConstructor(String message, Throwable cause) {
- throw new RuntimeException("bad constructor");
+ @Override
+ public boolean set(String v) {
+ return super.set(v);
}
}
- public void testFutures_nullChecks() throws Exception {
- new ClassSanityTester()
- .forAllPublicStaticMethods(Futures.class)
- .thatReturn(Future.class)
- .testNulls();
- }
+ // This test covers a bug where an Error thrown from a callback could cause the TimeoutFuture to
+ // never complete when timing out. Notably, nothing would get logged since the Error would get
+ // stuck in the ScheduledFuture inside of TimeoutFuture and nothing ever calls get on it.
- private static void failWithCause(Throwable cause, String message) {
- AssertionFailedError failure = new AssertionFailedError(message);
- failure.initCause(cause);
- throw failure;
- }
+ // Simulate a timeout that fires before the call the SES.schedule returns but the future is
+ // already completed.
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/FuturesTransformAsyncTest.java b/guava-tests/test/com/google/common/util/concurrent/FuturesTransformAsyncTest.java
new file mode 100644
index 0000000..89eb61c
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/FuturesTransformAsyncTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.util.concurrent.Uninterruptibles.awaitUninterruptibly;
+
+import com.google.common.util.concurrent.ForwardingListenableFuture.SimpleForwardingListenableFuture;
+
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Unit tests for {@link Futures#transformAsync(ListenableFuture, AsyncFunction)}.
+ *
+ * @author Nishant Thakkar
+ */
+public class FuturesTransformAsyncTest
+ extends AbstractChainedListenableFutureTest<String> {
+ protected static final int SLOW_OUTPUT_VALID_INPUT_DATA = 2;
+ protected static final int SLOW_FUNC_VALID_INPUT_DATA = 3;
+ private static final String RESULT_DATA = "SUCCESS";
+
+ private SettableFuture<String> outputFuture;
+ // Signals that the function is waiting to complete
+ private CountDownLatch funcIsWaitingLatch;
+ // Signals the function so it will complete
+ private CountDownLatch funcCompletionLatch;
+
+ @Override protected ListenableFuture<String> buildChainingFuture(
+ ListenableFuture<Integer> inputFuture) {
+ outputFuture = SettableFuture.create();
+ funcIsWaitingLatch = new CountDownLatch(1);
+ funcCompletionLatch = new CountDownLatch(1);
+ return Futures.transformAsync(inputFuture, new ChainingFunction());
+ }
+
+ @Override protected String getSuccessfulResult() {
+ return RESULT_DATA;
+ }
+
+ private class ChainingFunction implements AsyncFunction<Integer, String> {
+ @Override
+ public ListenableFuture<String> apply(Integer input) {
+ switch (input) {
+ case VALID_INPUT_DATA: outputFuture.set(RESULT_DATA); break;
+ case SLOW_OUTPUT_VALID_INPUT_DATA: break; // do nothing to the result
+ case SLOW_FUNC_VALID_INPUT_DATA:
+ funcIsWaitingLatch.countDown();
+ awaitUninterruptibly(funcCompletionLatch);
+ break;
+ default: throw new UndeclaredThrowableException(EXCEPTION);
+ }
+ return outputFuture;
+ }
+ }
+
+ public void testFutureGetThrowsFunctionException() throws Exception {
+ inputFuture.set(EXCEPTION_DATA);
+ listener.assertException(EXCEPTION);
+ }
+
+ public void testFutureGetThrowsCancellationIfInputCancelled()
+ throws Exception {
+ inputFuture.cancel(true); // argument is ignored
+ try {
+ resultFuture.get();
+ fail("Result future must throw CancellationException"
+ + " if input future is cancelled.");
+ } catch (CancellationException expected) {}
+ }
+
+ public void testFutureGetThrowsCancellationIfOutputCancelled()
+ throws Exception {
+ inputFuture.set(SLOW_OUTPUT_VALID_INPUT_DATA);
+ outputFuture.cancel(true); // argument is ignored
+ try {
+ resultFuture.get();
+ fail("Result future must throw CancellationException"
+ + " if function output future is cancelled.");
+ } catch (CancellationException expected) {}
+ }
+
+ public void testFutureCancelBeforeInputCompletion() throws Exception {
+ assertTrue(resultFuture.cancel(true));
+ assertTrue(resultFuture.isCancelled());
+ assertTrue(inputFuture.isCancelled());
+ assertFalse(outputFuture.isCancelled());
+ try {
+ resultFuture.get();
+ fail("Result future is cancelled and should have thrown a"
+ + " CancellationException");
+ } catch (CancellationException expected) {}
+ }
+
+ public void testFutureCancellableBeforeOutputCompletion() throws Exception {
+ inputFuture.set(SLOW_OUTPUT_VALID_INPUT_DATA);
+ assertTrue(resultFuture.cancel(true));
+ assertTrue(resultFuture.isCancelled());
+ assertFalse(inputFuture.isCancelled());
+ assertTrue(outputFuture.isCancelled());
+ try {
+ resultFuture.get();
+ fail("Result future is cancelled and should have thrown a"
+ + " CancellationException");
+ } catch (CancellationException expected) {}
+ }
+
+ public void testFutureCancellableBeforeFunctionCompletion() throws Exception {
+ // Set the result in a separate thread since this test runs the function
+ // (which will block) in the same thread.
+ new Thread() {
+ @Override
+ public void run() {
+ inputFuture.set(SLOW_FUNC_VALID_INPUT_DATA);
+ }
+ }.start();
+ funcIsWaitingLatch.await();
+
+ assertTrue(resultFuture.cancel(true));
+ assertTrue(resultFuture.isCancelled());
+ assertFalse(inputFuture.isCancelled());
+ assertFalse(outputFuture.isCancelled());
+ try {
+ resultFuture.get();
+ fail("Result future is cancelled and should have thrown a"
+ + " CancellationException");
+ } catch (CancellationException expected) {}
+
+ funcCompletionLatch.countDown(); // allow the function to complete
+ try {
+ outputFuture.get();
+ fail("The function output future is cancelled and should have thrown a"
+ + " CancellationException");
+ } catch (CancellationException expected) {}
+ }
+
+ public void testFutureCancelAfterCompletion() throws Exception {
+ inputFuture.set(VALID_INPUT_DATA);
+ assertFalse(resultFuture.cancel(true));
+ assertFalse(resultFuture.isCancelled());
+ assertFalse(inputFuture.isCancelled());
+ assertFalse(outputFuture.isCancelled());
+ assertEquals(RESULT_DATA, resultFuture.get());
+ }
+
+ public void testFutureGetThrowsRuntimeException() throws Exception {
+ BadFuture badInput = new BadFuture(Futures.immediateFuture(20));
+ ListenableFuture<String> chain = buildChainingFuture(badInput);
+ try {
+ chain.get();
+ fail("Future.get must throw an exception when the input future fails.");
+ } catch (ExecutionException e) {
+ assertSame(RuntimeException.class, e.getCause().getClass());
+ }
+ }
+
+ /**
+ * Proxy to throw a {@link RuntimeException} out of the {@link #get()} method.
+ */
+ public static class BadFuture
+ extends SimpleForwardingListenableFuture<Integer> {
+ protected BadFuture(ListenableFuture<Integer> delegate) {
+ super(delegate);
+ }
+
+ @Override
+ public Integer get() {
+ throw new RuntimeException("Oops");
+ }
+ }
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/GeneratedMonitorTest.java b/guava-tests/test/com/google/common/util/concurrent/GeneratedMonitorTest.java
new file mode 100644
index 0000000..25a49f5
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/GeneratedMonitorTest.java
@@ -0,0 +1,787 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.util.concurrent.Uninterruptibles.awaitUninterruptibly;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.collect.ImmutableList;
+import com.google.common.primitives.Ints;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Locale;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Generated tests for {@link Monitor}.
+ *
+ * <p>This test class generates all of its own test cases in the {@link #suite()} method. Every
+ * {@code enterXxx}, {@code tryEnterXxx}, and {@code waitForXxx} method of the {@code Monitor} class
+ * is analyzed reflectively to determine appropriate test cases based on its signature. Additional
+ * ad hoc test cases can be found in {@link SupplementalMonitorTest}.
+ *
+ * @author Justin T. Sampson
+ */
+
+public class GeneratedMonitorTest extends TestCase {
+
+ public static TestSuite suite() {
+ TestSuite suite = new TestSuite();
+
+ Method[] methods = Monitor.class.getMethods();
+ sortMethods(methods);
+ for (Method method : methods) {
+ if (isAnyEnter(method) || isWaitFor(method)) {
+ validateMethod(method);
+ addTests(suite, method);
+ }
+ }
+
+ assertEquals(548, suite.testCount());
+
+ return suite;
+ }
+
+ /**
+ * A typical timeout value we'll use in the tests.
+ */
+ private static final long SMALL_TIMEOUT_MILLIS = 10;
+
+ /**
+ * How long to wait when determining that a thread is blocked if we expect it to be blocked.
+ */
+ private static final long EXPECTED_HANG_DELAY_MILLIS = 75;
+
+ /**
+ * How long to wait when determining that a thread is blocked if we DON'T expect it to be blocked.
+ */
+ private static final long UNEXPECTED_HANG_DELAY_MILLIS = 10000;
+
+ /**
+ * Various scenarios to be generated for each method under test. The actual scenario generation
+ * (determining which scenarios are applicable to which methods and what the outcome should be)
+ * takes place in {@link #addTests(TestSuite, Method)}.
+ */
+ private enum Scenario {
+
+ SATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING,
+ UNSATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING,
+ SATISFIED_AND_OCCUPIED_BEFORE_ENTERING,
+ SATISFIED_UNOCCUPIED_AND_INTERRUPTED_BEFORE_ENTERING,
+
+ SATISFIED_BEFORE_WAITING,
+ SATISFIED_WHILE_WAITING,
+ SATISFIED_AND_INTERRUPTED_BEFORE_WAITING,
+ UNSATISFIED_BEFORE_AND_WHILE_WAITING,
+ UNSATISFIED_AND_INTERRUPTED_BEFORE_WAITING;
+
+ @Override
+ public String toString() {
+ return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+ }
+
+ }
+
+ /**
+ * Timeout values to combine with each {@link Scenario}.
+ */
+ private enum Timeout {
+
+ MIN(Long.MIN_VALUE, "-oo"),
+ MINUS_SMALL(-SMALL_TIMEOUT_MILLIS, "-" + SMALL_TIMEOUT_MILLIS + "ms"),
+ ZERO(0L, "0ms"),
+ SMALL(SMALL_TIMEOUT_MILLIS, SMALL_TIMEOUT_MILLIS + "ms"),
+ LARGE(UNEXPECTED_HANG_DELAY_MILLIS * 2, (2 * UNEXPECTED_HANG_DELAY_MILLIS) + "ms"),
+ MAX(Long.MAX_VALUE, "+oo");
+
+ final long millis;
+ final String label;
+
+ private Timeout(long millis, String label) {
+ this.millis = millis;
+ this.label = label;
+ }
+
+ @Override
+ public String toString() {
+ return label;
+ }
+
+ }
+
+ /**
+ * Convenient subsets of the {@link Timeout} enumeration for specifying scenario outcomes.
+ */
+ private enum TimeoutsToUse {
+
+ ANY(Timeout.values()),
+ PAST(Timeout.MIN, Timeout.MINUS_SMALL, Timeout.ZERO),
+ FUTURE(Timeout.SMALL, Timeout.MAX),
+ SMALL(Timeout.SMALL),
+ FINITE(Timeout.MIN, Timeout.MINUS_SMALL, Timeout.ZERO, Timeout.SMALL),
+ INFINITE(Timeout.LARGE, Timeout.MAX);
+
+ final ImmutableList<Timeout> timeouts;
+
+ private TimeoutsToUse(Timeout... timeouts) {
+ this.timeouts = ImmutableList.copyOf(timeouts);
+ }
+
+ }
+
+ /**
+ * Possible outcomes of calling any of the methods under test.
+ */
+ private enum Outcome {
+
+ /**
+ * The method returned normally and is either void or returned true.
+ */
+ SUCCESS,
+
+ /**
+ * The method returned false.
+ */
+ FAILURE,
+
+ /**
+ * The method threw an InterruptedException.
+ */
+ INTERRUPT,
+
+ /**
+ * The method did not return or throw anything.
+ */
+ HANG;
+
+ @Override
+ public String toString() {
+ return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+ }
+
+ }
+
+ /**
+ * Identifies all enterXxx and tryEnterXxx methods.
+ */
+ private static boolean isAnyEnter(Method method) {
+ return method.getName().startsWith("enter") || method.getName().startsWith("tryEnter");
+ }
+
+ /**
+ * Identifies just tryEnterXxx methods (a subset of {@link #isAnyEnter}), which never block.
+ */
+ private static boolean isTryEnter(Method method) {
+ return method.getName().startsWith("tryEnter");
+ }
+
+ /**
+ * Identifies just enterIfXxx methods (a subset of {@link #isAnyEnter}), which are mostly like the
+ * enterXxx methods but behave like tryEnterXxx in some scenarios.
+ */
+ private static boolean isEnterIf(Method method) {
+ return method.getName().startsWith("enterIf");
+ }
+
+ /**
+ * Identifies all waitForXxx methods, which must be called while occupying the monitor.
+ */
+ private static boolean isWaitFor(Method method) {
+ return method.getName().startsWith("waitFor");
+ }
+
+ /**
+ * Determines whether the given method takes a Guard as its first parameter.
+ */
+ private static boolean isGuarded(Method method) {
+ Class<?>[] parameterTypes = method.getParameterTypes();
+ return parameterTypes.length >= 1 && parameterTypes[0] == Monitor.Guard.class;
+ }
+
+ /**
+ * Determines whether the given method takes a time and unit as its last two parameters.
+ */
+ private static boolean isTimed(Method method) {
+ Class<?>[] parameterTypes = method.getParameterTypes();
+ return parameterTypes.length >= 2
+ && parameterTypes[parameterTypes.length - 2] == long.class
+ && parameterTypes[parameterTypes.length - 1] == TimeUnit.class;
+ }
+
+ /**
+ * Determines whether the given method returns a boolean value.
+ */
+ private static boolean isBoolean(Method method) {
+ return method.getReturnType() == boolean.class;
+ }
+
+ /**
+ * Determines whether the given method can throw InterruptedException.
+ */
+ private static boolean isInterruptible(Method method) {
+ return Arrays.asList(method.getExceptionTypes()).contains(InterruptedException.class);
+ }
+
+ /**
+ * Sorts the given methods primarily by name and secondarily by number of parameters.
+ */
+ private static void sortMethods(Method[] methods) {
+ Arrays.sort(methods, new Comparator<Method>() {
+ @Override public int compare(Method m1, Method m2) {
+ int nameComparison = m1.getName().compareTo(m2.getName());
+ if (nameComparison != 0) {
+ return nameComparison;
+ } else {
+ return Ints.compare(m1.getParameterTypes().length, m2.getParameterTypes().length);
+ }
+ }
+ });
+ }
+
+ /**
+ * Validates that the given method's signature meets all of our assumptions.
+ */
+ private static void validateMethod(Method method) {
+ String desc = method.toString();
+
+ assertTrue(desc, isAnyEnter(method) || isWaitFor(method));
+
+ switch (method.getParameterTypes().length) {
+ case 0:
+ assertFalse(desc, isGuarded(method));
+ assertFalse(desc, isTimed(method));
+ break;
+ case 1:
+ assertTrue(desc, isGuarded(method));
+ assertFalse(desc, isTimed(method));
+ break;
+ case 2:
+ assertFalse(desc, isGuarded(method));
+ assertTrue(desc, isTimed(method));
+ break;
+ case 3:
+ assertTrue(desc, isGuarded(method));
+ assertTrue(desc, isTimed(method));
+ break;
+ default:
+ fail(desc);
+ }
+
+ if (method.getReturnType() == void.class) {
+ assertFalse(desc, isBoolean(method));
+ } else {
+ assertTrue(desc, isBoolean(method));
+ }
+
+ switch (method.getExceptionTypes().length) {
+ case 0:
+ assertFalse(desc, isInterruptible(method));
+ break;
+ case 1:
+ assertTrue(desc, isInterruptible(method));
+ break;
+ default:
+ fail(desc);
+ }
+
+ if (isEnterIf(method)) {
+ assertTrue(desc, isGuarded(method));
+ assertTrue(desc, isBoolean(method));
+ } else if (isTryEnter(method)) {
+ assertFalse(desc, isTimed(method));
+ assertTrue(desc, isBoolean(method));
+ assertFalse(desc, isInterruptible(method));
+ } else if (isWaitFor(method)) {
+ assertTrue(desc, isGuarded(method));
+ assertEquals(desc, isTimed(method), isBoolean(method));
+ } else { // any other enterXxx method
+ assertEquals(desc, isTimed(method), isBoolean(method));
+ }
+ }
+
+ /**
+ * Generates all test cases appropriate for the given method.
+ */
+ private static void addTests(TestSuite suite, Method method) {
+ if (isGuarded(method)) {
+ for (boolean fair1 : new boolean[] { true, false }) {
+ for (boolean fair2 : new boolean[] { true, false }) {
+ suite.addTest(generateGuardWithWrongMonitorTestCase(method, fair1, fair2));
+ }
+ }
+ }
+ if (isAnyEnter(method)) {
+ addTests(suite, method,
+ Scenario.SATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING,
+ TimeoutsToUse.ANY,
+ Outcome.SUCCESS);
+ addTests(suite, method,
+ Scenario.UNSATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING,
+ TimeoutsToUse.FINITE,
+ isGuarded(method)
+ ? (isBoolean(method) ? Outcome.FAILURE : Outcome.HANG)
+ : Outcome.SUCCESS);
+ addTests(suite, method,
+ Scenario.UNSATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING,
+ TimeoutsToUse.INFINITE,
+ isGuarded(method)
+ ? (isTryEnter(method) || isEnterIf(method) ? Outcome.FAILURE : Outcome.HANG)
+ : Outcome.SUCCESS);
+ addTests(suite, method,
+ Scenario.SATISFIED_AND_OCCUPIED_BEFORE_ENTERING,
+ TimeoutsToUse.FINITE,
+ isBoolean(method) ? Outcome.FAILURE : Outcome.HANG);
+ addTests(suite, method,
+ Scenario.SATISFIED_AND_OCCUPIED_BEFORE_ENTERING,
+ TimeoutsToUse.INFINITE,
+ isGuarded(method)
+ ? Outcome.HANG
+ : (isTryEnter(method) ? Outcome.FAILURE : Outcome.HANG));
+ addTests(suite, method,
+ Scenario.SATISFIED_UNOCCUPIED_AND_INTERRUPTED_BEFORE_ENTERING,
+ TimeoutsToUse.ANY,
+ isInterruptible(method) ? Outcome.INTERRUPT : Outcome.SUCCESS);
+ } else { // any waitForXxx method
+ suite.addTest(generateWaitForWhenNotOccupyingTestCase(method, true));
+ suite.addTest(generateWaitForWhenNotOccupyingTestCase(method, false));
+ addTests(suite, method,
+ Scenario.SATISFIED_BEFORE_WAITING,
+ TimeoutsToUse.ANY,
+ Outcome.SUCCESS);
+ addTests(suite, method,
+ Scenario.SATISFIED_WHILE_WAITING,
+ TimeoutsToUse.INFINITE,
+ Outcome.SUCCESS);
+ addTests(suite, method,
+ Scenario.SATISFIED_WHILE_WAITING,
+ TimeoutsToUse.PAST,
+ Outcome.FAILURE);
+ addTests(suite, method,
+ Scenario.SATISFIED_AND_INTERRUPTED_BEFORE_WAITING,
+ TimeoutsToUse.ANY,
+ Outcome.SUCCESS);
+ addTests(suite, method,
+ Scenario.UNSATISFIED_BEFORE_AND_WHILE_WAITING,
+ TimeoutsToUse.FINITE,
+ Outcome.FAILURE);
+ addTests(suite, method,
+ Scenario.UNSATISFIED_BEFORE_AND_WHILE_WAITING,
+ TimeoutsToUse.INFINITE,
+ Outcome.HANG);
+ addTests(suite, method,
+ Scenario.UNSATISFIED_AND_INTERRUPTED_BEFORE_WAITING,
+ TimeoutsToUse.PAST,
+ // prefer responding to interrupt over timing out
+ isInterruptible(method) ? Outcome.INTERRUPT : Outcome.FAILURE);
+ addTests(suite, method,
+ Scenario.UNSATISFIED_AND_INTERRUPTED_BEFORE_WAITING,
+ TimeoutsToUse.SMALL,
+ isInterruptible(method) ? Outcome.INTERRUPT : Outcome.FAILURE);
+ addTests(suite, method,
+ Scenario.UNSATISFIED_AND_INTERRUPTED_BEFORE_WAITING,
+ TimeoutsToUse.INFINITE,
+ isInterruptible(method) ? Outcome.INTERRUPT : Outcome.HANG);
+ }
+ }
+
+ /**
+ * Generates test cases for the given combination of scenario and timeouts. For methods that take
+ * an explicit timeout value, all of the given timeoutsToUse result in individual test cases. For
+ * methods that do not take an explicit timeout value, a single test case is generated only if the
+ * implicit timeout of that method matches the given timeoutsToUse. For example, enter() is
+ * treated like enter(MAX, MILLIS) and tryEnter() is treated like enter(0, MILLIS).
+ */
+ private static void addTests(TestSuite suite, Method method, Scenario scenario,
+ TimeoutsToUse timeoutsToUse, Outcome expectedOutcome) {
+ for (boolean fair : new boolean[] { true, false }) {
+ if (isTimed(method)) {
+ for (Timeout timeout : timeoutsToUse.timeouts) {
+ suite.addTest(new GeneratedMonitorTest(method, scenario, fair, timeout, expectedOutcome));
+ }
+ } else {
+ Timeout implicitTimeout = (isTryEnter(method) ? Timeout.ZERO : Timeout.MAX);
+ if (timeoutsToUse.timeouts.contains(implicitTimeout)) {
+ suite.addTest(new GeneratedMonitorTest(method, scenario, fair, null, expectedOutcome));
+ }
+ }
+ }
+ }
+
+ /**
+ * A guard that encapsulates a simple, mutable boolean flag.
+ */
+ static class FlagGuard extends Monitor.Guard {
+
+ private boolean satisfied;
+
+ protected FlagGuard(Monitor monitor) {
+ super(monitor);
+ }
+
+ @Override
+ public boolean isSatisfied() {
+ return satisfied;
+ }
+
+ public void setSatisfied(boolean satisfied) {
+ this.satisfied = satisfied;
+ }
+
+ }
+
+ private final Method method;
+ private final Scenario scenario;
+ private final Timeout timeout;
+ private final Outcome expectedOutcome;
+ private final Monitor monitor;
+ private final FlagGuard guard;
+ private final CountDownLatch tearDownLatch;
+ private final CountDownLatch doingCallLatch;
+ private final CountDownLatch callCompletedLatch;
+
+ private GeneratedMonitorTest(
+ Method method, Scenario scenario, boolean fair, Timeout timeout, Outcome expectedOutcome) {
+ super(nameFor(method, scenario, fair, timeout, expectedOutcome));
+ this.method = method;
+ this.scenario = scenario;
+ this.timeout = timeout;
+ this.expectedOutcome = expectedOutcome;
+ this.monitor = new Monitor(fair);
+ this.guard = new FlagGuard(monitor);
+ this.tearDownLatch = new CountDownLatch(1);
+ this.doingCallLatch = new CountDownLatch(1);
+ this.callCompletedLatch = new CountDownLatch(1);
+ }
+
+ private static String nameFor(
+ Method method, Scenario scenario, boolean fair, Timeout timeout, Outcome expectedOutcome) {
+ return String.format(Locale.ROOT,
+ "%s%s(%s)/%s->%s",
+ method.getName(),
+ fair ? "(fair)" : "(nonfair)",
+ (timeout == null) ? "untimed" : timeout,
+ scenario,
+ expectedOutcome);
+ }
+
+ @Override
+ protected void runTest() throws Throwable {
+ final Runnable runChosenTest = new Runnable() {
+ @Override public void run() { runChosenTest(); }
+ };
+ final FutureTask<Void> task = new FutureTask<Void>(runChosenTest, null);
+ startThread(new Runnable() {
+ @Override public void run() { task.run(); }
+ });
+ awaitUninterruptibly(doingCallLatch);
+ long hangDelayMillis = (expectedOutcome == Outcome.HANG)
+ ? EXPECTED_HANG_DELAY_MILLIS
+ : UNEXPECTED_HANG_DELAY_MILLIS;
+ boolean hung = !awaitUninterruptibly(
+ callCompletedLatch, hangDelayMillis, TimeUnit.MILLISECONDS);
+ if (hung) {
+ assertEquals(expectedOutcome, Outcome.HANG);
+ } else {
+ assertNull(task.get(UNEXPECTED_HANG_DELAY_MILLIS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // We don't want to leave stray threads running after each test. At this point, every thread
+ // launched by this test is either:
+ //
+ // (a) Blocked attempting to enter the monitor.
+ // (b) Waiting for the single guard to become satisfied.
+ // (c) Occupying the monitor and awaiting the tearDownLatch.
+ //
+ // Except for (c), every thread should occupy the monitor very briefly, and every thread leaves
+ // the monitor with the guard satisfied. Therefore as soon as tearDownLatch is triggered, we
+ // should be able to enter the monitor, and then we set the guard to satisfied for the benefit
+ // of any remaining waiting threads.
+
+ tearDownLatch.countDown();
+ assertTrue("Monitor still occupied in tearDown()",
+ monitor.enter(UNEXPECTED_HANG_DELAY_MILLIS, TimeUnit.MILLISECONDS));
+ try {
+ guard.setSatisfied(true);
+ } finally {
+ monitor.leave();
+ }
+ }
+
+ private void runChosenTest() {
+ if (isAnyEnter(method)) {
+ runEnterTest();
+ } else {
+ runWaitTest();
+ }
+ }
+
+ private void runEnterTest() {
+ assertFalse(Thread.currentThread().isInterrupted());
+ assertFalse(monitor.isOccupiedByCurrentThread());
+
+ doEnterScenarioSetUp();
+
+ boolean interruptedBeforeCall = Thread.currentThread().isInterrupted();
+ Outcome actualOutcome = doCall();
+ boolean occupiedAfterCall = monitor.isOccupiedByCurrentThread();
+ boolean interruptedAfterCall = Thread.currentThread().isInterrupted();
+
+ if (occupiedAfterCall) {
+ guard.setSatisfied(true);
+ monitor.leave();
+ assertFalse(monitor.isOccupiedByCurrentThread());
+ }
+
+ assertEquals(expectedOutcome, actualOutcome);
+ assertEquals(expectedOutcome == Outcome.SUCCESS, occupiedAfterCall);
+ assertEquals(interruptedBeforeCall && expectedOutcome != Outcome.INTERRUPT,
+ interruptedAfterCall);
+ }
+
+ private void doEnterScenarioSetUp() {
+ switch (scenario) {
+ case SATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING:
+ enterSatisfyGuardAndLeaveInCurrentThread();
+ break;
+ case UNSATISFIED_AND_UNOCCUPIED_BEFORE_ENTERING:
+ break;
+ case SATISFIED_AND_OCCUPIED_BEFORE_ENTERING:
+ enterSatisfyGuardAndLeaveInCurrentThread();
+ enterAndRemainOccupyingInAnotherThread();
+ break;
+ case SATISFIED_UNOCCUPIED_AND_INTERRUPTED_BEFORE_ENTERING:
+ enterSatisfyGuardAndLeaveInCurrentThread();
+ Thread.currentThread().interrupt();
+ break;
+ default:
+ throw new AssertionError("unsupported scenario: " + scenario);
+ }
+ }
+
+ private void runWaitTest() {
+ assertFalse(Thread.currentThread().isInterrupted());
+ assertFalse(monitor.isOccupiedByCurrentThread());
+ monitor.enter();
+ try {
+ assertTrue(monitor.isOccupiedByCurrentThread());
+
+ doWaitScenarioSetUp();
+
+ boolean interruptedBeforeCall = Thread.currentThread().isInterrupted();
+ Outcome actualOutcome = doCall();
+ boolean occupiedAfterCall = monitor.isOccupiedByCurrentThread();
+ boolean interruptedAfterCall = Thread.currentThread().isInterrupted();
+
+ assertEquals(expectedOutcome, actualOutcome);
+ assertTrue(occupiedAfterCall);
+ assertEquals(interruptedBeforeCall && expectedOutcome != Outcome.INTERRUPT,
+ interruptedAfterCall);
+ } finally {
+ guard.setSatisfied(true);
+ monitor.leave();
+ assertFalse(monitor.isOccupiedByCurrentThread());
+ }
+ }
+
+ private void doWaitScenarioSetUp() {
+ switch (scenario) {
+ case SATISFIED_BEFORE_WAITING:
+ guard.setSatisfied(true);
+ break;
+ case SATISFIED_WHILE_WAITING:
+ guard.setSatisfied(false);
+ enterSatisfyGuardAndLeaveInAnotherThread(); // enter blocks until we call waitFor
+ break;
+ case UNSATISFIED_BEFORE_AND_WHILE_WAITING:
+ guard.setSatisfied(false);
+ break;
+ case SATISFIED_AND_INTERRUPTED_BEFORE_WAITING:
+ guard.setSatisfied(true);
+ Thread.currentThread().interrupt();
+ break;
+ case UNSATISFIED_AND_INTERRUPTED_BEFORE_WAITING:
+ guard.setSatisfied(false);
+ Thread.currentThread().interrupt();
+ break;
+ default:
+ throw new AssertionError("unsupported scenario: " + scenario);
+ }
+ }
+
+ private Outcome doCall() {
+ boolean guarded = isGuarded(method);
+ boolean timed = isTimed(method);
+ Object[] arguments = new Object[(guarded ? 1 : 0) + (timed ? 2 : 0)];
+ if (guarded) {
+ arguments[0] = guard;
+ }
+ if (timed) {
+ arguments[arguments.length - 2] = timeout.millis;
+ arguments[arguments.length - 1] = TimeUnit.MILLISECONDS;
+ }
+ try {
+ Object result;
+ doingCallLatch.countDown();
+ try {
+ result = method.invoke(monitor, arguments);
+ } finally {
+ callCompletedLatch.countDown();
+ }
+ if (result == null) {
+ return Outcome.SUCCESS;
+ } else if ((Boolean) result) {
+ return Outcome.SUCCESS;
+ } else {
+ return Outcome.FAILURE;
+ }
+ } catch (InvocationTargetException targetException) {
+ Throwable actualException = targetException.getTargetException();
+ if (actualException instanceof InterruptedException) {
+ return Outcome.INTERRUPT;
+ } else {
+ throw newAssertionError("unexpected exception", targetException);
+ }
+ } catch (IllegalAccessException e) {
+ throw newAssertionError("unexpected exception", e);
+ }
+ }
+
+ private void enterSatisfyGuardAndLeaveInCurrentThread() {
+ monitor.enter();
+ try {
+ guard.setSatisfied(true);
+ } finally {
+ monitor.leave();
+ }
+ }
+
+ private void enterSatisfyGuardAndLeaveInAnotherThread() {
+ final CountDownLatch startedLatch = new CountDownLatch(1);
+ startThread(new Runnable() {
+ @Override public void run() {
+ startedLatch.countDown();
+ enterSatisfyGuardAndLeaveInCurrentThread();
+ }
+ });
+ awaitUninterruptibly(startedLatch);
+ }
+
+ private void enterAndRemainOccupyingInAnotherThread() {
+ final CountDownLatch enteredLatch = new CountDownLatch(1);
+ startThread(new Runnable() {
+ @Override public void run() {
+ monitor.enter();
+ try {
+ enteredLatch.countDown();
+ awaitUninterruptibly(tearDownLatch);
+ guard.setSatisfied(true);
+ } finally {
+ monitor.leave();
+ }
+ }
+ });
+ awaitUninterruptibly(enteredLatch);
+ }
+
+ static Thread startThread(Runnable runnable) {
+ Thread thread = new Thread(runnable);
+ thread.setDaemon(true);
+ thread.start();
+ return thread;
+ }
+
+ /**
+ * Generates a test case verifying that calling any enterXxx, tryEnterXxx, or waitForXxx method
+ * with a guard that doesn't match the monitor produces an IllegalMonitorStateException.
+ */
+ private static TestCase generateGuardWithWrongMonitorTestCase(final Method method,
+ final boolean fair1,
+ final boolean fair2) {
+ final boolean timed = isTimed(method); // Not going to bother with all timeouts, just 0ms.
+ return new TestCase(method.getName() + (timed ? "(0ms)" : "()") + "/WrongMonitor->IMSE") {
+ @Override protected void runTest() throws Throwable {
+ Monitor monitor1 = new Monitor(fair1);
+ Monitor monitor2 = new Monitor(fair2);
+ FlagGuard guard = new FlagGuard(monitor2);
+ Object[] arguments =
+ (timed ? new Object[] {guard, 0L, TimeUnit.MILLISECONDS} : new Object[] {guard});
+ boolean occupyMonitor = isWaitFor(method);
+ if (occupyMonitor) {
+ // If we don't already occupy the monitor, we'll get an IMSE regardless of the guard (see
+ // generateWaitForWhenNotOccupyingTestCase).
+ monitor1.enter();
+ }
+ try {
+ method.invoke(monitor1, arguments);
+ fail("expected IllegalMonitorStateException");
+ } catch (InvocationTargetException e) {
+ assertEquals(IllegalMonitorStateException.class, e.getTargetException().getClass());
+ } finally {
+ if (occupyMonitor) {
+ monitor1.leave();
+ }
+ }
+ }
+ };
+ }
+
+ /**
+ * Generates a test case verifying that calling any waitForXxx method when not occupying the
+ * monitor produces an IllegalMonitorStateException.
+ */
+ private static TestCase generateWaitForWhenNotOccupyingTestCase(final Method method,
+ final boolean fair) {
+ final boolean timed = isTimed(method); // Not going to bother with all timeouts, just 0ms.
+ String testName = method.getName()
+ + (fair ? "(fair)" : "(nonfair)")
+ + (timed ? "(0ms)" : "()")
+ + "/NotOccupying->IMSE";
+ return new TestCase(testName) {
+ @Override protected void runTest() throws Throwable {
+ Monitor monitor = new Monitor(fair);
+ FlagGuard guard = new FlagGuard(monitor);
+ Object[] arguments =
+ (timed ? new Object[] {guard, 0L, TimeUnit.MILLISECONDS} : new Object[] {guard});
+ try {
+ method.invoke(monitor, arguments);
+ fail("expected IllegalMonitorStateException");
+ } catch (InvocationTargetException e) {
+ assertEquals(IllegalMonitorStateException.class, e.getTargetException().getClass());
+ }
+ }
+ };
+ }
+
+ /** Alternative to AssertionError(String, Throwable), which doesn't exist in Java 1.6 */
+ private static AssertionError newAssertionError(String message, Throwable cause) {
+ AssertionError e = new AssertionError(message);
+ e.initCause(cause);
+ return e;
+ }
+
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/ListenableFutureTester.java b/guava-tests/test/com/google/common/util/concurrent/ListenableFutureTester.java
index cb10fc8..d9e100c 100644
--- a/guava-tests/test/com/google/common/util/concurrent/ListenableFutureTester.java
+++ b/guava-tests/test/com/google/common/util/concurrent/ListenableFutureTester.java
@@ -17,6 +17,7 @@
package com.google.common.util.concurrent;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -104,7 +105,7 @@ public class ListenableFutureTester {
future.get();
fail("Future should rethrow the exception.");
} catch (ExecutionException e) {
- assertEquals(message, e.getCause().getMessage());
+ assertThat(e.getCause()).hasMessage(message);
}
}
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/MoreExecutorsTest.java b/guava-tests/test/com/google/common/util/concurrent/MoreExecutorsTest.java
index cb1898c..994d5d9 100644
--- a/guava-tests/test/com/google/common/util/concurrent/MoreExecutorsTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/MoreExecutorsTest.java
@@ -53,6 +53,7 @@ import com.google.common.util.concurrent.MoreExecutors.Application;
import org.mockito.InOrder;
import org.mockito.Mockito;
+import java.lang.Thread.State;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -243,6 +244,51 @@ public class MoreExecutorsTest extends JSR166TestCase {
throwableFromOtherThread.get());
}
+ /**
+ * Test for a bug where threads weren't getting signaled when shutdown was called, only when
+ * tasks completed.
+ */
+
+ public void testDirectExecutorService_awaitTermination_missedSignal() {
+ final ExecutorService service = MoreExecutors.newDirectExecutorService();
+ Thread waiter = new Thread() {
+ @Override public void run() {
+ try {
+ service.awaitTermination(1, TimeUnit.DAYS);
+ } catch (InterruptedException e) {
+ return;
+ }
+ }
+ };
+ waiter.start();
+ awaitTimedWaiting(waiter);
+ service.shutdown();
+ Uninterruptibles.joinUninterruptibly(waiter, 10, TimeUnit.SECONDS);
+ if (waiter.isAlive()) {
+ waiter.interrupt();
+ fail("awaitTermination failed to trigger after shutdown()");
+ }
+ }
+
+ /** Wait for the given thread to reach the {@link State#TIMED_WAITING} thread state. */
+ void awaitTimedWaiting(Thread thread) {
+ while (true) {
+ switch (thread.getState()) {
+ case BLOCKED:
+ case NEW:
+ case RUNNABLE:
+ case WAITING:
+ Thread.yield();
+ break;
+ case TIMED_WAITING:
+ return;
+ case TERMINATED:
+ default:
+ throw new AssertionError();
+ }
+ }
+ }
+
public void testDirectExecutorService_shutdownNow() {
ExecutorService executor = newDirectExecutorService();
assertEquals(ImmutableList.of(), executor.shutdownNow());
@@ -263,7 +309,7 @@ public class MoreExecutorsTest extends JSR166TestCase {
ListeningExecutorService executor = newDirectExecutorService();
List<Callable<T>> tasks = ImmutableList.of();
@SuppressWarnings("unchecked") // guaranteed by invokeAll contract
- List<ListenableFuture<T>> futures = (List) executor.invokeAll(tasks);
+ List<ListenableFuture<T>> unused = (List) executor.invokeAll(tasks);
}
public void testListeningDecorator() throws Exception {
@@ -275,10 +321,10 @@ public class MoreExecutorsTest extends JSR166TestCase {
List<Future<String>> results;
results = service.invokeAll(callables);
- assertThat(getOnlyElement(results)).isA(ListenableFutureTask.class);
+ assertThat(getOnlyElement(results)).isInstanceOf(TrustedListenableFutureTask.class);
results = service.invokeAll(callables, 1, SECONDS);
- assertThat(getOnlyElement(results)).isA(ListenableFutureTask.class);
+ assertThat(getOnlyElement(results)).isInstanceOf(TrustedListenableFutureTask.class);
/*
* TODO(cpovirk): move ForwardingTestCase somewhere common, and use it to
@@ -306,8 +352,8 @@ public class MoreExecutorsTest extends JSR166TestCase {
}
};
ListeningScheduledExecutorService service = listeningDecorator(delegate);
- ListenableFuture<?> future =
- service.schedule(Callables.returning(null), 1, TimeUnit.MILLISECONDS);
+ ListenableFuture<Integer> future =
+ service.schedule(Callables.returning(42), 1, TimeUnit.MILLISECONDS);
/*
* Wait not just until the Future's value is set (as in future.get()) but
@@ -316,6 +362,7 @@ public class MoreExecutorsTest extends JSR166TestCase {
*/
completed.await();
assertTrue(future.isDone());
+ assertThat(future.get()).isEqualTo(42);
assertListenerRunImmediately(future);
assertEquals(0, delegate.getQueue().size());
}
@@ -472,7 +519,7 @@ public class MoreExecutorsTest extends JSR166TestCase {
invokeAnyImpl(e, l, false, 0);
shouldThrow();
} catch (ExecutionException success) {
- assertTrue(success.getCause() instanceof NullPointerException);
+ assertThat(success.getCause()).isInstanceOf(NullPointerException.class);
} finally {
joinPool(e);
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/PackageSanityTests.java b/guava-tests/test/com/google/common/util/concurrent/PackageSanityTests.java
index 669e547..359f71b 100644
--- a/guava-tests/test/com/google/common/util/concurrent/PackageSanityTests.java
+++ b/guava-tests/test/com/google/common/util/concurrent/PackageSanityTests.java
@@ -19,6 +19,8 @@ package com.google.common.util.concurrent;
import com.google.common.testing.AbstractPackageSanityTests;
import com.google.common.util.concurrent.RateLimiter.SleepingStopwatch;
+import java.io.IOException;
+
/**
* Basic sanity tests for the entire package.
*
@@ -40,6 +42,7 @@ public class PackageSanityTests extends AbstractPackageSanityTests {
public PackageSanityTests() {
setDefault(RateLimiter.class, RateLimiter.create(1.0));
setDefault(SleepingStopwatch.class, NO_OP_STOPWATCH);
+ setDefault(Class.class, IOException.class);
setDefault(long.class, 0L);
}
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/RateLimiterTest.java b/guava-tests/test/com/google/common/util/concurrent/RateLimiterTest.java
index 62ced5c..69a7011 100644
--- a/guava-tests/test/com/google/common/util/concurrent/RateLimiterTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/RateLimiterTest.java
@@ -37,6 +37,7 @@ import org.mockito.Mockito;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
+import java.util.Locale;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@@ -64,6 +65,14 @@ public class RateLimiterTest extends TestCase {
assertFalse("Capable of acquiring secondary permit", r.tryAcquire());
}
+ public void testDoubleMinValueCanAcquireExactlyOnce() {
+ RateLimiter r = RateLimiter.create(stopwatch, Double.MIN_VALUE);
+ assertTrue("Unable to acquire initial permit", r.tryAcquire());
+ assertFalse("Capable of acquiring an additional permit", r.tryAcquire());
+ stopwatch.sleepMillis(Integer.MAX_VALUE);
+ assertFalse("Capable of acquiring an additional permit after sleeping", r.tryAcquire());
+ }
+
public void testSimpleRateUpdate() {
RateLimiter limiter = RateLimiter.create(5.0, 5, SECONDS);
assertEquals(5.0, limiter.getRate());
@@ -174,8 +183,9 @@ public class RateLimiterTest extends TestCase {
}
}
+ @SuppressUnderAndroid // difference in String.format rounding?
public void testWarmUp() {
- RateLimiter limiter = RateLimiter.create(stopwatch, 2.0, 4000, MILLISECONDS);
+ RateLimiter limiter = RateLimiter.create(stopwatch, 2.0, 4000, MILLISECONDS, 3.0);
for (int i = 0; i < 8; i++) {
limiter.acquire(); // #1
}
@@ -199,8 +209,49 @@ public class RateLimiterTest extends TestCase {
"R0.00, R0.50, R0.50, R0.50, R0.50, R0.50, R0.50, R0.50"); // #7
}
+ public void testWarmUpWithColdFactor() {
+ RateLimiter limiter = RateLimiter.create(stopwatch, 5.0, 4000, MILLISECONDS, 10.0);
+ for (int i = 0; i < 8; i++) {
+ limiter.acquire(); // #1
+ }
+ stopwatch.sleepMillis(200); // #2: to repay for the last acquire
+ stopwatch.sleepMillis(4000); // #3: becomes cold again
+ for (int i = 0; i < 8; i++) {
+ limiter.acquire(); // // #4
+ }
+ stopwatch.sleepMillis(200); // #5: to repay for the last acquire
+ stopwatch.sleepMillis(1000); // #6: still warm! It would take another 3 seconds to go cold
+ for (int i = 0; i < 8; i++) {
+ limiter.acquire(); // #7
+ }
+ assertEvents(
+ "R0.00, R1.75, R1.26, R0.76, R0.30, R0.20, R0.20, R0.20", // #1
+ "U0.20", // #2
+ "U4.00", // #3
+ "R0.00, R1.75, R1.26, R0.76, R0.30, R0.20, R0.20, R0.20", // #4
+ "U0.20", // #5
+ "U1.00", // #6
+ "R0.00, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20"); // #7
+ }
+
+ public void testWarmUpWithColdFactor1() {
+ RateLimiter limiter = RateLimiter.create(stopwatch, 5.0, 4000, MILLISECONDS, 1.0);
+ for (int i = 0; i < 8; i++) {
+ limiter.acquire(); // #1
+ }
+ stopwatch.sleepMillis(340); // #2
+ for (int i = 0; i < 8; i++) {
+ limiter.acquire(); // #3
+ }
+ assertEvents(
+ "R0.00, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20", // #1
+ "U0.34", // #2
+ "R0.00, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20"); // #3
+ }
+
+ @SuppressUnderAndroid // difference in String.format rounding?
public void testWarmUpAndUpdate() {
- RateLimiter limiter = RateLimiter.create(stopwatch, 2.0, 4000, MILLISECONDS);
+ RateLimiter limiter = RateLimiter.create(stopwatch, 2.0, 4000, MILLISECONDS, 3.0);
for (int i = 0; i < 8; i++) {
limiter.acquire(); // // #1
}
@@ -231,6 +282,38 @@ public class RateLimiterTest extends TestCase {
"R0.34, R0.28, R0.25, R0.25"); // #7 (cont.), note, this matches #5
}
+ public void testWarmUpAndUpdateWithColdFactor() {
+ RateLimiter limiter = RateLimiter.create(stopwatch, 5.0, 4000, MILLISECONDS, 10.0);
+ for (int i = 0; i < 8; i++) {
+ limiter.acquire(); // #1
+ }
+ stopwatch.sleepMillis(4200); // #2: back to cold state (warmup period + repay last acquire)
+ for (int i = 0; i < 3; i++) { // only three steps, we're somewhere in the warmup period
+ limiter.acquire(); // #3
+ }
+
+ limiter.setRate(10.0); // double the rate!
+ limiter.acquire(); // #4, we repay the debt of the last acquire (imposed by the old rate)
+ for (int i = 0; i < 4; i++) {
+ limiter.acquire(); // #5
+ }
+ stopwatch.sleepMillis(4100); // #6, back to cold state (warmup period + repay last acquire)
+ for (int i = 0; i < 11; i++) {
+ limiter.acquire(); // #7, showing off the warmup starting from totally cold
+ }
+
+ // make sure the areas (times) remain the same, while permits are different
+ assertEvents(
+ "R0.00, R1.75, R1.26, R0.76, R0.30, R0.20, R0.20, R0.20", // #1
+ "U4.20", // #2
+ "R0.00, R1.75, R1.26", // #3, after that the rate changes
+ "R0.76", // #4, this is what the throttling would be with the old rate
+ "R0.20, R0.10, R0.10, R0.10", // #5
+ "U4.10", // #6
+ "R0.00, R0.94, R0.81, R0.69, R0.57, R0.44, R0.32", // #7
+ "R0.20, R0.10, R0.10, R0.10"); // #7 (cont.), note, this matches #5
+ }
+
public void testBurstyAndUpdate() {
RateLimiter rateLimiter = RateLimiter.create(stopwatch, 1.0);
rateLimiter.acquire(1); // no wait
@@ -335,7 +418,7 @@ public class RateLimiterTest extends TestCase {
public void testInfinity_WarmUp() {
RateLimiter limiter = RateLimiter.create(
- stopwatch, Double.POSITIVE_INFINITY, 10, SECONDS);
+ stopwatch, Double.POSITIVE_INFINITY, 10, SECONDS, 3.0);
limiter.acquire(Integer.MAX_VALUE / 4);
limiter.acquire(Integer.MAX_VALUE / 2);
limiter.acquire(Integer.MAX_VALUE);
@@ -355,7 +438,7 @@ public class RateLimiterTest extends TestCase {
}
public void testInfinity_WarmUpTimeElapsed() {
- RateLimiter limiter = RateLimiter.create(stopwatch, Double.POSITIVE_INFINITY, 10, SECONDS);
+ RateLimiter limiter = RateLimiter.create(stopwatch, Double.POSITIVE_INFINITY, 10, SECONDS, 3.0);
stopwatch.instant += 1000000;
limiter.setRate(1.0);
for (int i = 0; i < 5; i++) {
@@ -393,17 +476,19 @@ public class RateLimiterTest extends TestCase {
*/
public void testTimeToWarmUpIsHonouredEvenWithWeights() {
Random random = new Random();
- int maxPermits = 10;
+ int warmupPermits = 10;
+ double[] coldFactorsToTest = { 2.0, 3.0, 10.0 };
double[] qpsToTest = { 4.0, 2.0, 1.0, 0.5, 0.1 };
for (int trial = 0; trial < 100; trial++) {
- for (double qps : qpsToTest) {
- // Since we know that: maxPermits = 0.5 * warmup / stableInterval;
- // then if maxPermits == 10, we have:
- // warmupSeconds = 20 / qps
- long warmupMillis = (long) ((2 * maxPermits / qps) * 1000.0);
- RateLimiter rateLimiter = RateLimiter.create(
- stopwatch, qps, warmupMillis, MILLISECONDS);
- assertEquals(warmupMillis, measureTotalTimeMillis(rateLimiter, maxPermits, random));
+ for (double coldFactor : coldFactorsToTest) {
+ for (double qps : qpsToTest) {
+ // If warmupPermits = maxPermits - thresholdPermits then
+ // warmupPeriod = (1 + coldFactor) * warmupPermits * stableInterval / 2
+ long warmupMillis = (long) ((1 + coldFactor) * warmupPermits / (2.0 * qps) * 1000.0);
+ RateLimiter rateLimiter = RateLimiter.create(
+ stopwatch, qps, warmupMillis, MILLISECONDS, coldFactor);
+ assertEquals(warmupMillis, measureTotalTimeMillis(rateLimiter, warmupPermits, random));
+ }
}
}
}
@@ -411,7 +496,8 @@ public class RateLimiterTest extends TestCase {
public void testNulls() {
NullPointerTester tester = new NullPointerTester()
.setDefault(SleepingStopwatch.class, stopwatch)
- .setDefault(int.class, 1);
+ .setDefault(int.class, 1)
+ .setDefault(double.class, 1.0d);
tester.testStaticMethods(RateLimiter.class, Visibility.PACKAGE);
tester.testInstanceMethods(RateLimiter.create(stopwatch, 5.0), Visibility.PACKAGE);
}
@@ -451,7 +537,7 @@ public class RateLimiterTest extends TestCase {
void sleepMicros(String caption, long micros) {
instant += MICROSECONDS.toNanos(micros);
- events.add(caption + String.format("%3.2f", (micros / 1000000.0)));
+ events.add(caption + String.format(Locale.ROOT, "%3.2f", (micros / 1000000.0)));
}
@Override
@@ -473,16 +559,29 @@ public class RateLimiterTest extends TestCase {
}
}
- public void testMocking() throws Exception {
- RateLimiter mockito = Mockito.mock(RateLimiter.class);
- RateLimiter easyMock = EasyMock.createNiceMock(RateLimiter.class);
- EasyMock.replay(easyMock);
+ /*
+ * Note: Mockito appears to lose its ability to Mock doGetRate as of Android 21. If we start
+ * testing with that version or newer, we'll need to suppress this test (or see if Mockito can be
+ * changed to support this).
+ */
+ public void testMockingMockito() throws Exception {
+ RateLimiter mock = Mockito.mock(RateLimiter.class);
+ doTestMocking(mock);
+ }
+
+ @SuppressUnderAndroid // EasyMock Class Extension doesn't appear to work on Android.
+ public void testMockingEasyMock() throws Exception {
+ RateLimiter mock = EasyMock.createNiceMock(RateLimiter.class);
+ EasyMock.replay(mock);
+ doTestMocking(mock);
+ }
+
+ private static void doTestMocking(RateLimiter mock) throws Exception {
for (Method method : RateLimiter.class.getMethods()) {
if (!isStatic(method.getModifiers())
&& !NOT_WORKING_ON_MOCKS.contains(method.getName())
&& !method.getDeclaringClass().equals(Object.class)) {
- method.invoke(mockito, arbitraryParameters(method));
- method.invoke(easyMock, arbitraryParameters(method));
+ method.invoke(mock, arbitraryParameters(method));
}
}
}
@@ -497,7 +596,7 @@ public class RateLimiterTest extends TestCase {
}
private static final ImmutableSet<String> NOT_WORKING_ON_MOCKS =
- ImmutableSet.of("latestPermitAgeSec", "setRate");
+ ImmutableSet.of("latestPermitAgeSec", "setRate", "getAvailablePermits");
// We would use ArbitraryInstances, but it returns 0, invalid for many RateLimiter methods.
private static final ImmutableClassToInstanceMap<Object> PARAMETER_VALUES =
diff --git a/guava-tests/test/com/google/common/util/concurrent/SerializingExecutorTest.java b/guava-tests/test/com/google/common/util/concurrent/SerializingExecutorTest.java
index f055fe4..97fe727 100644
--- a/guava-tests/test/com/google/common/util/concurrent/SerializingExecutorTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/SerializingExecutorTest.java
@@ -54,6 +54,11 @@ public class SerializingExecutorTest extends TestCase {
tasks.remove().run();
}
+ void runAll() {
+ while (hasNext()) {
+ runNext();
+ }
+ }
}
private FakeExecutor fakePool;
private SerializingExecutor e;
@@ -78,28 +83,80 @@ public class SerializingExecutorTest extends TestCase {
@Override
public void run() {
totalCalls.incrementAndGet();
+ // Make sure that no other tasks are scheduled to run while this is running.
+ assertFalse(fakePool.hasNext());
}
};
assertFalse(fakePool.hasNext());
e.execute(intCounter);
+ // A task should have been scheduled
assertTrue(fakePool.hasNext());
e.execute(intCounter);
+ // Our executor hasn't run any tasks yet.
assertEquals(0, totalCalls.get());
- fakePool.runNext(); // run just 1 sub task...
+ fakePool.runAll();
assertEquals(2, totalCalls.get());
+ // Queue is empty so no runner should be scheduled.
assertFalse(fakePool.hasNext());
// Check that execute can be safely repeated
e.execute(intCounter);
e.execute(intCounter);
e.execute(intCounter);
+ // No change yet.
assertEquals(2, totalCalls.get());
- fakePool.runNext();
+ fakePool.runAll();
assertEquals(5, totalCalls.get());
assertFalse(fakePool.hasNext());
}
+ public void testSuspend() {
+ final AtomicInteger totalCalls = new AtomicInteger();
+ Runnable suspender = new Runnable() {
+ @Override
+ public void run() {
+ totalCalls.incrementAndGet();
+ // Suspend the queue so no other calls run.
+ e.suspend();
+ }
+ };
+
+ assertFalse(fakePool.hasNext());
+ e.execute(suspender);
+ // A task should have been scheduled
+ assertTrue(fakePool.hasNext());
+ e.execute(suspender);
+ fakePool.runAll();
+ // Only the first call that was already scheduled before suspension should have run.
+ assertEquals(1, totalCalls.get());
+ // Queue is suspended so no runner should be scheduled.
+ assertFalse(fakePool.hasNext());
+
+ e.execute(suspender);
+ // Queue is suspended so no runner should be scheduled.
+ assertFalse(fakePool.hasNext());
+ e.resume();
+ // A task should have been scheduled
+ assertTrue(fakePool.hasNext());
+ fakePool.runAll();
+ // Another call should have been run, but that suspended the queue again.
+ assertEquals(2, totalCalls.get());
+ assertFalse(fakePool.hasNext());
+
+ // Suspend the queue from here as well, making the count two.
+ e.suspend();
+ e.resume();
+ // Queue is still suspended, with count one, so no runner should be scheduled.
+ assertFalse(fakePool.hasNext());
+ e.resume();
+ // A task should have been scheduled
+ assertTrue(fakePool.hasNext());
+ fakePool.runAll();
+ // Another call should have been run, but that suspended the queue again.
+ assertEquals(3, totalCalls.get());
+ }
+
public void testOrdering() {
final List<Integer> callOrder = Lists.newArrayList();
@@ -119,12 +176,36 @@ public class SerializingExecutorTest extends TestCase {
e.execute(new FakeOp(0));
e.execute(new FakeOp(1));
e.execute(new FakeOp(2));
- fakePool.runNext();
+ fakePool.runAll();
+
+ assertEquals(ImmutableList.of(0, 1, 2), callOrder);
+ }
+
+ public void testPrependContinuation() {
+ final List<Integer> callOrder = Lists.newArrayList();
+
+ class FakeOp implements Runnable {
+ final int op;
+
+ FakeOp(int op) {
+ this.op = op;
+ }
+
+ @Override
+ public void run() {
+ callOrder.add(op);
+ }
+ }
+
+ e.execute(new FakeOp(1));
+ e.execute(new FakeOp(2));
+ e.executeFirst(new FakeOp(0));
+ fakePool.runAll();
assertEquals(ImmutableList.of(0, 1, 2), callOrder);
}
- public void testExceptions() {
+ public void testRuntimeException_doesNotStopExecution() {
final AtomicInteger numCalls = new AtomicInteger();
@@ -138,9 +219,30 @@ public class SerializingExecutorTest extends TestCase {
e.execute(runMe);
e.execute(runMe);
- fakePool.runNext();
+ fakePool.runAll();
+
+ assertEquals(2, numCalls.get());
+ }
+
+ public void testInterrupt_doesNotStopExecution() {
+
+ final AtomicInteger numCalls = new AtomicInteger();
+
+ Runnable runMe = new Runnable() {
+ @Override
+ public void run() {
+ numCalls.incrementAndGet();
+ }
+ };
+
+ Thread.currentThread().interrupt();
+
+ e.execute(runMe);
+ e.execute(runMe);
+ fakePool.runAll();
assertEquals(2, numCalls.get());
+ assertTrue(Thread.interrupted());
}
public void testDelegateRejection() {
diff --git a/guava-tests/test/com/google/common/util/concurrent/ServiceManagerTest.java b/guava-tests/test/com/google/common/util/concurrent/ServiceManagerTest.java
index 302b7d1..9fecf0a 100644
--- a/guava-tests/test/com/google/common/util/concurrent/ServiceManagerTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/ServiceManagerTest.java
@@ -24,6 +24,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.testing.NullPointerTester;
import com.google.common.testing.TestLogHandler;
+import com.google.common.util.concurrent.Service.State;
import com.google.common.util.concurrent.ServiceManager.Listener;
import junit.framework.TestCase;
@@ -91,20 +92,20 @@ public class ServiceManagerTest extends TestCase {
private static class FailStartService extends NoOpService {
@Override protected void doStart() {
- notifyFailed(new IllegalStateException("failed"));
+ notifyFailed(new IllegalStateException("start failure"));
}
}
private static class FailRunService extends NoOpService {
@Override protected void doStart() {
super.doStart();
- notifyFailed(new IllegalStateException("failed"));
+ notifyFailed(new IllegalStateException("run failure"));
}
}
private static class FailStopService extends NoOpService {
@Override protected void doStop() {
- notifyFailed(new IllegalStateException("failed"));
+ notifyFailed(new IllegalStateException("stop failure"));
}
}
@@ -115,8 +116,10 @@ public class ServiceManagerTest extends TestCase {
serviceManager.startAsync().awaitHealthy();
ImmutableMap<Service, Long> startupTimes = serviceManager.startupTimes();
assertEquals(2, startupTimes.size());
- assertThat(startupTimes.get(a)).isInclusivelyInRange(150, Long.MAX_VALUE);
- assertThat(startupTimes.get(b)).isInclusivelyInRange(353, Long.MAX_VALUE);
+ // TODO(kak): Use assertThat(startupTimes.get(a)).isAtLeast(150);
+ assertTrue(startupTimes.get(a) >= 150);
+ // TODO(kak): Use assertThat(startupTimes.get(b)).isAtLeast(353);
+ assertTrue(startupTimes.get(b) >= 353);
}
public void testServiceStartupTimes_selfStartingServices() {
@@ -141,7 +144,8 @@ public class ServiceManagerTest extends TestCase {
serviceManager.startAsync().awaitHealthy();
ImmutableMap<Service, Long> startupTimes = serviceManager.startupTimes();
assertEquals(2, startupTimes.size());
- assertThat(startupTimes.get(a)).isInclusivelyInRange(150, Long.MAX_VALUE);
+ // TODO(kak): Use assertThat(startupTimes.get(a)).isAtLeast(150);
+ assertTrue(startupTimes.get(a) >= 150);
// Service b startup takes at least 353 millis, but starting the timer is delayed by at least
// 150 milliseconds. so in a perfect world the timing would be 353-150=203ms, but since either
// of our sleep calls can be arbitrarily delayed we should just assert that there is a time
@@ -243,8 +247,8 @@ public class ServiceManagerTest extends TestCase {
Service b = new FailStartService();
ServiceManager manager = new ServiceManager(asList(a, b));
String toString = manager.toString();
- assertTrue(toString.contains("NoOpService"));
- assertTrue(toString.contains("FailStartService"));
+ assertThat(toString).contains("NoOpService");
+ assertThat(toString).contains("FailStartService");
}
public void testTimeouts() throws Exception {
@@ -363,7 +367,7 @@ public class ServiceManagerTest extends TestCase {
}
};
for (LogRecord record : logHandler.getStoredLogRecords()) {
- assertFalse(logFormatter.format(record).contains("NoOpService"));
+ assertThat(logFormatter.format(record)).doesNotContain("NoOpService");
}
}
@@ -498,7 +502,7 @@ public class ServiceManagerTest extends TestCase {
new ServiceManager(Arrays.asList(service1, service2));
fail();
} catch (IllegalArgumentException expected) {
- assertTrue(expected.getMessage().contains("started transitioning asynchronously"));
+ assertThat(expected.getMessage()).contains("started transitioning asynchronously");
}
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/ServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/ServiceTest.java
index e8ff37f..d24fa8a 100644
--- a/guava-tests/test/com/google/common/util/concurrent/ServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/ServiceTest.java
@@ -25,6 +25,8 @@ import static com.google.common.util.concurrent.Service.State.TERMINATED;
import junit.framework.TestCase;
+import java.util.Locale;
+
/**
* Unit tests for {@link Service}
*/
@@ -49,7 +51,7 @@ public class ServiceTest extends TestCase {
private static <T extends Comparable<? super T>> void assertLessThan(T a, T b) {
if (a.compareTo(b) >= 0) {
- fail(String.format("Expected %s to be less than %s", a, b));
+ fail(String.format(Locale.ROOT, "Expected %s to be less than %s", a, b));
}
}
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/SettableFutureTest.java b/guava-tests/test/com/google/common/util/concurrent/SettableFutureTest.java
index 47f71c0..f3ea784 100644
--- a/guava-tests/test/com/google/common/util/concurrent/SettableFutureTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/SettableFutureTest.java
@@ -18,6 +18,8 @@ package com.google.common.util.concurrent;
import junit.framework.TestCase;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -72,4 +74,153 @@ public class SettableFutureTest extends TestCase {
assertTrue(future.cancel(true));
tester.testCancelledFuture();
}
+
+ /** Tests the initial state of the future. */
+ public void testCreate() throws Exception {
+ SettableFuture<Integer> future = SettableFuture.create();
+ assertFalse(future.isDone());
+ assertFalse(future.isCancelled());
+ }
+
+ public void testSetValue_simpleThreaded() throws Exception {
+ SettableFuture<Integer> future = SettableFuture.create();
+ assertTrue(future.set(42));
+ // Later attempts to set the future should return false.
+ assertFalse(future.set(23));
+ assertFalse(future.setException(new Exception("bar")));
+ assertFalse(future.setFuture(SettableFuture.<Integer>create()));
+ // Check that the future has been set properly.
+ assertTrue(future.isDone());
+ assertFalse(future.isCancelled());
+ assertEquals(42, (int) future.get());
+ }
+
+ public void testSetException() throws Exception {
+ SettableFuture<Object> future = SettableFuture.create();
+ Exception e = new Exception("foobarbaz");
+ assertTrue(future.setException(e));
+ // Later attempts to set the future should return false.
+ assertFalse(future.set(23));
+ assertFalse(future.setException(new Exception("quux")));
+ assertFalse(future.setFuture(SettableFuture.create()));
+ // Check that the future has been set properly.
+ assertTrue(future.isDone());
+ assertFalse(future.isCancelled());
+ try {
+ future.get();
+ fail("Expected ExecutionException");
+ } catch (ExecutionException ee) {
+ assertSame(e, ee.getCause());
+ }
+ }
+
+ public void testSetFuture() throws Exception {
+ SettableFuture<String> future = SettableFuture.create();
+ SettableFuture<String> nested = SettableFuture.create();
+ assertTrue(future.setFuture(nested));
+ // Later attempts to set the future should return false.
+ assertFalse(future.set("x"));
+ assertFalse(future.setException(new Exception("bar")));
+ assertFalse(future.setFuture(SettableFuture.<String>create()));
+ // Check that the future has been set properly.
+ assertFalse(future.isDone());
+ assertFalse(future.isCancelled());
+ try {
+ future.get(0, TimeUnit.MILLISECONDS);
+ fail("Expected TimeoutException");
+ } catch (TimeoutException expected) { /* expected */ }
+ nested.set("foo");
+ assertTrue(future.isDone());
+ assertFalse(future.isCancelled());
+ assertEquals("foo", future.get());
+ }
+
+ private static class Foo {}
+ private static class FooChild extends Foo {}
+
+ public void testSetFuture_genericsHierarchy() throws Exception {
+ SettableFuture<Foo> future = SettableFuture.create();
+ SettableFuture<FooChild> nested = SettableFuture.create();
+ assertTrue(future.setFuture(nested));
+ // Later attempts to set the future should return false.
+ assertFalse(future.set(new Foo()));
+ assertFalse(future.setException(new Exception("bar")));
+ assertFalse(future.setFuture(SettableFuture.<Foo>create()));
+ // Check that the future has been set properly.
+ assertFalse(future.isDone());
+ assertFalse(future.isCancelled());
+ try {
+ future.get(0, TimeUnit.MILLISECONDS);
+ fail("Expected TimeoutException");
+ } catch (TimeoutException expected) { /* expected */ }
+ FooChild value = new FooChild();
+ nested.set(value);
+ assertTrue(future.isDone());
+ assertFalse(future.isCancelled());
+ assertSame(value, future.get());
+ }
+
+ public void testCancel_innerCancelsAsync() throws Exception {
+ SettableFuture<Object> async = SettableFuture.create();
+ SettableFuture<Object> inner = SettableFuture.create();
+ async.setFuture(inner);
+ inner.cancel(true);
+ assertTrue(async.isCancelled());
+ try {
+ async.get();
+ fail("Expected CancellationException");
+ } catch (CancellationException expected) { /* expected */ }
+ }
+
+ public void testCancel_resultCancelsInner_interrupted() throws Exception {
+ SettableFuture<Object> async = SettableFuture.create();
+ SettableFuture<Object> inner = SettableFuture.create();
+ async.setFuture(inner);
+ async.cancel(true);
+ assertTrue(inner.isCancelled());
+ assertTrue(inner.wasInterrupted());
+ try {
+ inner.get();
+ fail("Expected CancellationException");
+ } catch (CancellationException expected) { /* expected */ }
+ }
+
+ public void testCancel_resultCancelsInner() throws Exception {
+ SettableFuture<Object> async = SettableFuture.create();
+ SettableFuture<Object> inner = SettableFuture.create();
+ async.setFuture(inner);
+ async.cancel(false);
+ assertTrue(inner.isCancelled());
+ assertFalse(inner.wasInterrupted());
+ try {
+ inner.get();
+ fail("Expected CancellationException");
+ } catch (CancellationException expected) { /* expected */ }
+ }
+
+ public void testCancel_beforeSet() throws Exception {
+ SettableFuture<Object> async = SettableFuture.create();
+ async.cancel(true);
+ assertFalse(async.set(42));
+ }
+
+ public void testCancel_multipleBeforeSetFuture_noInterruptFirst() throws Exception {
+ SettableFuture<Object> async = SettableFuture.create();
+ async.cancel(false);
+ async.cancel(true);
+ SettableFuture<Object> inner = SettableFuture.create();
+ assertFalse(async.setFuture(inner));
+ assertTrue(inner.isCancelled());
+ assertFalse(inner.wasInterrupted());
+ }
+
+ public void testCancel_multipleBeforeSetFuture_interruptFirst() throws Exception {
+ SettableFuture<Object> async = SettableFuture.create();
+ async.cancel(true);
+ async.cancel(false);
+ SettableFuture<Object> inner = SettableFuture.create();
+ assertFalse(async.setFuture(inner));
+ assertTrue(inner.isCancelled());
+ assertTrue(inner.wasInterrupted());
+ }
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/SupplementalMonitorTest.java b/guava-tests/test/com/google/common/util/concurrent/SupplementalMonitorTest.java
new file mode 100644
index 0000000..252e219
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/SupplementalMonitorTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.util.concurrent.GeneratedMonitorTest.startThread;
+import static com.google.common.util.concurrent.Uninterruptibles.joinUninterruptibly;
+
+import com.google.common.util.concurrent.GeneratedMonitorTest.FlagGuard;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Supplemental tests for {@link Monitor}.
+ *
+ * <p>This test class contains various test cases that don't fit into the test case generation in
+ * {@link GeneratedMonitorTest}.
+ *
+ * @author Justin T. Sampson
+ */
+
+public class SupplementalMonitorTest extends TestCase {
+
+ public void testLeaveWithoutEnterThrowsIMSE() {
+ Monitor monitor = new Monitor();
+ try {
+ monitor.leave();
+ fail("expected IllegalMonitorStateException");
+ } catch (IllegalMonitorStateException e) {
+ // expected
+ }
+ }
+
+ public void testGetWaitQueueLengthWithWrongMonitorThrowsIMSE() {
+ Monitor monitor1 = new Monitor();
+ Monitor monitor2 = new Monitor();
+ FlagGuard guard = new FlagGuard(monitor2);
+ try {
+ monitor1.getWaitQueueLength(guard);
+ fail("expected IllegalMonitorStateException");
+ } catch (IllegalMonitorStateException e) {
+ // expected
+ }
+ }
+
+ public void testHasWaitersWithWrongMonitorThrowsIMSE() {
+ Monitor monitor1 = new Monitor();
+ Monitor monitor2 = new Monitor();
+ FlagGuard guard = new FlagGuard(monitor2);
+ try {
+ monitor1.hasWaiters(guard);
+ fail("expected IllegalMonitorStateException");
+ } catch (IllegalMonitorStateException e) {
+ // expected
+ }
+ }
+
+ public void testNullMonitorInGuardConstructorThrowsNPE() {
+ try {
+ new FlagGuard(null);
+ fail("expected NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testIsFair() {
+ assertTrue(new Monitor(true).isFair());
+ assertFalse(new Monitor(false).isFair());
+ }
+
+ public void testOccupiedMethods() {
+ Monitor monitor = new Monitor();
+ verifyOccupiedMethodsInCurrentThread(monitor, false, false, 0);
+ verifyOccupiedMethodsInAnotherThread(monitor, false, false, 0);
+ monitor.enter();
+ try {
+ verifyOccupiedMethodsInCurrentThread(monitor, true, true, 1);
+ verifyOccupiedMethodsInAnotherThread(monitor, true, false, 0);
+ monitor.enter();
+ try {
+ verifyOccupiedMethodsInCurrentThread(monitor, true, true, 2);
+ verifyOccupiedMethodsInAnotherThread(monitor, true, false, 0);
+ } finally {
+ monitor.leave();
+ }
+ verifyOccupiedMethodsInCurrentThread(monitor, true, true, 1);
+ verifyOccupiedMethodsInAnotherThread(monitor, true, false, 0);
+ } finally {
+ monitor.leave();
+ }
+ verifyOccupiedMethodsInCurrentThread(monitor, false, false, 0);
+ verifyOccupiedMethodsInAnotherThread(monitor, false, false, 0);
+ }
+
+ private static void verifyOccupiedMethodsInCurrentThread(Monitor monitor,
+ boolean expectedIsOccupied, boolean expectedIsOccupiedByCurrentThread,
+ int expectedOccupiedDepth) {
+ assertEquals(expectedIsOccupied, monitor.isOccupied());
+ assertEquals(expectedIsOccupiedByCurrentThread, monitor.isOccupiedByCurrentThread());
+ assertEquals(expectedOccupiedDepth, monitor.getOccupiedDepth());
+ }
+
+ private static void verifyOccupiedMethodsInAnotherThread(final Monitor monitor,
+ boolean expectedIsOccupied, boolean expectedIsOccupiedByCurrentThread,
+ int expectedOccupiedDepth) {
+ final AtomicBoolean actualIsOccupied = new AtomicBoolean();
+ final AtomicBoolean actualIsOccupiedByCurrentThread = new AtomicBoolean();
+ final AtomicInteger actualOccupiedDepth = new AtomicInteger();
+ final AtomicReference<Throwable> thrown = new AtomicReference<Throwable>();
+ joinUninterruptibly(startThread(new Runnable() {
+ @Override public void run() {
+ try {
+ actualIsOccupied.set(monitor.isOccupied());
+ actualIsOccupiedByCurrentThread.set(monitor.isOccupiedByCurrentThread());
+ actualOccupiedDepth.set(monitor.getOccupiedDepth());
+ } catch (Throwable t) {
+ thrown.set(t);
+ }
+ }
+ }));
+ assertNull(thrown.get());
+ assertEquals(expectedIsOccupied, actualIsOccupied.get());
+ assertEquals(expectedIsOccupiedByCurrentThread, actualIsOccupiedByCurrentThread.get());
+ assertEquals(expectedOccupiedDepth, actualOccupiedDepth.get());
+ }
+
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/SuppressUnderAndroid.java b/guava-tests/test/com/google/common/util/concurrent/SuppressUnderAndroid.java
new file mode 100644
index 0000000..69dcaf7
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/SuppressUnderAndroid.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Signifies that a test should not be run under Android. This annotation is respected only by our
+ * Google-internal Android suite generators. Note that those generators also suppress any test
+ * annotated with MediumTest or LargeTest.
+ *
+ * <p>For more discussion, see {@linkplain com.google.common.base.SuppressUnderAndroid the
+ * documentation on another copy of this annotation}.
+ */
+ at Retention(CLASS)
+ at Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+ at GwtCompatible
+ at interface SuppressUnderAndroid {}
diff --git a/guava-tests/test/com/google/common/util/concurrent/TestPlatform.java b/guava-tests/test/com/google/common/util/concurrent/TestPlatform.java
new file mode 100644
index 0000000..0db25b6
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/TestPlatform.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.util.concurrent.FuturesTest.failureWithCause;
+import static com.google.common.util.concurrent.FuturesTest.pseudoTimedGetUninterruptibly;
+import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.fail;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Methods factored out so that they can be emulated differently in GWT.
+ */
+ at GwtCompatible(emulated = true)
+final class TestPlatform {
+ static void verifyGetOnPendingFuture(Future<?> future) {
+ checkNotNull(future);
+ try {
+ pseudoTimedGetUninterruptibly(future, 10, MILLISECONDS);
+ fail();
+ } catch (TimeoutException expected) {
+ } catch (ExecutionException e) {
+ throw failureWithCause(e, "");
+ }
+ }
+
+ static void verifyTimedGetOnPendingFuture(Future<?> future) {
+ try {
+ getUninterruptibly(future, 0, SECONDS);
+ fail();
+ } catch (TimeoutException expected) {
+ } catch (ExecutionException e) {
+ throw failureWithCause(e, "");
+ }
+ }
+
+ static void verifyThreadWasNotInterrupted() {
+ assertFalse(Thread.currentThread().isInterrupted());
+ }
+
+ static void clearInterrupt() {
+ Thread.interrupted();
+ }
+
+ private TestPlatform() {}
+}
diff --git a/guava-tests/test/com/google/common/util/concurrent/ThreadFactoryBuilderTest.java b/guava-tests/test/com/google/common/util/concurrent/ThreadFactoryBuilderTest.java
index 3582415..18cb51c 100644
--- a/guava-tests/test/com/google/common/util/concurrent/ThreadFactoryBuilderTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/ThreadFactoryBuilderTest.java
@@ -23,6 +23,7 @@ import com.google.common.testing.NullPointerTester;
import junit.framework.TestCase;
import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.Locale;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
@@ -90,14 +91,14 @@ public class ThreadFactoryBuilderTest extends TestCase {
}
private static void checkThreadPoolName(Thread thread, int threadId) {
- assertTrue(thread.getName().matches("^pool-\\d+-thread-" + threadId + "$"));
+ assertThat(thread.getName()).matches("^pool-\\d+-thread-" + threadId + "$");
}
public void testNameFormatWithPercentS_custom() {
String format = "super-duper-thread-%s";
ThreadFactory factory = builder.setNameFormat(format).build();
for (int i = 0; i < 11; i++) {
- assertEquals(String.format(format, i),
+ assertEquals(rootLocaleFormat(format, i),
factory.newThread(monitoredRunnable).getName());
}
}
@@ -106,7 +107,7 @@ public class ThreadFactoryBuilderTest extends TestCase {
String format = "super-duper-thread-%d";
ThreadFactory factory = builder.setNameFormat(format).build();
for (int i = 0; i < 11; i++) {
- assertEquals(String.format(format, i),
+ assertEquals(rootLocaleFormat(format, i),
factory.newThread(monitoredRunnable).getName());
}
}
@@ -212,4 +213,8 @@ public class ThreadFactoryBuilderTest extends TestCase {
npTester.testAllPublicStaticMethods(ThreadFactoryBuilder.class);
npTester.testAllPublicInstanceMethods(builder);
}
+
+ private static String rootLocaleFormat(String format, Object... args) {
+ return String.format(Locale.ROOT, format, args);
+ }
}
diff --git a/guava/src/com/google/common/collect/FilteredSetMultimap.java b/guava-tests/test/com/google/common/util/concurrent/TrustedInputFutureTest.java
similarity index 54%
copy from guava/src/com/google/common/collect/FilteredSetMultimap.java
copy to guava-tests/test/com/google/common/util/concurrent/TrustedInputFutureTest.java
index 6b73281..105a7cf 100644
--- a/guava/src/com/google/common/collect/FilteredSetMultimap.java
+++ b/guava-tests/test/com/google/common/util/concurrent/TrustedInputFutureTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,21 @@
* limitations under the License.
*/
-package com.google.common.collect;
+package com.google.common.util.concurrent;
import com.google.common.annotations.GwtCompatible;
+import com.google.common.util.concurrent.AbstractFuture.TrustedFuture;
/**
- * A supertype for filtered {@link SetMultimap} implementations.
- *
- * @author Louis Wasserman
+ * Tests for {@link AbstractFuture} that use a {@link TrustedFuture} for
+ * {@link AbstractFuture#setFuture} calls.
*/
@GwtCompatible
-interface FilteredSetMultimap<K, V> extends FilteredMultimap<K, V>, SetMultimap<K, V> {
+public class TrustedInputFutureTest extends AbstractAbstractFutureTest {
@Override
- SetMultimap<K, V> unfiltered();
+ AbstractFuture<Integer> newDelegate() {
+ AbstractFuture<Integer> future = new TrustedFuture<Integer>() {};
+ assertTrue(future instanceof TrustedFuture); // sanity check
+ return future;
+ }
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/TrustedListenableFutureTaskTest.java b/guava-tests/test/com/google/common/util/concurrent/TrustedListenableFutureTaskTest.java
new file mode 100644
index 0000000..6fdf059
--- /dev/null
+++ b/guava-tests/test/com/google/common/util/concurrent/TrustedListenableFutureTaskTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.util.concurrent.Callables.returning;
+import static com.google.common.util.concurrent.TestPlatform.verifyThreadWasNotInterrupted;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Test case for {@link TrustedListenableFutureTask}.
+ */
+ at GwtCompatible(emulated = true)
+public class TrustedListenableFutureTaskTest extends TestCase {
+
+ public void testSuccessful() throws Exception {
+ TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(returning(2));
+ assertFalse(task.isDone());
+ task.run();
+ assertTrue(task.isDone());
+ assertFalse(task.isCancelled());
+ assertEquals(2, task.get().intValue());
+ }
+
+ public void testCancelled() throws Exception {
+ TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(returning(2));
+ assertFalse(task.isDone());
+ task.cancel(false);
+ assertTrue(task.isDone());
+ assertTrue(task.isCancelled());
+ assertFalse(task.wasInterrupted());
+ try {
+ task.get();
+ fail();
+ } catch (CancellationException expected) {
+ }
+ verifyThreadWasNotInterrupted();
+ }
+
+ public void testFailed() throws Exception {
+ final Exception e = new Exception();
+ TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(
+ new Callable<Integer>() {
+ @Override public Integer call() throws Exception {
+ throw e;
+ }
+ });
+ task.run();
+ assertTrue(task.isDone());
+ assertFalse(task.isCancelled());
+ try {
+ task.get();
+ fail();
+ } catch (ExecutionException executionException) {
+ assertEquals(e, executionException.getCause());
+ }
+ }
+
+ @GwtIncompatible("blocking wait")
+
+ public void testCancel_interrupted() throws Exception {
+ final AtomicBoolean interruptedExceptionThrown = new AtomicBoolean();
+ final CountDownLatch enterLatch = new CountDownLatch(1);
+ final CountDownLatch exitLatch = new CountDownLatch(1);
+ final TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(
+ new Callable<Integer>() {
+ @Override public Integer call() throws Exception {
+ enterLatch.countDown();
+ try {
+ new CountDownLatch(1).await(); // wait forever
+ throw new AssertionError();
+ } catch (InterruptedException e) {
+ interruptedExceptionThrown.set(true);
+ throw e;
+ } finally {
+ }
+ }
+ });
+ assertFalse(task.isDone());
+ Thread thread = new Thread(new Runnable() {
+ @Override public void run() {
+ try {
+ task.run();
+ } finally {
+ exitLatch.countDown();
+ }
+ }
+ });
+ thread.start();
+ enterLatch.await();
+ assertFalse(task.isDone());
+ task.cancel(true);
+ assertTrue(task.isDone());
+ assertTrue(task.isCancelled());
+ assertTrue(task.wasInterrupted());
+ try {
+ task.get();
+ fail();
+ } catch (CancellationException expected) {
+ }
+ exitLatch.await();
+ assertTrue(interruptedExceptionThrown.get());
+ }
+
+ @GwtIncompatible("blocking wait")
+
+ public void testRunIdempotency() throws Exception {
+ final int numThreads = 10;
+ final ExecutorService executor = Executors.newFixedThreadPool(numThreads);
+ for (int i = 0; i < 1000; i++) {
+ final AtomicInteger counter = new AtomicInteger();
+ final TrustedListenableFutureTask<Integer> task = TrustedListenableFutureTask.create(
+ new Callable<Integer>() {
+ @Override public Integer call() {
+ return counter.incrementAndGet();
+ }
+ });
+ final CyclicBarrier barrier = new CyclicBarrier(numThreads + 1);
+ Runnable wrapper = new Runnable() {
+ @Override public void run() {
+ awaitUnchecked(barrier);
+ task.run();
+ awaitUnchecked(barrier);
+ }
+ };
+ for (int j = 0; j < 10; j++) {
+ executor.execute(wrapper);
+ }
+ barrier.await(); // release the threads!
+ barrier.await(); // wait for them all to complete
+ assertEquals(1, task.get().intValue());
+ assertEquals(1, counter.get());
+ }
+ executor.shutdown();
+ }
+
+ @GwtIncompatible("used only in GwtIncomaptible tests")
+ private int awaitUnchecked(CyclicBarrier barrier) {
+ try {
+ return barrier.await();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/guava/src/com/google/common/collect/FilteredSetMultimap.java b/guava-tests/test/com/google/common/util/concurrent/UntrustedInputFutureTest.java
similarity index 54%
copy from guava/src/com/google/common/collect/FilteredSetMultimap.java
copy to guava-tests/test/com/google/common/util/concurrent/UntrustedInputFutureTest.java
index 6b73281..a5505b1 100644
--- a/guava/src/com/google/common/collect/FilteredSetMultimap.java
+++ b/guava-tests/test/com/google/common/util/concurrent/UntrustedInputFutureTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,21 @@
* limitations under the License.
*/
-package com.google.common.collect;
+package com.google.common.util.concurrent;
import com.google.common.annotations.GwtCompatible;
+import com.google.common.util.concurrent.AbstractFuture.TrustedFuture;
/**
- * A supertype for filtered {@link SetMultimap} implementations.
- *
- * @author Louis Wasserman
+ * Tests for {@link AbstractFuture} that use a non-{@link TrustedFuture} for
+ * {@link AbstractFuture#setFuture} calls.
*/
@GwtCompatible
-interface FilteredSetMultimap<K, V> extends FilteredMultimap<K, V>, SetMultimap<K, V> {
+public class UntrustedInputFutureTest extends AbstractAbstractFutureTest {
@Override
- SetMultimap<K, V> unfiltered();
+ AbstractFuture<Integer> newDelegate() {
+ AbstractFuture<Integer> future = new AbstractFuture<Integer>() {};
+ assertFalse(future instanceof TrustedFuture); // sanity check
+ return future;
+ }
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/WrappingExecutorServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/WrappingExecutorServiceTest.java
index 900bd5d..cb6d723 100644
--- a/guava-tests/test/com/google/common/util/concurrent/WrappingExecutorServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/WrappingExecutorServiceTest.java
@@ -16,6 +16,7 @@
package com.google.common.util.concurrent;
+import static com.google.common.truth.Truth.assertThat;
import static com.google.common.util.concurrent.MoreExecutors.newDirectExecutorService;
import static com.google.common.util.concurrent.Runnables.doNothing;
@@ -271,28 +272,28 @@ public class WrappingExecutorServiceTest extends TestCase {
@Override
public <T> Future<T> submit(Callable<T> task) {
lastMethodCalled = "submit";
- assertTrue(task instanceof WrappedCallable);
+ assertThat(task).isInstanceOf(WrappedCallable.class);
return inline.submit(task);
}
@Override
public Future<?> submit(Runnable task) {
lastMethodCalled = "submit";
- assertTrue(task instanceof WrappedRunnable);
+ assertThat(task).isInstanceOf(WrappedRunnable.class);
return inline.submit(task);
}
@Override
public <T> Future<T> submit(Runnable task, T result) {
lastMethodCalled = "submit";
- assertTrue(task instanceof WrappedRunnable);
+ assertThat(task).isInstanceOf(WrappedRunnable.class);
return inline.submit(task, result);
}
@Override
public void execute(Runnable command) {
lastMethodCalled = "execute";
- assertTrue(command instanceof WrappedRunnable);
+ assertThat(command).isInstanceOf(WrappedRunnable.class);
inline.execute(command);
}
diff --git a/guava-tests/test/com/google/common/util/concurrent/WrappingScheduledExecutorServiceTest.java b/guava-tests/test/com/google/common/util/concurrent/WrappingScheduledExecutorServiceTest.java
index 9beadb4..24c35f0 100644
--- a/guava-tests/test/com/google/common/util/concurrent/WrappingScheduledExecutorServiceTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/WrappingScheduledExecutorServiceTest.java
@@ -16,6 +16,8 @@
package com.google.common.util.concurrent;
+import static com.google.common.truth.Truth.assertThat;
+
import junit.framework.TestCase;
import java.util.Collection;
@@ -122,26 +124,28 @@ public class WrappingScheduledExecutorServiceTest extends TestCase {
assertEquals(unit, lastUnit);
}
- @Override public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
- assertTrue(command instanceof WrappedRunnable);
+ @Override
+ public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
+ assertThat(command).isInstanceOf(WrappedRunnable.class);
lastMethodCalled = "scheduleRunnable";
lastDelay = delay;
lastUnit = unit;
return null;
}
- @Override public <V> ScheduledFuture<V> schedule(
- Callable<V> callable, long delay, TimeUnit unit) {
- assertTrue(callable instanceof WrappedCallable);
+ @Override
+ public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
+ assertThat(callable).isInstanceOf(WrappedCallable.class);
lastMethodCalled = "scheduleCallable";
lastDelay = delay;
lastUnit = unit;
return null;
}
- @Override public ScheduledFuture<?> scheduleAtFixedRate(
+ @Override
+ public ScheduledFuture<?> scheduleAtFixedRate(
Runnable command, long initialDelay, long period, TimeUnit unit) {
- assertTrue(command instanceof WrappedRunnable);
+ assertThat(command).isInstanceOf(WrappedRunnable.class);
lastMethodCalled = "scheduleAtFixedRate";
lastInitialDelay = initialDelay;
lastDelay = period;
@@ -149,9 +153,10 @@ public class WrappingScheduledExecutorServiceTest extends TestCase {
return null;
}
- @Override public ScheduledFuture<?> scheduleWithFixedDelay(
+ @Override
+ public ScheduledFuture<?> scheduleWithFixedDelay(
Runnable command, long initialDelay, long delay, TimeUnit unit) {
- assertTrue(command instanceof WrappedRunnable);
+ assertThat(command).isInstanceOf(WrappedRunnable.class);
lastMethodCalled = "scheduleWithFixedDelay";
lastInitialDelay = initialDelay;
lastDelay = delay;
diff --git a/guava-tests/test/com/google/common/xml/XmlEscapersTest.java b/guava-tests/test/com/google/common/xml/XmlEscapersTest.java
index 5052962..2f21e1c 100644
--- a/guava-tests/test/com/google/common/xml/XmlEscapersTest.java
+++ b/guava-tests/test/com/google/common/xml/XmlEscapersTest.java
@@ -55,7 +55,7 @@ public class XmlEscapersTest extends TestCase {
}
// Helper to assert common properties of xml escapers.
- private void assertBasicXmlEscaper(CharEscaper xmlEscaper,
+ static void assertBasicXmlEscaper(CharEscaper xmlEscaper,
boolean shouldEscapeQuotes, boolean shouldEscapeWhitespaceChars) {
// Simple examples (smoke tests)
assertEquals("xxx", xmlEscaper.escape("xxx"));
diff --git a/guava/pom.xml b/guava/pom.xml
index 4cf038a..eef6890 100644
--- a/guava/pom.xml
+++ b/guava/pom.xml
@@ -5,11 +5,11 @@
<parent>
<groupId>com.google.guava</groupId>
<artifactId>guava-parent</artifactId>
- <version>18.0</version>
+ <version>19.0</version>
</parent>
<artifactId>guava</artifactId>
- <name>Guava: Google Core Libraries for Java</name>
<packaging>bundle</packaging>
+ <name>Guava: Google Core Libraries for Java</name>
<description>
Guava is a suite of core and expanded libraries that include
utility classes, google's collections, io classes, and much
@@ -24,15 +24,32 @@
<artifactId>jsr305</artifactId>
<optional>true</optional><!-- needed only for annotations -->
</dependency>
+ <dependency>
+ <groupId>com.google.errorprone</groupId>
+ <artifactId>error_prone_annotations</artifactId>
+ <optional>true</optional><!-- needed only for annotations -->
+ </dependency>
+ <dependency>
+ <groupId>com.google.j2objc</groupId>
+ <artifactId>j2objc-annotations</artifactId>
+ <optional>true</optional><!-- needed only for annotations -->
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>animal-sniffer-annotations</artifactId>
+ <version>${animal.sniffer.version}</version>
+ <optional>true</optional><!-- needed only for annotations -->
+ </dependency>
+ <!-- TODO(cpovirk): does this comment belong on the <dependency> in <profiles>? -->
<!-- TODO(cpovirk): want this only for dependency plugin but seems not to work there? Maven runs without failure, but the resulting Javadoc is missing the hoped-for inherited text -->
</dependencies>
<build>
<plugins>
<plugin>
+ <extensions>true</extensions>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
- <extensions>true</extensions>
<executions>
<execution>
<id>bundle-manifest</id>
@@ -69,7 +86,6 @@
<goals><goal>unpack-dependencies</goal></goals>
<configuration>
<includeArtifactIds>srczip</includeArtifactIds>
- <overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/jdk-sources</outputDirectory>
<silent>false</silent>
</configuration>
@@ -107,21 +123,6 @@
<phase>site</phase>
<goals><goal>javadoc</goal></goals>
</execution>
- <execution>
- <id>generate-jdiff-site-report</id>
- <phase>site</phase>
- <goals><goal>javadoc</goal></goals>
- <configuration>
- <doclet>jdiff.JDiff</doclet>
- <docletPath>${project.basedir}/lib/jdiff.jar</docletPath>
- <additionalparam>
- -XDignore.symbol.file -apiname 'Guava ${project.version}'
- </additionalparam>
- <useStandardDocletOptions>false</useStandardDocletOptions>
- <reportOutputDirectory>${project.reporting.outputDirectory}</reportOutputDirectory>
- <destDir>jdiff</destDir>
- </configuration>
- </execution>
</executions>
</plugin>
</plugins>
@@ -145,5 +146,37 @@
</dependency>
</dependencies>
</profile>
+ <profile>
+ <id>jdk8</id>
+ <activation>
+ <jdk>[1.8,)</jdk>
+ </activation>
+ <!-- Disable doclint under JDK 8 -->
+ <!-- This is defined in guava-parent as well, but we need it here too because the
+ <additionalparam> from the maven-javadoc-plugin configuration above seems to
+ override the one from the parent pom. -->
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <additionalparam>-XDignore.symbol.file -Xdoclint:none</additionalparam>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <additionalparam>-XDignore.symbol.file -Xdoclint:none</additionalparam>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
</profiles>
</project>
diff --git a/guava/src/com/google/common/base/Absent.java b/guava/src/com/google/common/base/Absent.java
index 8b298b2..a607621 100644
--- a/guava/src/com/google/common/base/Absent.java
+++ b/guava/src/com/google/common/base/Absent.java
@@ -39,50 +39,62 @@ final class Absent<T> extends Optional<T> {
private Absent() {}
- @Override public boolean isPresent() {
+ @Override
+ public boolean isPresent() {
return false;
}
- @Override public T get() {
+ @Override
+ public T get() {
throw new IllegalStateException("Optional.get() cannot be called on an absent value");
}
- @Override public T or(T defaultValue) {
+ @Override
+ public T or(T defaultValue) {
return checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)");
}
@SuppressWarnings("unchecked") // safe covariant cast
- @Override public Optional<T> or(Optional<? extends T> secondChoice) {
+ @Override
+ public Optional<T> or(Optional<? extends T> secondChoice) {
return (Optional<T>) checkNotNull(secondChoice);
}
- @Override public T or(Supplier<? extends T> supplier) {
- return checkNotNull(supplier.get(),
- "use Optional.orNull() instead of a Supplier that returns null");
+ @Override
+ public T or(Supplier<? extends T> supplier) {
+ return checkNotNull(
+ supplier.get(), "use Optional.orNull() instead of a Supplier that returns null");
}
- @Override @Nullable public T orNull() {
+ @Override
+ @Nullable
+ public T orNull() {
return null;
}
- @Override public Set<T> asSet() {
+ @Override
+ public Set<T> asSet() {
return Collections.emptySet();
}
- @Override public <V> Optional<V> transform(Function<? super T, V> function) {
+ @Override
+ public <V> Optional<V> transform(Function<? super T, V> function) {
checkNotNull(function);
return Optional.absent();
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return object == this;
}
- @Override public int hashCode() {
- return 0x598df91c;
+ @Override
+ public int hashCode() {
+ return 0x79a31aac;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Optional.absent()";
}
diff --git a/guava/src/com/google/common/base/AbstractIterator.java b/guava/src/com/google/common/base/AbstractIterator.java
index d8b7257..7b29fea 100644
--- a/guava/src/com/google/common/base/AbstractIterator.java
+++ b/guava/src/com/google/common/base/AbstractIterator.java
@@ -34,7 +34,10 @@ abstract class AbstractIterator<T> implements Iterator<T> {
protected AbstractIterator() {}
private enum State {
- READY, NOT_READY, DONE, FAILED,
+ READY,
+ NOT_READY,
+ DONE,
+ FAILED,
}
private T next;
@@ -50,10 +53,10 @@ abstract class AbstractIterator<T> implements Iterator<T> {
public final boolean hasNext() {
checkState(state != State.FAILED);
switch (state) {
- case DONE:
- return false;
case READY:
return true;
+ case DONE:
+ return false;
default:
}
return tryToComputeNext();
@@ -80,7 +83,8 @@ abstract class AbstractIterator<T> implements Iterator<T> {
return result;
}
- @Override public final void remove() {
+ @Override
+ public final void remove() {
throw new UnsupportedOperationException();
}
}
diff --git a/guava/src/com/google/common/base/Ascii.java b/guava/src/com/google/common/base/Ascii.java
index 37f7ed6..9024290 100644
--- a/guava/src/com/google/common/base/Ascii.java
+++ b/guava/src/com/google/common/base/Ascii.java
@@ -41,6 +41,7 @@ import javax.annotation.CheckReturnValue;
* @author Gregory Kick
* @since 7.0
*/
+ at CheckReturnValue
@GwtCompatible
public final class Ascii {
@@ -580,7 +581,6 @@ public final class Ascii {
* @since 16.0
*/
@Beta
- @CheckReturnValue
public static String truncate(CharSequence seq, int maxLength, String truncationIndicator) {
checkNotNull(seq);
@@ -589,9 +589,11 @@ public final class Ascii {
// in this worst case, this allows a maxLength equal to the length of the truncationIndicator,
// meaning that a string will be truncated to just the truncation indicator itself
- checkArgument(truncationLength >= 0,
+ checkArgument(
+ truncationLength >= 0,
"maxLength (%s) must be >= length of the truncation indicator (%s)",
- maxLength, truncationIndicator.length());
+ maxLength,
+ truncationIndicator.length());
if (seq.length() <= maxLength) {
String string = seq.toString();
diff --git a/guava/src/com/google/common/base/CaseFormat.java b/guava/src/com/google/common/base/CaseFormat.java
index 0b4cb5c..c074de2 100644
--- a/guava/src/com/google/common/base/CaseFormat.java
+++ b/guava/src/com/google/common/base/CaseFormat.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -32,16 +33,20 @@ import javax.annotation.Nullable;
* @author Mike Bostock
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible
public enum CaseFormat {
/**
* Hyphenated variable naming convention, e.g., "lower-hyphen".
*/
LOWER_HYPHEN(CharMatcher.is('-'), "-") {
- @Override String normalizeWord(String word) {
+ @Override
+ String normalizeWord(String word) {
return Ascii.toLowerCase(word);
}
- @Override String convert(CaseFormat format, String s) {
+
+ @Override
+ String convert(CaseFormat format, String s) {
if (format == LOWER_UNDERSCORE) {
return s.replace('-', '_');
}
@@ -56,10 +61,13 @@ public enum CaseFormat {
* C++ variable naming convention, e.g., "lower_underscore".
*/
LOWER_UNDERSCORE(CharMatcher.is('_'), "_") {
- @Override String normalizeWord(String word) {
+ @Override
+ String normalizeWord(String word) {
return Ascii.toLowerCase(word);
}
- @Override String convert(CaseFormat format, String s) {
+
+ @Override
+ String convert(CaseFormat format, String s) {
if (format == LOWER_HYPHEN) {
return s.replace('_', '-');
}
@@ -74,7 +82,8 @@ public enum CaseFormat {
* Java variable naming convention, e.g., "lowerCamel".
*/
LOWER_CAMEL(CharMatcher.inRange('A', 'Z'), "") {
- @Override String normalizeWord(String word) {
+ @Override
+ String normalizeWord(String word) {
return firstCharOnlyToUpper(word);
}
},
@@ -83,7 +92,8 @@ public enum CaseFormat {
* Java and C++ class naming convention, e.g., "UpperCamel".
*/
UPPER_CAMEL(CharMatcher.inRange('A', 'Z'), "") {
- @Override String normalizeWord(String word) {
+ @Override
+ String normalizeWord(String word) {
return firstCharOnlyToUpper(word);
}
},
@@ -92,10 +102,13 @@ public enum CaseFormat {
* Java and C++ constant naming convention, e.g., "UPPER_UNDERSCORE".
*/
UPPER_UNDERSCORE(CharMatcher.is('_'), "_") {
- @Override String normalizeWord(String word) {
+ @Override
+ String normalizeWord(String word) {
return Ascii.toUpperCase(word);
}
- @Override String convert(CaseFormat format, String s) {
+
+ @Override
+ String convert(CaseFormat format, String s) {
if (format == LOWER_HYPHEN) {
return Ascii.toLowerCase(s.replace('_', '-'));
}
@@ -145,8 +158,8 @@ public enum CaseFormat {
i = j + wordSeparator.length();
}
return (i == 0)
- ? format.normalizeFirstWord(s)
- : out.append(format.normalizeWord(s.substring(i))).toString();
+ ? format.normalizeFirstWord(s)
+ : out.append(format.normalizeWord(s.substring(i))).toString();
}
/**
@@ -159,8 +172,8 @@ public enum CaseFormat {
return new StringConverter(this, targetFormat);
}
- private static final class StringConverter
- extends Converter<String, String> implements Serializable {
+ private static final class StringConverter extends Converter<String, String>
+ implements Serializable {
private final CaseFormat sourceFormat;
private final CaseFormat targetFormat;
@@ -170,30 +183,32 @@ public enum CaseFormat {
this.targetFormat = checkNotNull(targetFormat);
}
- @Override protected String doForward(String s) {
- // TODO(kevinb): remove null boilerplate (convert() will do it automatically)
- return s == null ? null : sourceFormat.to(targetFormat, s);
+ @Override
+ protected String doForward(String s) {
+ return sourceFormat.to(targetFormat, s);
}
- @Override protected String doBackward(String s) {
- // TODO(kevinb): remove null boilerplate (convert() will do it automatically)
- return s == null ? null : targetFormat.to(sourceFormat, s);
+ @Override
+ protected String doBackward(String s) {
+ return targetFormat.to(sourceFormat, s);
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object instanceof StringConverter) {
StringConverter that = (StringConverter) object;
- return sourceFormat.equals(that.sourceFormat)
- && targetFormat.equals(that.targetFormat);
+ return sourceFormat.equals(that.sourceFormat) && targetFormat.equals(that.targetFormat);
}
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return sourceFormat.hashCode() ^ targetFormat.hashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return sourceFormat + ".converterTo(" + targetFormat + ")";
}
diff --git a/guava/src/com/google/common/base/CharMatcher.java b/guava/src/com/google/common/base/CharMatcher.java
index 8a73530..7e732dd 100644
--- a/guava/src/com/google/common/base/CharMatcher.java
+++ b/guava/src/com/google/common/base/CharMatcher.java
@@ -18,10 +18,12 @@ package com.google.common.base;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkPositionIndex;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
+import com.google.common.annotations.VisibleForTesting;
import java.util.Arrays;
import java.util.BitSet;
@@ -42,11 +44,11 @@ import javax.annotation.CheckReturnValue;
* treats these just as two separate characters.
*
* <p>Example usages: <pre>
- * String trimmed = {@link #WHITESPACE WHITESPACE}.{@link #trimFrom trimFrom}(userInput);
- * if ({@link #ASCII ASCII}.{@link #matchesAllOf matchesAllOf}(s)) { ... }</pre>
+ * String trimmed = {@link #whitespace() whitespace()}.{@link #trimFrom trimFrom}(userInput);
+ * if ({@link #ascii() ascii()}.{@link #matchesAllOf matchesAllOf}(s)) { ... }</pre>
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/StringsExplained#CharMatcher">
+ * "https://github.com/google/guava/wiki/StringsExplained#charmatcher">
* {@code CharMatcher}</a>.
*
* @author Kevin Bourrillion
@@ -56,184 +58,144 @@ import javax.annotation.CheckReturnValue;
@GwtCompatible(emulated = true)
public abstract class CharMatcher implements Predicate<Character> {
- // Constants
+ // Constant matcher factory methods
+
/**
- * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
- * interpreted as a break between words for formatting purposes). See {@link #WHITESPACE} for a
- * discussion of that term.
+ * Matches any character.
*
- * @since 2.0
+ * @since 19.0 (since 1.0 as constant {@code ANY})
*/
- public static final CharMatcher BREAKING_WHITESPACE = new CharMatcher() {
- @Override
- public boolean matches(char c) {
- switch (c) {
- case '\t':
- case '\n':
- case '\013':
- case '\f':
- case '\r':
- case ' ':
- case '\u0085':
- case '\u1680':
- case '\u2028':
- case '\u2029':
- case '\u205f':
- case '\u3000':
- return true;
- case '\u2007':
- return false;
- default:
- return c >= '\u2000' && c <= '\u200a';
- }
- }
-
- @Override
- public String toString() {
- return "CharMatcher.BREAKING_WHITESPACE";
- }
- };
+ public static CharMatcher any() {
+ return Any.INSTANCE;
+ }
/**
- * Determines whether a character is ASCII, meaning that its code point is less than 128.
+ * Matches no characters.
+ *
+ * @since 19.0 (since 1.0 as constant {@code NONE})
*/
- public static final CharMatcher ASCII = inRange('\0', '\u007f', "CharMatcher.ASCII");
-
- private static class RangesMatcher extends CharMatcher {
- private final char[] rangeStarts;
- private final char[] rangeEnds;
-
- RangesMatcher(String description, char[] rangeStarts, char[] rangeEnds) {
- super(description);
- this.rangeStarts = rangeStarts;
- this.rangeEnds = rangeEnds;
- checkArgument(rangeStarts.length == rangeEnds.length);
- for (int i = 0; i < rangeStarts.length; i++) {
- checkArgument(rangeStarts[i] <= rangeEnds[i]);
- if (i + 1 < rangeStarts.length) {
- checkArgument(rangeEnds[i] < rangeStarts[i + 1]);
- }
- }
- }
+ public static CharMatcher none() {
+ return None.INSTANCE;
+ }
- @Override
- public boolean matches(char c) {
- int index = Arrays.binarySearch(rangeStarts, c);
- if (index >= 0) {
- return true;
- } else {
- index = ~index - 1;
- return index >= 0 && c <= rangeEnds[index];
- }
- }
+ /**
+ * Determines whether a character is whitespace according to the latest Unicode standard, as
+ * illustrated <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
+ * This is not the same definition used by other Java APIs. (See a <a
+ * href="http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">comparison of several
+ * definitions of "whitespace"</a>.)
+ *
+ * <p><b>Note:</b> as the Unicode definition evolves, we will modify this matcher to keep it up
+ * to date.
+ *
+ * @since 19.0 (since 1.0 as constant {@code WHITESPACE})
+ */
+ public static CharMatcher whitespace() {
+ return Whitespace.INSTANCE;
}
- // Must be in ascending order.
- private static final String ZEROES = "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66\u0be6"
- + "\u0c66\u0ce6\u0d66\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810\u1946\u19d0\u1b50\u1bb0"
- + "\u1c40\u1c50\ua620\ua8d0\ua900\uaa50\uff10";
+ /**
+ * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
+ * interpreted as a break between words for formatting purposes). See {@link #whitespace()} for a
+ * discussion of that term.
+ *
+ * @since 19.0 (since 2.0 as constant {@code BREAKING_WHITESPACE})
+ */
+ public static CharMatcher breakingWhitespace() {
+ return BreakingWhitespace.INSTANCE;
+ }
- private static final String NINES;
- static {
- StringBuilder builder = new StringBuilder(ZEROES.length());
- for (int i = 0; i < ZEROES.length(); i++) {
- builder.append((char) (ZEROES.charAt(i) + 9));
- }
- NINES = builder.toString();
+ /**
+ * Determines whether a character is ASCII, meaning that its code point is less than 128.
+ *
+ * @since 19.0 (since 1.0 as constant {@code ASCII})
+ */
+ public static CharMatcher ascii() {
+ return Ascii.INSTANCE;
}
/**
* Determines whether a character is a digit according to
* <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D">Unicode</a>.
* If you only care to match ASCII digits, you can use {@code inRange('0', '9')}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code DIGIT})
*/
- public static final CharMatcher DIGIT = new RangesMatcher(
- "CharMatcher.DIGIT", ZEROES.toCharArray(), NINES.toCharArray());
+ public static CharMatcher digit() {
+ return Digit.INSTANCE;
+ }
/**
* Determines whether a character is a digit according to {@linkplain Character#isDigit(char)
- * Java's definition}. If you only care to match ASCII digits, you can use {@code
- * inRange('0', '9')}.
+ * Java's definition}. If you only care to match ASCII digits, you can use {@code inRange('0',
+ * '9')}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code JAVA_DIGIT})
*/
- public static final CharMatcher JAVA_DIGIT = new CharMatcher("CharMatcher.JAVA_DIGIT") {
- @Override public boolean matches(char c) {
- return Character.isDigit(c);
- }
- };
+ public static CharMatcher javaDigit() {
+ return JavaDigit.INSTANCE;
+ }
/**
* Determines whether a character is a letter according to {@linkplain Character#isLetter(char)
* Java's definition}. If you only care to match letters of the Latin alphabet, you can use {@code
* inRange('a', 'z').or(inRange('A', 'Z'))}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code JAVA_LETTER})
*/
- public static final CharMatcher JAVA_LETTER = new CharMatcher("CharMatcher.JAVA_LETTER") {
- @Override public boolean matches(char c) {
- return Character.isLetter(c);
- }
- };
+ public static CharMatcher javaLetter() {
+ return JavaLetter.INSTANCE;
+ }
/**
* Determines whether a character is a letter or digit according to {@linkplain
* Character#isLetterOrDigit(char) Java's definition}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code JAVA_LETTER_OR_DIGIT}).
*/
- public static final CharMatcher JAVA_LETTER_OR_DIGIT =
- new CharMatcher("CharMatcher.JAVA_LETTER_OR_DIGIT") {
- @Override public boolean matches(char c) {
- return Character.isLetterOrDigit(c);
- }
- };
+ public static CharMatcher javaLetterOrDigit() {
+ return JavaLetterOrDigit.INSTANCE;
+ }
/**
* Determines whether a character is upper case according to {@linkplain
* Character#isUpperCase(char) Java's definition}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code JAVA_UPPER_CASE})
*/
- public static final CharMatcher JAVA_UPPER_CASE =
- new CharMatcher("CharMatcher.JAVA_UPPER_CASE") {
- @Override public boolean matches(char c) {
- return Character.isUpperCase(c);
- }
- };
+ public static CharMatcher javaUpperCase() {
+ return JavaUpperCase.INSTANCE;
+ }
/**
* Determines whether a character is lower case according to {@linkplain
* Character#isLowerCase(char) Java's definition}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code JAVA_LOWER_CASE})
*/
- public static final CharMatcher JAVA_LOWER_CASE =
- new CharMatcher("CharMatcher.JAVA_LOWER_CASE") {
- @Override public boolean matches(char c) {
- return Character.isLowerCase(c);
- }
- };
+ public static CharMatcher javaLowerCase() {
+ return JavaLowerCase.INSTANCE;
+ }
/**
* Determines whether a character is an ISO control character as specified by {@link
* Character#isISOControl(char)}.
+ *
+ * @since 19.0 (since 1.0 as constant {@code JAVA_ISO_CONTROL})
*/
- public static final CharMatcher JAVA_ISO_CONTROL =
- inRange('\u0000', '\u001f')
- .or(inRange('\u007f', '\u009f'))
- .withToString("CharMatcher.JAVA_ISO_CONTROL");
+ public static CharMatcher javaIsoControl() {
+ return JavaIsoControl.INSTANCE;
+ }
/**
* Determines whether a character is invisible; that is, if its Unicode category is any of
* SPACE_SEPARATOR, LINE_SEPARATOR, PARAGRAPH_SEPARATOR, CONTROL, FORMAT, SURROGATE, and
* PRIVATE_USE according to ICU4J.
+ *
+ * @since 19.0 (since 1.0 as constant {@code INVISIBLE})
*/
- public static final CharMatcher INVISIBLE = new RangesMatcher("CharMatcher.INVISIBLE", (
- "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u1680\u180e\u2000\u2028\u205f\u2066\u2067\u2068"
- + "\u2069\u206a\u3000\ud800\ufeff\ufff9\ufffa").toCharArray(), (
- "\u0020\u00a0\u00ad\u0604\u061c\u06dd\u070f\u1680\u180e\u200f\u202f\u2064\u2066\u2067\u2068"
- + "\u2069\u206f\u3000\uf8ff\ufeff\ufff9\ufffb").toCharArray());
-
- private static String showCharacter(char c) {
- String hex = "0123456789ABCDEF";
- char[] tmp = {'\\', 'u', '\0', '\0', '\0', '\0'};
- for (int i = 0; i < 4; i++) {
- tmp[5 - i] = hex.charAt(c & 0xF);
- c >>= 4;
- }
- return String.copyValueOf(tmp);
-
+ public static CharMatcher invisible() {
+ return Invisible.INSTANCE;
}
/**
@@ -241,170 +203,111 @@ public abstract class CharMatcher implements Predicate<Character> {
* errs on the side of returning {@code false} (that is, it tends to assume a character is
* double-width).
*
- * <p><b>Note:</b> as the reference file evolves, we will modify this constant to keep it up to
+ * <p><b>Note:</b> as the reference file evolves, we will modify this matcher to keep it up to
* date.
+ *
+ * @since 19.0 (since 1.0 as constant {@code SINGLE_WIDTH})
*/
- public static final CharMatcher SINGLE_WIDTH = new RangesMatcher("CharMatcher.SINGLE_WIDTH",
- "\u0000\u05be\u05d0\u05f3\u0600\u0750\u0e00\u1e00\u2100\ufb50\ufe70\uff61".toCharArray(),
- "\u04f9\u05be\u05ea\u05f4\u06ff\u077f\u0e7f\u20af\u213a\ufdff\ufeff\uffdc".toCharArray());
-
- /** Matches any character. */
- public static final CharMatcher ANY =
- new FastMatcher("CharMatcher.ANY") {
- @Override public boolean matches(char c) {
- return true;
- }
+ public static CharMatcher singleWidth() {
+ return SingleWidth.INSTANCE;
+ }
- @Override public int indexIn(CharSequence sequence) {
- return (sequence.length() == 0) ? -1 : 0;
- }
+ // Legacy constants
+ // TODO(cgdecker): Deprecate these so they can be removed eventually
- @Override public int indexIn(CharSequence sequence, int start) {
- int length = sequence.length();
- Preconditions.checkPositionIndex(start, length);
- return (start == length) ? -1 : start;
- }
+ /**
+ * Determines whether a character is whitespace according to the latest Unicode standard, as
+ * illustrated <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
+ * This is not the same definition used by other Java APIs. (See a <a
+ * href="http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">comparison of several
+ * definitions of "whitespace"</a>.)
+ *
+ * <p><b>Note:</b> as the Unicode definition evolves, we will modify this constant to keep it up
+ * to date.
+ */
+ public static final CharMatcher WHITESPACE = whitespace();
- @Override public int lastIndexIn(CharSequence sequence) {
- return sequence.length() - 1;
- }
+ /**
+ * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
+ * interpreted as a break between words for formatting purposes). See {@link #WHITESPACE} for a
+ * discussion of that term.
+ *
+ * @since 2.0
+ */
+ public static final CharMatcher BREAKING_WHITESPACE = breakingWhitespace();
- @Override public boolean matchesAllOf(CharSequence sequence) {
- checkNotNull(sequence);
- return true;
- }
+ /**
+ * Determines whether a character is ASCII, meaning that its code point is less than 128.
+ */
+ public static final CharMatcher ASCII = ascii();
- @Override public boolean matchesNoneOf(CharSequence sequence) {
- return sequence.length() == 0;
- }
+ /**
+ * Determines whether a character is a digit according to
+ * <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D">Unicode</a>.
+ * If you only care to match ASCII digits, you can use {@code inRange('0', '9')}.
+ */
+ public static final CharMatcher DIGIT = digit();
- @Override public String removeFrom(CharSequence sequence) {
- checkNotNull(sequence);
- return "";
- }
+ /**
+ * Determines whether a character is a digit according to {@linkplain Character#isDigit(char)
+ * Java's definition}. If you only care to match ASCII digits, you can use {@code
+ * inRange('0', '9')}.
+ */
+ public static final CharMatcher JAVA_DIGIT = javaDigit();
- @Override public String replaceFrom(CharSequence sequence, char replacement) {
- char[] array = new char[sequence.length()];
- Arrays.fill(array, replacement);
- return new String(array);
- }
+ /**
+ * Determines whether a character is a letter according to {@linkplain Character#isLetter(char)
+ * Java's definition}. If you only care to match letters of the Latin alphabet, you can use {@code
+ * inRange('a', 'z').or(inRange('A', 'Z'))}.
+ */
+ public static final CharMatcher JAVA_LETTER = javaLetter();
- @Override public String replaceFrom(CharSequence sequence, CharSequence replacement) {
- StringBuilder retval = new StringBuilder(sequence.length() * replacement.length());
- for (int i = 0; i < sequence.length(); i++) {
- retval.append(replacement);
- }
- return retval.toString();
- }
+ /**
+ * Determines whether a character is a letter or digit according to {@linkplain
+ * Character#isLetterOrDigit(char) Java's definition}.
+ */
+ public static final CharMatcher JAVA_LETTER_OR_DIGIT = javaLetterOrDigit();
- @Override public String collapseFrom(CharSequence sequence, char replacement) {
- return (sequence.length() == 0) ? "" : String.valueOf(replacement);
- }
+ /**
+ * Determines whether a character is upper case according to {@linkplain
+ * Character#isUpperCase(char) Java's definition}.
+ */
+ public static final CharMatcher JAVA_UPPER_CASE = javaUpperCase();
- @Override public String trimFrom(CharSequence sequence) {
- checkNotNull(sequence);
- return "";
- }
+ /**
+ * Determines whether a character is lower case according to {@linkplain
+ * Character#isLowerCase(char) Java's definition}.
+ */
+ public static final CharMatcher JAVA_LOWER_CASE = javaLowerCase();
- @Override public int countIn(CharSequence sequence) {
- return sequence.length();
- }
+ /**
+ * Determines whether a character is an ISO control character as specified by {@link
+ * Character#isISOControl(char)}.
+ */
+ public static final CharMatcher JAVA_ISO_CONTROL = javaIsoControl();
- @Override public CharMatcher and(CharMatcher other) {
- return checkNotNull(other);
- }
+ /**
+ * Determines whether a character is invisible; that is, if its Unicode category is any of
+ * SPACE_SEPARATOR, LINE_SEPARATOR, PARAGRAPH_SEPARATOR, CONTROL, FORMAT, SURROGATE, and
+ * PRIVATE_USE according to ICU4J.
+ */
+ public static final CharMatcher INVISIBLE = invisible();
- @Override public CharMatcher or(CharMatcher other) {
- checkNotNull(other);
- return this;
- }
+ /**
+ * Determines whether a character is single-width (not double-width). When in doubt, this matcher
+ * errs on the side of returning {@code false} (that is, it tends to assume a character is
+ * double-width).
+ *
+ * <p><b>Note:</b> as the reference file evolves, we will modify this constant to keep it up to
+ * date.
+ */
+ public static final CharMatcher SINGLE_WIDTH = singleWidth();
- @Override public CharMatcher negate() {
- return NONE;
- }
- };
+ /** Matches any character. */
+ public static final CharMatcher ANY = any();
/** Matches no characters. */
- public static final CharMatcher NONE =
- new FastMatcher("CharMatcher.NONE") {
- @Override public boolean matches(char c) {
- return false;
- }
-
- @Override public int indexIn(CharSequence sequence) {
- checkNotNull(sequence);
- return -1;
- }
-
- @Override public int indexIn(CharSequence sequence, int start) {
- int length = sequence.length();
- Preconditions.checkPositionIndex(start, length);
- return -1;
- }
-
- @Override public int lastIndexIn(CharSequence sequence) {
- checkNotNull(sequence);
- return -1;
- }
-
- @Override public boolean matchesAllOf(CharSequence sequence) {
- return sequence.length() == 0;
- }
-
- @Override public boolean matchesNoneOf(CharSequence sequence) {
- checkNotNull(sequence);
- return true;
- }
-
- @Override public String removeFrom(CharSequence sequence) {
- return sequence.toString();
- }
-
- @Override public String replaceFrom(CharSequence sequence, char replacement) {
- return sequence.toString();
- }
-
- @Override public String replaceFrom(CharSequence sequence, CharSequence replacement) {
- checkNotNull(replacement);
- return sequence.toString();
- }
-
- @Override public String collapseFrom(CharSequence sequence, char replacement) {
- return sequence.toString();
- }
-
- @Override public String trimFrom(CharSequence sequence) {
- return sequence.toString();
- }
-
- @Override
- public String trimLeadingFrom(CharSequence sequence) {
- return sequence.toString();
- }
-
- @Override
- public String trimTrailingFrom(CharSequence sequence) {
- return sequence.toString();
- }
-
- @Override public int countIn(CharSequence sequence) {
- checkNotNull(sequence);
- return 0;
- }
-
- @Override public CharMatcher and(CharMatcher other) {
- checkNotNull(other);
- return this;
- }
-
- @Override public CharMatcher or(CharMatcher other) {
- return checkNotNull(other);
- }
-
- @Override public CharMatcher negate() {
- return ANY;
- }
- };
+ public static final CharMatcher NONE = none();
// Static factories
@@ -412,34 +315,7 @@ public abstract class CharMatcher implements Predicate<Character> {
* Returns a {@code char} matcher that matches only one specified character.
*/
public static CharMatcher is(final char match) {
- String description = "CharMatcher.is('" + showCharacter(match) + "')";
- return new FastMatcher(description) {
- @Override public boolean matches(char c) {
- return c == match;
- }
-
- @Override public String replaceFrom(CharSequence sequence, char replacement) {
- return sequence.toString().replace(match, replacement);
- }
-
- @Override public CharMatcher and(CharMatcher other) {
- return other.matches(match) ? this : NONE;
- }
-
- @Override public CharMatcher or(CharMatcher other) {
- return other.matches(match) ? other : super.or(other);
- }
-
- @Override public CharMatcher negate() {
- return isNot(match);
- }
-
- @GwtIncompatible("java.util.BitSet")
- @Override
- void setBits(BitSet table) {
- table.set(match);
- }
- };
+ return new Is(match);
}
/**
@@ -448,32 +324,8 @@ public abstract class CharMatcher implements Predicate<Character> {
* <p>To negate another {@code CharMatcher}, use {@link #negate()}.
*/
public static CharMatcher isNot(final char match) {
- String description = "CharMatcher.isNot('" + showCharacter(match) + "')";
- return new FastMatcher(description) {
- @Override public boolean matches(char c) {
- return c != match;
- }
-
- @Override public CharMatcher and(CharMatcher other) {
- return other.matches(match) ? super.and(other) : other;
- }
-
- @Override public CharMatcher or(CharMatcher other) {
- return other.matches(match) ? ANY : this;
- }
-
- @GwtIncompatible("java.util.BitSet")
- @Override
- void setBits(BitSet table) {
- table.set(0, match);
- table.set(match + 1, Character.MAX_VALUE + 1);
- }
-
- @Override public CharMatcher negate() {
- return is(match);
- }
- };
- }
+ return new IsNot(match);
+ }
/**
* Returns a {@code char} matcher that matches any character present in the given character
@@ -482,53 +334,16 @@ public abstract class CharMatcher implements Predicate<Character> {
public static CharMatcher anyOf(final CharSequence sequence) {
switch (sequence.length()) {
case 0:
- return NONE;
+ return none();
case 1:
return is(sequence.charAt(0));
case 2:
return isEither(sequence.charAt(0), sequence.charAt(1));
default:
- // continue below to handle the general case
- }
- // TODO(user): is it potentially worth just going ahead and building a precomputed matcher?
- final char[] chars = sequence.toString().toCharArray();
- Arrays.sort(chars);
- StringBuilder description = new StringBuilder("CharMatcher.anyOf(\"");
- for (char c : chars) {
- description.append(showCharacter(c));
- }
- description.append("\")");
- return new CharMatcher(description.toString()) {
- @Override public boolean matches(char c) {
- return Arrays.binarySearch(chars, c) >= 0;
- }
-
- @Override
- @GwtIncompatible("java.util.BitSet")
- void setBits(BitSet table) {
- for (char c : chars) {
- table.set(c);
- }
- }
- };
- }
-
- private static CharMatcher isEither(
- final char match1,
- final char match2) {
- String description = "CharMatcher.anyOf(\"" +
- showCharacter(match1) + showCharacter(match2) + "\")";
- return new FastMatcher(description) {
- @Override public boolean matches(char c) {
- return c == match1 || c == match2;
- }
-
- @GwtIncompatible("java.util.BitSet")
- @Override void setBits(BitSet table) {
- table.set(match1);
- table.set(match2);
- }
- };
+ // TODO(lowasser): is it potentially worth just going ahead and building a precomputed
+ // matcher?
+ return new AnyOf(sequence);
+ }
}
/**
@@ -547,25 +362,7 @@ public abstract class CharMatcher implements Predicate<Character> {
* @throws IllegalArgumentException if {@code endInclusive < startInclusive}
*/
public static CharMatcher inRange(final char startInclusive, final char endInclusive) {
- checkArgument(endInclusive >= startInclusive);
- String description = "CharMatcher.inRange('" +
- showCharacter(startInclusive) + "', '" +
- showCharacter(endInclusive) + "')";
- return inRange(startInclusive, endInclusive, description);
- }
-
- static CharMatcher inRange(final char startInclusive, final char endInclusive,
- String description) {
- return new FastMatcher(description) {
- @Override public boolean matches(char c) {
- return startInclusive <= c && c <= endInclusive;
- }
-
- @GwtIncompatible("java.util.BitSet")
- @Override void setBits(BitSet table) {
- table.set(startInclusive, endInclusive + 1);
- }
- };
+ return new InRange(startInclusive, endInclusive);
}
/**
@@ -573,41 +370,16 @@ public abstract class CharMatcher implements Predicate<Character> {
* which operates on primitive {@code char} instances instead.
*/
public static CharMatcher forPredicate(final Predicate<? super Character> predicate) {
- checkNotNull(predicate);
- if (predicate instanceof CharMatcher) {
- return (CharMatcher) predicate;
- }
- String description = "CharMatcher.forPredicate(" + predicate + ")";
- return new CharMatcher(description) {
- @Override public boolean matches(char c) {
- return predicate.apply(c);
- }
-
- @Override public boolean apply(Character character) {
- return predicate.apply(checkNotNull(character));
- }
- };
+ return predicate instanceof CharMatcher ? (CharMatcher) predicate : new ForPredicate(predicate);
}
- // State
- final String description;
-
// Constructors
/**
- * Sets the {@code toString()} from the given description.
- */
- CharMatcher(String description) {
- this.description = description;
- }
-
- /**
* Constructor for use by subclasses. When subclassing, you may want to override
* {@code toString()} to provide a useful description.
*/
- protected CharMatcher() {
- description = super.toString();
- }
+ protected CharMatcher() {}
// Abstract methods
@@ -620,136 +392,21 @@ public abstract class CharMatcher implements Predicate<Character> {
* Returns a matcher that matches any character not matched by this matcher.
*/
public CharMatcher negate() {
- return new NegatedMatcher(this);
- }
-
- private static class NegatedMatcher extends CharMatcher {
- final CharMatcher original;
-
- NegatedMatcher(String toString, CharMatcher original) {
- super(toString);
- this.original = original;
- }
-
- NegatedMatcher(CharMatcher original) {
- this(original + ".negate()", original);
- }
-
- @Override public boolean matches(char c) {
- return !original.matches(c);
- }
-
- @Override public boolean matchesAllOf(CharSequence sequence) {
- return original.matchesNoneOf(sequence);
- }
-
- @Override public boolean matchesNoneOf(CharSequence sequence) {
- return original.matchesAllOf(sequence);
- }
-
- @Override public int countIn(CharSequence sequence) {
- return sequence.length() - original.countIn(sequence);
- }
-
- @GwtIncompatible("java.util.BitSet")
- @Override
- void setBits(BitSet table) {
- BitSet tmp = new BitSet();
- original.setBits(tmp);
- tmp.flip(Character.MIN_VALUE, Character.MAX_VALUE + 1);
- table.or(tmp);
- }
-
- @Override public CharMatcher negate() {
- return original;
- }
-
- @Override
- CharMatcher withToString(String description) {
- return new NegatedMatcher(description, original);
- }
+ return new Negated(this);
}
/**
* Returns a matcher that matches any character matched by both this matcher and {@code other}.
*/
public CharMatcher and(CharMatcher other) {
- return new And(this, checkNotNull(other));
- }
-
- private static class And extends CharMatcher {
- final CharMatcher first;
- final CharMatcher second;
-
- And(CharMatcher a, CharMatcher b) {
- this(a, b, "CharMatcher.and(" + a + ", " + b + ")");
- }
-
- And(CharMatcher a, CharMatcher b, String description) {
- super(description);
- first = checkNotNull(a);
- second = checkNotNull(b);
- }
-
- @Override
- public boolean matches(char c) {
- return first.matches(c) && second.matches(c);
- }
-
- @GwtIncompatible("java.util.BitSet")
- @Override
- void setBits(BitSet table) {
- BitSet tmp1 = new BitSet();
- first.setBits(tmp1);
- BitSet tmp2 = new BitSet();
- second.setBits(tmp2);
- tmp1.and(tmp2);
- table.or(tmp1);
- }
-
- @Override
- CharMatcher withToString(String description) {
- return new And(first, second, description);
- }
+ return new And(this, other);
}
/**
* Returns a matcher that matches any character matched by either this matcher or {@code other}.
*/
public CharMatcher or(CharMatcher other) {
- return new Or(this, checkNotNull(other));
- }
-
- private static class Or extends CharMatcher {
- final CharMatcher first;
- final CharMatcher second;
-
- Or(CharMatcher a, CharMatcher b, String description) {
- super(description);
- first = checkNotNull(a);
- second = checkNotNull(b);
- }
-
- Or(CharMatcher a, CharMatcher b) {
- this(a, b, "CharMatcher.or(" + a + ", " + b + ")");
- }
-
- @GwtIncompatible("java.util.BitSet")
- @Override
- void setBits(BitSet table) {
- first.setBits(table);
- second.setBits(table);
- }
-
- @Override
- public boolean matches(char c) {
- return first.matches(c) || second.matches(c);
- }
-
- @Override
- CharMatcher withToString(String description) {
- return new Or(first, second, description);
- }
+ return new Or(this, other);
}
/**
@@ -765,16 +422,6 @@ public abstract class CharMatcher implements Predicate<Character> {
return Platform.precomputeCharMatcher(this);
}
- /**
- * Subclasses should provide a new CharMatcher with the same characteristics as {@code this},
- * but with their {@code toString} method overridden with the new description.
- *
- * <p>This is unsupported by default.
- */
- CharMatcher withToString(String description) {
- throw new UnsupportedOperationException();
- }
-
private static final int DISTINCT_CHARS = Character.MAX_VALUE - Character.MIN_VALUE + 1;
/**
@@ -793,60 +440,24 @@ public abstract class CharMatcher implements Predicate<Character> {
setBits(table);
int totalCharacters = table.cardinality();
if (totalCharacters * 2 <= DISTINCT_CHARS) {
- return precomputedPositive(totalCharacters, table, description);
+ return precomputedPositive(totalCharacters, table, toString());
} else {
- // TODO(user): is it worth it to worry about the last character of large matchers?
+ // TODO(lowasser): is it worth it to worry about the last character of large matchers?
table.flip(Character.MIN_VALUE, Character.MAX_VALUE + 1);
int negatedCharacters = DISTINCT_CHARS - totalCharacters;
String suffix = ".negate()";
- String negatedDescription = description.endsWith(suffix)
- ? description.substring(0, description.length() - suffix.length())
- : description + suffix;
- return new NegatedFastMatcher(toString(),
- precomputedPositive(negatedCharacters, table, negatedDescription));
- }
- }
-
- /**
- * A matcher for which precomputation will not yield any significant benefit.
- */
- abstract static class FastMatcher extends CharMatcher {
- FastMatcher() {
- super();
- }
-
- FastMatcher(String description) {
- super(description);
- }
-
- @Override
- public final CharMatcher precomputed() {
- return this;
- }
-
- @Override
- public CharMatcher negate() {
- return new NegatedFastMatcher(this);
- }
- }
-
- static final class NegatedFastMatcher extends NegatedMatcher {
- NegatedFastMatcher(CharMatcher original) {
- super(original);
- }
-
- NegatedFastMatcher(String toString, CharMatcher original) {
- super(toString, original);
- }
-
- @Override
- public final CharMatcher precomputed() {
- return this;
- }
-
- @Override
- CharMatcher withToString(String description) {
- return new NegatedFastMatcher(description, original);
+ final String description = toString();
+ String negatedDescription =
+ description.endsWith(suffix)
+ ? description.substring(0, description.length() - suffix.length())
+ : description + suffix;
+ return new NegatedFastMatcher(
+ precomputedPositive(negatedCharacters, table, negatedDescription)) {
+ @Override
+ public String toString() {
+ return description;
+ }
+ };
}
}
@@ -855,12 +466,10 @@ public abstract class CharMatcher implements Predicate<Character> {
*/
@GwtIncompatible("java.util.BitSet")
private static CharMatcher precomputedPositive(
- int totalCharacters,
- BitSet table,
- String description) {
+ int totalCharacters, BitSet table, String description) {
switch (totalCharacters) {
case 0:
- return NONE;
+ return none();
case 1:
return is((char) table.nextSetBit(0));
case 2:
@@ -878,30 +487,7 @@ public abstract class CharMatcher implements Predicate<Character> {
private static boolean isSmall(int totalCharacters, int tableLength) {
return totalCharacters <= SmallCharMatcher.MAX_SIZE
&& tableLength > (totalCharacters * 4 * Character.SIZE);
- // err on the side of BitSetMatcher
- }
-
- @GwtIncompatible("java.util.BitSet")
- private static class BitSetMatcher extends FastMatcher {
- private final BitSet table;
-
- private BitSetMatcher(BitSet table, String description) {
- super(description);
- if (table.length() + Long.SIZE < table.size()) {
- table = (BitSet) table.clone();
- // If only we could actually call BitSet.trimToSize() ourselves...
- }
- this.table = table;
- }
-
- @Override public boolean matches(char c) {
- return table.get(c);
- }
-
- @Override
- void setBits(BitSet bitSet) {
- bitSet.or(table);
- }
+ // err on the side of BitSetMatcher
}
/**
@@ -978,13 +564,7 @@ public abstract class CharMatcher implements Predicate<Character> {
* @return an index, or {@code -1} if no character matches
*/
public int indexIn(CharSequence sequence) {
- int length = sequence.length();
- for (int i = 0; i < length; i++) {
- if (matches(sequence.charAt(i))) {
- return i;
- }
- }
- return -1;
+ return indexIn(sequence, 0);
}
/**
@@ -1004,7 +584,7 @@ public abstract class CharMatcher implements Predicate<Character> {
*/
public int indexIn(CharSequence sequence, int start) {
int length = sequence.length();
- Preconditions.checkPositionIndex(start, length);
+ checkPositionIndex(start, length);
for (int i = start; i < length; i++) {
if (matches(sequence.charAt(i))) {
return i;
@@ -1065,7 +645,8 @@ public abstract class CharMatcher implements Predicate<Character> {
int spread = 1;
// This unusual loop comes from extensive benchmarking
- OUT: while (true) {
+ OUT:
+ while (true) {
pos++;
while (true) {
if (pos == chars.length) {
@@ -1273,14 +854,12 @@ public abstract class CharMatcher implements Predicate<Character> {
for (int i = 0; i < len; i++) {
char c = sequence.charAt(i);
if (matches(c)) {
- if (c == replacement
- && (i == len - 1 || !matches(sequence.charAt(i + 1)))) {
+ if (c == replacement && (i == len - 1 || !matches(sequence.charAt(i + 1)))) {
// a no-op replacement
i++;
} else {
- StringBuilder builder = new StringBuilder(len)
- .append(sequence.subSequence(0, i))
- .append(replacement);
+ StringBuilder builder =
+ new StringBuilder(len).append(sequence.subSequence(0, i)).append(replacement);
return finishCollapseFrom(sequence, i + 1, len, replacement, builder, true);
}
}
@@ -1298,23 +877,30 @@ public abstract class CharMatcher implements Predicate<Character> {
public String trimAndCollapseFrom(CharSequence sequence, char replacement) {
// This implementation avoids unnecessary allocation.
int len = sequence.length();
- int first;
- int last;
+ int first = 0;
+ int last = len - 1;
+
+ while (first < len && matches(sequence.charAt(first))) {
+ first++;
+ }
- for (first = 0; first < len && matches(sequence.charAt(first)); first++) {}
- for (last = len - 1; last > first && matches(sequence.charAt(last)); last--) {}
+ while (last > first && matches(sequence.charAt(last))) {
+ last--;
+ }
return (first == 0 && last == len - 1)
? collapseFrom(sequence, replacement)
: finishCollapseFrom(
- sequence, first, last + 1, replacement,
- new StringBuilder(last + 1 - first),
- false);
+ sequence, first, last + 1, replacement, new StringBuilder(last + 1 - first), false);
}
private String finishCollapseFrom(
- CharSequence sequence, int start, int end, char replacement,
- StringBuilder builder, boolean inMatchingGroup) {
+ CharSequence sequence,
+ int start,
+ int end,
+ char replacement,
+ StringBuilder builder,
+ boolean inMatchingGroup) {
for (int i = start; i < end; i++) {
char c = sequence.charAt(i);
if (matches(c)) {
@@ -1346,40 +932,895 @@ public abstract class CharMatcher implements Predicate<Character> {
*/
@Override
public String toString() {
- return description;
+ return super.toString();
}
- static final String WHITESPACE_TABLE = ""
- + "\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000"
- + "\u2029\u000B\u3000\u2008\u2003\u205F\u3000\u1680"
- + "\u0009\u0020\u2006\u2001\u202F\u00A0\u000C\u2009"
- + "\u3000\u2004\u3000\u3000\u2028\n\u2007\u3000";
- static final int WHITESPACE_MULTIPLIER = 1682554634;
- static final int WHITESPACE_SHIFT = Integer.numberOfLeadingZeros(WHITESPACE_TABLE.length() - 1);
-
/**
- * Determines whether a character is whitespace according to the latest Unicode standard, as
- * illustrated
- * <a href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
- * This is not the same definition used by other Java APIs. (See a
- * <a href="http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">comparison of several
- * definitions of "whitespace"</a>.)
- *
- * <p><b>Note:</b> as the Unicode definition evolves, we will modify this constant to keep it up
- * to date.
+ * Returns the Java Unicode escape sequence for the given character, in the form "\u12AB" where
+ * "12AB" is the four hexadecimal digits representing the 16 bits of the UTF-16 character.
*/
- public static final CharMatcher WHITESPACE = new FastMatcher("WHITESPACE") {
+ private static String showCharacter(char c) {
+ String hex = "0123456789ABCDEF";
+ char[] tmp = {'\\', 'u', '\0', '\0', '\0', '\0'};
+ for (int i = 0; i < 4; i++) {
+ tmp[5 - i] = hex.charAt(c & 0xF);
+ c = (char) (c >> 4);
+ }
+ return String.copyValueOf(tmp);
+ }
+
+ // Fast matchers
+
+ /** A matcher for which precomputation will not yield any significant benefit. */
+ abstract static class FastMatcher extends CharMatcher {
+
@Override
- public boolean matches(char c) {
- return WHITESPACE_TABLE.charAt((WHITESPACE_MULTIPLIER * c) >>> WHITESPACE_SHIFT) == c;
+ public final CharMatcher precomputed() {
+ return this;
}
- @GwtIncompatible("java.util.BitSet")
@Override
- void setBits(BitSet table) {
- for (int i = 0; i < WHITESPACE_TABLE.length(); i++) {
- table.set(WHITESPACE_TABLE.charAt(i));
+ public CharMatcher negate() {
+ return new NegatedFastMatcher(this);
+ }
+ }
+
+ /** {@link FastMatcher} which overrides {@code toString()} with a custom name. */
+ abstract static class NamedFastMatcher extends FastMatcher {
+
+ private final String description;
+
+ NamedFastMatcher(String description) {
+ this.description = checkNotNull(description);
+ }
+
+ @Override
+ public final String toString() {
+ return description;
+ }
+ }
+
+ /** Negation of a {@link FastMatcher}. */
+ static class NegatedFastMatcher extends Negated {
+
+ NegatedFastMatcher(CharMatcher original) {
+ super(original);
+ }
+
+ @Override
+ public final CharMatcher precomputed() {
+ return this;
+ }
+ }
+
+ /** Fast matcher using a {@link BitSet} table of matching characters. */
+ @GwtIncompatible("java.util.BitSet")
+ private static final class BitSetMatcher extends NamedFastMatcher {
+
+ private final BitSet table;
+
+ private BitSetMatcher(BitSet table, String description) {
+ super(description);
+ if (table.length() + Long.SIZE < table.size()) {
+ table = (BitSet) table.clone();
+ // If only we could actually call BitSet.trimToSize() ourselves...
}
+ this.table = table;
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return table.get(c);
}
- };
+
+ @Override
+ void setBits(BitSet bitSet) {
+ bitSet.or(table);
+ }
+ }
+
+ // Static constant implementation classes
+
+ /** Implementation of {@link #any()}. */
+ private static final class Any extends NamedFastMatcher {
+
+ static final Any INSTANCE = new Any();
+
+ private Any() {
+ super("CharMatcher.any()");
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return true;
+ }
+
+ @Override
+ public int indexIn(CharSequence sequence) {
+ return (sequence.length() == 0) ? -1 : 0;
+ }
+
+ @Override
+ public int indexIn(CharSequence sequence, int start) {
+ int length = sequence.length();
+ checkPositionIndex(start, length);
+ return (start == length) ? -1 : start;
+ }
+
+ @Override
+ public int lastIndexIn(CharSequence sequence) {
+ return sequence.length() - 1;
+ }
+
+ @Override
+ public boolean matchesAllOf(CharSequence sequence) {
+ checkNotNull(sequence);
+ return true;
+ }
+
+ @Override
+ public boolean matchesNoneOf(CharSequence sequence) {
+ return sequence.length() == 0;
+ }
+
+ @Override
+ public String removeFrom(CharSequence sequence) {
+ checkNotNull(sequence);
+ return "";
+ }
+
+ @Override
+ public String replaceFrom(CharSequence sequence, char replacement) {
+ char[] array = new char[sequence.length()];
+ Arrays.fill(array, replacement);
+ return new String(array);
+ }
+
+ @Override
+ public String replaceFrom(CharSequence sequence, CharSequence replacement) {
+ StringBuilder result = new StringBuilder(sequence.length() * replacement.length());
+ for (int i = 0; i < sequence.length(); i++) {
+ result.append(replacement);
+ }
+ return result.toString();
+ }
+
+ @Override
+ public String collapseFrom(CharSequence sequence, char replacement) {
+ return (sequence.length() == 0) ? "" : String.valueOf(replacement);
+ }
+
+ @Override
+ public String trimFrom(CharSequence sequence) {
+ checkNotNull(sequence);
+ return "";
+ }
+
+ @Override
+ public int countIn(CharSequence sequence) {
+ return sequence.length();
+ }
+
+ @Override
+ public CharMatcher and(CharMatcher other) {
+ return checkNotNull(other);
+ }
+
+ @Override
+ public CharMatcher or(CharMatcher other) {
+ checkNotNull(other);
+ return this;
+ }
+
+ @Override
+ public CharMatcher negate() {
+ return none();
+ }
+ }
+
+ /** Implementation of {@link #none()}. */
+ private static final class None extends NamedFastMatcher {
+
+ static final None INSTANCE = new None();
+
+ private None() {
+ super("CharMatcher.none()");
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return false;
+ }
+
+ @Override
+ public int indexIn(CharSequence sequence) {
+ checkNotNull(sequence);
+ return -1;
+ }
+
+ @Override
+ public int indexIn(CharSequence sequence, int start) {
+ int length = sequence.length();
+ checkPositionIndex(start, length);
+ return -1;
+ }
+
+ @Override
+ public int lastIndexIn(CharSequence sequence) {
+ checkNotNull(sequence);
+ return -1;
+ }
+
+ @Override
+ public boolean matchesAllOf(CharSequence sequence) {
+ return sequence.length() == 0;
+ }
+
+ @Override
+ public boolean matchesNoneOf(CharSequence sequence) {
+ checkNotNull(sequence);
+ return true;
+ }
+
+ @Override
+ public String removeFrom(CharSequence sequence) {
+ return sequence.toString();
+ }
+
+ @Override
+ public String replaceFrom(CharSequence sequence, char replacement) {
+ return sequence.toString();
+ }
+
+ @Override
+ public String replaceFrom(CharSequence sequence, CharSequence replacement) {
+ checkNotNull(replacement);
+ return sequence.toString();
+ }
+
+ @Override
+ public String collapseFrom(CharSequence sequence, char replacement) {
+ return sequence.toString();
+ }
+
+ @Override
+ public String trimFrom(CharSequence sequence) {
+ return sequence.toString();
+ }
+
+ @Override
+ public String trimLeadingFrom(CharSequence sequence) {
+ return sequence.toString();
+ }
+
+ @Override
+ public String trimTrailingFrom(CharSequence sequence) {
+ return sequence.toString();
+ }
+
+ @Override
+ public int countIn(CharSequence sequence) {
+ checkNotNull(sequence);
+ return 0;
+ }
+
+ @Override
+ public CharMatcher and(CharMatcher other) {
+ checkNotNull(other);
+ return this;
+ }
+
+ @Override
+ public CharMatcher or(CharMatcher other) {
+ return checkNotNull(other);
+ }
+
+ @Override
+ public CharMatcher negate() {
+ return any();
+ }
+ }
+
+ /** Implementation of {@link #whitespace()}. */
+ @VisibleForTesting
+ static final class Whitespace extends NamedFastMatcher {
+
+ static final String TABLE =
+ "\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000"
+ + "\u2029\u000B\u3000\u2008\u2003\u205F\u3000\u1680"
+ + "\u0009\u0020\u2006\u2001\u202F\u00A0\u000C\u2009"
+ + "\u3000\u2004\u3000\u3000\u2028\n\u2007\u3000";
+ static final int MULTIPLIER = 1682554634;
+ static final int SHIFT = Integer.numberOfLeadingZeros(TABLE.length() - 1);
+
+ static final Whitespace INSTANCE = new Whitespace();
+
+ Whitespace() {
+ super("CharMatcher.whitespace()");
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return TABLE.charAt((MULTIPLIER * c) >>> SHIFT) == c;
+ }
+
+ @GwtIncompatible("java.util.BitSet")
+ @Override
+ void setBits(BitSet table) {
+ for (int i = 0; i < TABLE.length(); i++) {
+ table.set(TABLE.charAt(i));
+ }
+ }
+ }
+
+ /** Implementation of {@link #breakingWhitespace()}. */
+ private static final class BreakingWhitespace extends CharMatcher {
+
+ static final CharMatcher INSTANCE = new BreakingWhitespace();
+
+ @Override
+ public boolean matches(char c) {
+ switch (c) {
+ case '\t':
+ case '\n':
+ case '\013':
+ case '\f':
+ case '\r':
+ case ' ':
+ case '\u0085':
+ case '\u1680':
+ case '\u2028':
+ case '\u2029':
+ case '\u205f':
+ case '\u3000':
+ return true;
+ case '\u2007':
+ return false;
+ default:
+ return c >= '\u2000' && c <= '\u200a';
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.breakingWhitespace()";
+ }
+ }
+
+ /** Implementation of {@link #ascii()}. */
+ private static final class Ascii extends NamedFastMatcher {
+
+ static final Ascii INSTANCE = new Ascii();
+
+ Ascii() {
+ super("CharMatcher.ascii()");
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return c <= '\u007f';
+ }
+ }
+
+ /** Implementation that matches characters that fall within multiple ranges. */
+ private static class RangesMatcher extends CharMatcher {
+
+ private final String description;
+ private final char[] rangeStarts;
+ private final char[] rangeEnds;
+
+ RangesMatcher(String description, char[] rangeStarts, char[] rangeEnds) {
+ this.description = description;
+ this.rangeStarts = rangeStarts;
+ this.rangeEnds = rangeEnds;
+ checkArgument(rangeStarts.length == rangeEnds.length);
+ for (int i = 0; i < rangeStarts.length; i++) {
+ checkArgument(rangeStarts[i] <= rangeEnds[i]);
+ if (i + 1 < rangeStarts.length) {
+ checkArgument(rangeEnds[i] < rangeStarts[i + 1]);
+ }
+ }
+ }
+
+ @Override
+ public boolean matches(char c) {
+ int index = Arrays.binarySearch(rangeStarts, c);
+ if (index >= 0) {
+ return true;
+ } else {
+ index = ~index - 1;
+ return index >= 0 && c <= rangeEnds[index];
+ }
+ }
+
+ @Override
+ public String toString() {
+ return description;
+ }
+ }
+
+ /** Implementation of {@link #digit()}. */
+ private static final class Digit extends RangesMatcher {
+
+ // Must be in ascending order.
+ private static final String ZEROES =
+ "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66"
+ + "\u0be6\u0c66\u0ce6\u0d66\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810"
+ + "\u1946\u19d0\u1b50\u1bb0\u1c40\u1c50\ua620\ua8d0\ua900\uaa50\uff10";
+
+ private static char[] zeroes() {
+ return ZEROES.toCharArray();
+ }
+
+ private static char[] nines() {
+ char[] nines = new char[ZEROES.length()];
+ for (int i = 0; i < ZEROES.length(); i++) {
+ nines[i] = (char) (ZEROES.charAt(i) + 9);
+ }
+ return nines;
+ }
+
+ static final Digit INSTANCE = new Digit();
+
+ private Digit() {
+ super("CharMatcher.digit()", zeroes(), nines());
+ }
+ }
+
+ /** Implementation of {@link #javaDigit()}. */
+ private static final class JavaDigit extends CharMatcher {
+
+ static final JavaDigit INSTANCE = new JavaDigit();
+
+ @Override
+ public boolean matches(char c) {
+ return Character.isDigit(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.javaDigit()";
+ }
+ }
+
+ /** Implementation of {@link #javaLetter()}. */
+ private static final class JavaLetter extends CharMatcher {
+
+ static final JavaLetter INSTANCE = new JavaLetter();
+
+ @Override
+ public boolean matches(char c) {
+ return Character.isLetter(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.javaLetter()";
+ }
+ }
+
+ /** Implementation of {@link #javaLetterOrDigit()}. */
+ private static final class JavaLetterOrDigit extends CharMatcher {
+
+ static final JavaLetterOrDigit INSTANCE = new JavaLetterOrDigit();
+
+ @Override
+ public boolean matches(char c) {
+ return Character.isLetterOrDigit(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.javaLetterOrDigit()";
+ }
+ }
+
+ /** Implementation of {@link #javaUpperCase()}. */
+ private static final class JavaUpperCase extends CharMatcher {
+
+ static final JavaUpperCase INSTANCE = new JavaUpperCase();
+
+ @Override
+ public boolean matches(char c) {
+ return Character.isUpperCase(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.javaUpperCase()";
+ }
+ }
+
+ /** Implementation of {@link #javaLowerCase()}. */
+ private static final class JavaLowerCase extends CharMatcher {
+
+ static final JavaLowerCase INSTANCE = new JavaLowerCase();
+
+ @Override
+ public boolean matches(char c) {
+ return Character.isLowerCase(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.javaLowerCase()";
+ }
+ }
+
+ /** Implementation of {@link #javaIsoControl()}. */
+ private static final class JavaIsoControl extends NamedFastMatcher {
+
+ static final JavaIsoControl INSTANCE = new JavaIsoControl();
+
+ private JavaIsoControl() {
+ super("CharMatcher.javaIsoControl()");
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return c <= '\u001f' || (c >= '\u007f' && c <= '\u009f');
+ }
+ }
+
+ /** Implementation of {@link #invisible()}. */
+ private static final class Invisible extends RangesMatcher {
+
+ private static final String RANGE_STARTS =
+ "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u1680\u180e\u2000\u2028\u205f\u2066\u2067"
+ + "\u2068\u2069\u206a\u3000\ud800\ufeff\ufff9\ufffa";
+ private static final String RANGE_ENDS =
+ "\u0020\u00a0\u00ad\u0604\u061c\u06dd\u070f\u1680\u180e\u200f\u202f\u2064\u2066\u2067"
+ + "\u2068\u2069\u206f\u3000\uf8ff\ufeff\ufff9\ufffb";
+
+ static final Invisible INSTANCE = new Invisible();
+
+ private Invisible() {
+ super(
+ "CharMatcher.invisible()",
+ RANGE_STARTS.toCharArray(),
+ RANGE_ENDS.toCharArray());
+ }
+ }
+
+ /** Implementation of {@link #singleWidth()}. */
+ private static final class SingleWidth extends RangesMatcher {
+
+ static final SingleWidth INSTANCE = new SingleWidth();
+
+ private SingleWidth() {
+ super(
+ "CharMatcher.singleWidth()",
+ "\u0000\u05be\u05d0\u05f3\u0600\u0750\u0e00\u1e00\u2100\ufb50\ufe70\uff61".toCharArray(),
+ "\u04f9\u05be\u05ea\u05f4\u06ff\u077f\u0e7f\u20af\u213a\ufdff\ufeff\uffdc".toCharArray());
+ }
+ }
+
+ // Non-static factory implementation classes
+
+ /** Implementation of {@link #negate()}. */
+ private static class Negated extends CharMatcher {
+
+ final CharMatcher original;
+
+ Negated(CharMatcher original) {
+ this.original = checkNotNull(original);
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return !original.matches(c);
+ }
+
+ @Override
+ public boolean matchesAllOf(CharSequence sequence) {
+ return original.matchesNoneOf(sequence);
+ }
+
+ @Override
+ public boolean matchesNoneOf(CharSequence sequence) {
+ return original.matchesAllOf(sequence);
+ }
+
+ @Override
+ public int countIn(CharSequence sequence) {
+ return sequence.length() - original.countIn(sequence);
+ }
+
+ @GwtIncompatible("java.util.BitSet")
+ @Override
+ void setBits(BitSet table) {
+ BitSet tmp = new BitSet();
+ original.setBits(tmp);
+ tmp.flip(Character.MIN_VALUE, Character.MAX_VALUE + 1);
+ table.or(tmp);
+ }
+
+ @Override
+ public CharMatcher negate() {
+ return original;
+ }
+
+ @Override
+ public String toString() {
+ return original + ".negate()";
+ }
+ }
+
+ /** Implementation of {@link #and(CharMatcher)}. */
+ private static final class And extends CharMatcher {
+
+ final CharMatcher first;
+ final CharMatcher second;
+
+ And(CharMatcher a, CharMatcher b) {
+ first = checkNotNull(a);
+ second = checkNotNull(b);
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return first.matches(c) && second.matches(c);
+ }
+
+ @GwtIncompatible("java.util.BitSet")
+ @Override
+ void setBits(BitSet table) {
+ BitSet tmp1 = new BitSet();
+ first.setBits(tmp1);
+ BitSet tmp2 = new BitSet();
+ second.setBits(tmp2);
+ tmp1.and(tmp2);
+ table.or(tmp1);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.and(" + first + ", " + second + ")";
+ }
+ }
+
+ /** Implementation of {@link #or(CharMatcher)}. */
+ private static final class Or extends CharMatcher {
+
+ final CharMatcher first;
+ final CharMatcher second;
+
+ Or(CharMatcher a, CharMatcher b) {
+ first = checkNotNull(a);
+ second = checkNotNull(b);
+ }
+
+ @GwtIncompatible("java.util.BitSet")
+ @Override
+ void setBits(BitSet table) {
+ first.setBits(table);
+ second.setBits(table);
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return first.matches(c) || second.matches(c);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.or(" + first + ", " + second + ")";
+ }
+ }
+
+ // Static factory implementations
+
+ /** Implementation of {@link #is(char)}. */
+ private static final class Is extends FastMatcher {
+
+ private final char match;
+
+ Is(char match) {
+ this.match = match;
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return c == match;
+ }
+
+ @Override
+ public String replaceFrom(CharSequence sequence, char replacement) {
+ return sequence.toString().replace(match, replacement);
+ }
+
+ @Override
+ public CharMatcher and(CharMatcher other) {
+ return other.matches(match) ? this : none();
+ }
+
+ @Override
+ public CharMatcher or(CharMatcher other) {
+ return other.matches(match) ? other : super.or(other);
+ }
+
+ @Override
+ public CharMatcher negate() {
+ return isNot(match);
+ }
+
+ @GwtIncompatible("java.util.BitSet")
+ @Override
+ void setBits(BitSet table) {
+ table.set(match);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.is('" + showCharacter(match) + "')";
+ }
+ }
+
+ /** Implementation of {@link #isNot(char)}. */
+ private static final class IsNot extends FastMatcher {
+
+ private final char match;
+
+ IsNot(char match) {
+ this.match = match;
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return c != match;
+ }
+
+ @Override
+ public CharMatcher and(CharMatcher other) {
+ return other.matches(match) ? super.and(other) : other;
+ }
+
+ @Override
+ public CharMatcher or(CharMatcher other) {
+ return other.matches(match) ? any() : this;
+ }
+
+ @GwtIncompatible("java.util.BitSet")
+ @Override
+ void setBits(BitSet table) {
+ table.set(0, match);
+ table.set(match + 1, Character.MAX_VALUE + 1);
+ }
+
+ @Override
+ public CharMatcher negate() {
+ return is(match);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.isNot('" + showCharacter(match) + "')";
+ }
+ }
+
+ private static CharMatcher.IsEither isEither(char c1, char c2) {
+ return new CharMatcher.IsEither(c1, c2);
+ }
+
+ /** Implementation of {@link #anyOf(CharSequence)} for exactly two characters. */
+ private static final class IsEither extends FastMatcher {
+
+ private final char match1;
+ private final char match2;
+
+ IsEither(char match1, char match2) {
+ this.match1 = match1;
+ this.match2 = match2;
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return c == match1 || c == match2;
+ }
+
+ @GwtIncompatible("java.util.BitSet")
+ @Override
+ void setBits(BitSet table) {
+ table.set(match1);
+ table.set(match2);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.anyOf(\"" + showCharacter(match1) + showCharacter(match2) + "\")";
+ }
+ }
+
+ /** Implementation of {@link #anyOf(CharSequence)} for three or more characters. */
+ private static final class AnyOf extends CharMatcher {
+
+ private final char[] chars;
+
+ public AnyOf(CharSequence chars) {
+ this.chars = chars.toString().toCharArray();
+ Arrays.sort(this.chars);
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return Arrays.binarySearch(chars, c) >= 0;
+ }
+
+ @Override
+ @GwtIncompatible("java.util.BitSet")
+ void setBits(BitSet table) {
+ for (char c : chars) {
+ table.set(c);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder description = new StringBuilder("CharMatcher.anyOf(\"");
+ for (char c : chars) {
+ description.append(showCharacter(c));
+ }
+ description.append("\")");
+ return description.toString();
+ }
+ }
+
+ /** Implementation of {@link #inRange(char, char)}. */
+ private static final class InRange extends FastMatcher {
+
+ private final char startInclusive;
+ private final char endInclusive;
+
+ InRange(char startInclusive, char endInclusive) {
+ checkArgument(endInclusive >= startInclusive);
+ this.startInclusive = startInclusive;
+ this.endInclusive = endInclusive;
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return startInclusive <= c && c <= endInclusive;
+ }
+
+ @GwtIncompatible("java.util.BitSet")
+ @Override
+ void setBits(BitSet table) {
+ table.set(startInclusive, endInclusive + 1);
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.inRange('"
+ + showCharacter(startInclusive)
+ + "', '"
+ + showCharacter(endInclusive)
+ + "')";
+ }
+ }
+
+ /** Implementation of {@link #forPredicate(Predicate)}. */
+ private static final class ForPredicate extends CharMatcher {
+
+ private final Predicate<? super Character> predicate;
+
+ ForPredicate(Predicate<? super Character> predicate) {
+ this.predicate = checkNotNull(predicate);
+ }
+
+ @Override
+ public boolean matches(char c) {
+ return predicate.apply(c);
+ }
+
+ @SuppressWarnings("deprecation") // intentional; deprecation is for callers primarily
+ @Override
+ public boolean apply(Character character) {
+ return predicate.apply(checkNotNull(character));
+ }
+
+ @Override
+ public String toString() {
+ return "CharMatcher.forPredicate(" + predicate + ")";
+ }
+ }
}
diff --git a/guava/src/com/google/common/base/Charsets.java b/guava/src/com/google/common/base/Charsets.java
index 37fc686..9aba5c4 100644
--- a/guava/src/com/google/common/base/Charsets.java
+++ b/guava/src/com/google/common/base/Charsets.java
@@ -28,7 +28,7 @@ import java.nio.charset.Charset;
* <p>Assuming you're free to choose, note that <b>{@link #UTF_8} is widely preferred</b>.
*
* <p>See the Guava User Guide article on <a
- * href="http://code.google.com/p/guava-libraries/wiki/StringsExplained#Charsets">
+ * href="https://github.com/google/guava/wiki/StringsExplained#charsets">
* {@code Charsets}</a>.
*
* @author Mike Bostock
diff --git a/guava/src/com/google/common/base/Converter.java b/guava/src/com/google/common/base/Converter.java
index 6c13776..40ca53a 100644
--- a/guava/src/com/google/common/base/Converter.java
+++ b/guava/src/com/google/common/base/Converter.java
@@ -69,8 +69,9 @@ import javax.annotation.Nullable;
* com.google.common.collect.Maps#asConverter Maps.asConverter}. For example, use this to create
* a "fake" converter for a unit test. It is unnecessary (and confusing) to <i>mock</i> the
* {@code Converter} type using a mocking framework.
- * <li>Otherwise, extend this class and implement its {@link #doForward} and {@link #doBackward}
- * methods.
+ * <li>Extend this class and implement its {@link #doForward} and {@link #doBackward} methods.
+ * <li>If using Java 8, you may prefer to pass two lambda expressions or method references to {@link
+ * #from}.
* </ul>
*
* <p>Using a converter:
@@ -85,6 +86,26 @@ import javax.annotation.Nullable;
* overridden.
* </ul>
*
+ * <h3>Example</h3>
+ *
+ * <pre> {@code
+ *
+ * return new Converter<Integer, String>() {
+ * @Override
+ * protected String doForward(Integer i) {
+ * return Integer.toHexString(i);
+ * }
+ *
+ * @Override
+ * protected Integer doBackward(String s) {
+ * return parseUnsignedInt(s, 16);
+ * }
+ * };}</pre>
+ *
+ * <p>An alternative using Java 8: <pre> {@code
+ *
+ * return Converter.from(Integer::toHexString, s -> parseUnsignedInt(s, 16));}</pre>
+ *
* @author Mike Ward
* @author Kurt Alfred Kluever
* @author Gregory Kick
@@ -178,7 +199,8 @@ public abstract class Converter<A, B> implements Function<A, B> {
public Iterable<B> convertAll(final Iterable<? extends A> fromIterable) {
checkNotNull(fromIterable, "fromIterable");
return new Iterable<B>() {
- @Override public Iterator<B> iterator() {
+ @Override
+ public Iterator<B> iterator() {
return new Iterator<B>() {
private final Iterator<? extends A> fromIterator = fromIterable.iterator();
@@ -207,14 +229,14 @@ public abstract class Converter<A, B> implements Function<A, B> {
*
* <p>The returned converter is serializable if {@code this} converter is.
*/
- // TODO(user): Make this method final
+ // TODO(kak): Make this method final
public Converter<B, A> reverse() {
Converter<B, A> result = reverse;
return (result == null) ? reverse = new ReverseConverter<A, B>(this) : result;
}
- private static final class ReverseConverter<A, B>
- extends Converter<B, A> implements Serializable {
+ private static final class ReverseConverter<A, B> extends Converter<B, A>
+ implements Serializable {
final Converter<A, B> original;
ReverseConverter(Converter<A, B> original) {
@@ -295,8 +317,8 @@ public abstract class Converter<A, B> implements Function<A, B> {
return new ConverterComposition<A, B, C>(this, checkNotNull(secondConverter));
}
- private static final class ConverterComposition<A, B, C>
- extends Converter<A, C> implements Serializable {
+ private static final class ConverterComposition<A, B, C> extends Converter<A, C>
+ implements Serializable {
final Converter<A, B> first;
final Converter<B, C> second;
@@ -338,8 +360,7 @@ public abstract class Converter<A, B> implements Function<A, B> {
public boolean equals(@Nullable Object object) {
if (object instanceof ConverterComposition) {
ConverterComposition<?, ?, ?> that = (ConverterComposition<?, ?, ?>) object;
- return this.first.equals(that.first)
- && this.second.equals(that.second);
+ return this.first.equals(that.first) && this.second.equals(that.second);
}
return false;
}
@@ -405,8 +426,8 @@ public abstract class Converter<A, B> implements Function<A, B> {
return new FunctionBasedConverter<A, B>(forwardFunction, backwardFunction);
}
- private static final class FunctionBasedConverter<A, B>
- extends Converter<A, B> implements Serializable {
+ private static final class FunctionBasedConverter<A, B> extends Converter<A, B>
+ implements Serializable {
private final Function<? super A, ? extends B> forwardFunction;
private final Function<? super B, ? extends A> backwardFunction;
diff --git a/guava/src/com/google/common/base/Defaults.java b/guava/src/com/google/common/base/Defaults.java
index e07c75c..bfc22cf 100644
--- a/guava/src/com/google/common/base/Defaults.java
+++ b/guava/src/com/google/common/base/Defaults.java
@@ -22,6 +22,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -30,6 +31,7 @@ import javax.annotation.Nullable;
* @author Ben Yu
* @since 1.0
*/
+ at CheckReturnValue
public final class Defaults {
private Defaults() {}
@@ -56,7 +58,7 @@ public final class Defaults {
/**
* Returns the default value of {@code type} as defined by JLS --- {@code 0} for numbers, {@code
* false} for {@code boolean} and {@code '\0'} for {@code char}. For non-primitive types and
- * {@code void}, null is returned.
+ * {@code void}, {@code null} is returned.
*/
@Nullable
public static <T> T defaultValue(Class<T> type) {
diff --git a/guava/src/com/google/common/base/Enums.java b/guava/src/com/google/common/base/Enums.java
index dbc3754..cbbe08f 100644
--- a/guava/src/com/google/common/base/Enums.java
+++ b/guava/src/com/google/common/base/Enums.java
@@ -30,6 +30,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -39,6 +40,7 @@ import javax.annotation.Nullable;
*
* @since 9.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
@Beta
public final class Enums {
@@ -70,8 +72,7 @@ public final class Enums {
*
* @since 12.0
*/
- public static <T extends Enum<T>> Optional<T> getIfPresent(
- Class<T> enumClass, String value) {
+ public static <T extends Enum<T>> Optional<T> getIfPresent(Class<T> enumClass, String value) {
checkNotNull(enumClass);
checkNotNull(value);
return Platform.getEnumIfPresent(enumClass, value);
@@ -79,14 +80,15 @@ public final class Enums {
@GwtIncompatible("java.lang.ref.WeakReference")
private static final Map<Class<? extends Enum<?>>, Map<String, WeakReference<? extends Enum<?>>>>
- enumConstantCache = new WeakHashMap
- <Class<? extends Enum<?>>, Map<String, WeakReference<? extends Enum<?>>>>();
+ enumConstantCache =
+ new WeakHashMap<
+ Class<? extends Enum<?>>, Map<String, WeakReference<? extends Enum<?>>>>();
@GwtIncompatible("java.lang.ref.WeakReference")
private static <T extends Enum<T>> Map<String, WeakReference<? extends Enum<?>>> populateCache(
Class<T> enumClass) {
- Map<String, WeakReference<? extends Enum<?>>> result
- = new HashMap<String, WeakReference<? extends Enum<?>>>();
+ Map<String, WeakReference<? extends Enum<?>>> result =
+ new HashMap<String, WeakReference<? extends Enum<?>>>();
for (T enumInstance : EnumSet.allOf(enumClass)) {
result.put(enumInstance.name(), new WeakReference<Enum<?>>(enumInstance));
}
@@ -98,8 +100,7 @@ public final class Enums {
static <T extends Enum<T>> Map<String, WeakReference<? extends Enum<?>>> getEnumConstants(
Class<T> enumClass) {
synchronized (enumConstantCache) {
- Map<String, WeakReference<? extends Enum<?>>> constants =
- enumConstantCache.get(enumClass);
+ Map<String, WeakReference<? extends Enum<?>>> constants = enumConstantCache.get(enumClass);
if (constants == null) {
constants = populateCache(enumClass);
}
@@ -119,8 +120,8 @@ public final class Enums {
return new StringConverter<T>(enumClass);
}
- private static final class StringConverter<T extends Enum<T>>
- extends Converter<String, T> implements Serializable {
+ private static final class StringConverter<T extends Enum<T>> extends Converter<String, T>
+ implements Serializable {
private final Class<T> enumClass;
diff --git a/guava/src/com/google/common/base/Equivalence.java b/guava/src/com/google/common/base/Equivalence.java
index be654cf..344454f 100644
--- a/guava/src/com/google/common/base/Equivalence.java
+++ b/guava/src/com/google/common/base/Equivalence.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -33,9 +34,10 @@ import javax.annotation.Nullable;
* @author Bob Lee
* @author Ben Yu
* @author Gregory Kick
- * @since 10.0 (<a href="http://code.google.com/p/guava-libraries/wiki/Compatibility"
+ * @since 10.0 (<a href="https://github.com/google/guava/wiki/Compatibility"
* >mostly source-compatible</a> since 4.0)
*/
+ at CheckReturnValue
@GwtCompatible
public abstract class Equivalence<T> {
/**
@@ -124,27 +126,27 @@ public abstract class Equivalence<T> {
*
* <pre> {@code
* Equivalence<Person> SAME_AGE = Equivalence.equals().onResultOf(GET_PERSON_AGE);}</pre>
- *
+ *
* <p>{@code function} will never be invoked with a null value.
- *
+ *
* <p>Note that {@code function} must be consistent according to {@code this} equivalence
* relation. That is, invoking {@link Function#apply} multiple times for a given value must return
* equivalent results.
* For example, {@code Equivalence.identity().onResultOf(Functions.toStringFunction())} is broken
* because it's not guaranteed that {@link Object#toString}) always returns the same string
* instance.
- *
+ *
* @since 10.0
*/
public final <F> Equivalence<F> onResultOf(Function<F, ? extends T> function) {
return new FunctionalEquivalence<F, T>(function, this);
}
-
+
/**
* Returns a wrapper of {@code reference} that implements
* {@link Wrapper#equals(Object) Object.equals()} such that
* {@code wrap(a).equals(wrap(b))} if and only if {@code equivalent(a, b)}.
- *
+ *
* @since 10.0
*/
public final <S extends T> Wrapper<S> wrap(@Nullable S reference) {
@@ -179,7 +181,8 @@ public abstract class Equivalence<T> {
}
/** Returns the (possibly null) reference wrapped by this instance. */
- @Nullable public T get() {
+ @Nullable
+ public T get() {
return reference;
}
@@ -188,7 +191,8 @@ public abstract class Equivalence<T> {
* references is {@code true} and both wrappers use the {@link Object#equals(Object) same}
* equivalence.
*/
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj == this) {
return true;
}
@@ -211,7 +215,8 @@ public abstract class Equivalence<T> {
/**
* Returns the result of {@link Equivalence#hash(Object)} applied to the wrapped reference.
*/
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return equivalence.hash(reference);
}
@@ -219,7 +224,8 @@ public abstract class Equivalence<T> {
* Returns a string representation for this equivalence wrapper. The form of this string
* representation is not specified.
*/
- @Override public String toString() {
+ @Override
+ public String toString() {
return equivalence + ".wrap(" + reference + ")";
}
@@ -231,7 +237,7 @@ public abstract class Equivalence<T> {
* specifically, two iterables are considered equivalent if they both contain the same number of
* elements, and each pair of corresponding elements is equivalent according to
* {@code this}. Null iterables are equivalent to one another.
- *
+ *
* <p>Note that this method performs a similar function for equivalences as {@link
* com.google.common.collect.Ordering#lexicographical} does for orderings.
*
@@ -243,11 +249,11 @@ public abstract class Equivalence<T> {
// the need for this is so rare that it's not worth making callers deal with the ugly wildcard.
return new PairwiseEquivalence<S>(this);
}
-
+
/**
* Returns a predicate that evaluates to true if and only if the input is
* equivalent to {@code target} according to this equivalence relation.
- *
+ *
* @since 10.0
*/
@Beta
@@ -265,27 +271,30 @@ public abstract class Equivalence<T> {
this.target = target;
}
- @Override public boolean apply(@Nullable T input) {
+ @Override
+ public boolean apply(@Nullable T input) {
return equivalence.equivalent(input, target);
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof EquivalentToPredicate) {
EquivalentToPredicate<?> that = (EquivalentToPredicate<?>) obj;
- return equivalence.equals(that.equivalence)
- && Objects.equal(target, that.target);
+ return equivalence.equals(that.equivalence) && Objects.equal(target, that.target);
}
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Objects.hashCode(equivalence, target);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return equivalence + ".equivalentTo(" + target + ")";
}
@@ -318,40 +327,45 @@ public abstract class Equivalence<T> {
return Identity.INSTANCE;
}
- static final class Equals extends Equivalence<Object>
- implements Serializable {
-
+ static final class Equals extends Equivalence<Object> implements Serializable {
+
static final Equals INSTANCE = new Equals();
- @Override protected boolean doEquivalent(Object a, Object b) {
+ @Override
+ protected boolean doEquivalent(Object a, Object b) {
return a.equals(b);
}
- @Override protected int doHash(Object o) {
+
+ @Override
+ protected int doHash(Object o) {
return o.hashCode();
}
private Object readResolve() {
return INSTANCE;
- }
+ }
+
private static final long serialVersionUID = 1;
}
-
- static final class Identity extends Equivalence<Object>
- implements Serializable {
-
+
+ static final class Identity extends Equivalence<Object> implements Serializable {
+
static final Identity INSTANCE = new Identity();
-
- @Override protected boolean doEquivalent(Object a, Object b) {
+
+ @Override
+ protected boolean doEquivalent(Object a, Object b) {
return false;
}
- @Override protected int doHash(Object o) {
+ @Override
+ protected int doHash(Object o) {
return System.identityHashCode(o);
}
-
+
private Object readResolve() {
return INSTANCE;
}
+
private static final long serialVersionUID = 1;
}
}
diff --git a/guava/src/com/google/common/base/FinalizablePhantomReference.java b/guava/src/com/google/common/base/FinalizablePhantomReference.java
index c694bc9..952143e 100644
--- a/guava/src/com/google/common/base/FinalizablePhantomReference.java
+++ b/guava/src/com/google/common/base/FinalizablePhantomReference.java
@@ -27,7 +27,7 @@ import java.lang.ref.ReferenceQueue;
* <p>Unlike a normal phantom reference, this reference will be cleared automatically.
*
* @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public abstract class FinalizablePhantomReference<T> extends PhantomReference<T>
implements FinalizableReference {
diff --git a/guava/src/com/google/common/base/FinalizableReference.java b/guava/src/com/google/common/base/FinalizableReference.java
index ab2dec3..acc6efc 100644
--- a/guava/src/com/google/common/base/FinalizableReference.java
+++ b/guava/src/com/google/common/base/FinalizableReference.java
@@ -21,7 +21,7 @@ package com.google.common.base;
*
* @see FinalizableReferenceQueue
* @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public interface FinalizableReference {
/**
diff --git a/guava/src/com/google/common/base/FinalizableReferenceQueue.java b/guava/src/com/google/common/base/FinalizableReferenceQueue.java
index ddd27fa..7ff90e8 100644
--- a/guava/src/com/google/common/base/FinalizableReferenceQueue.java
+++ b/guava/src/com/google/common/base/FinalizableReferenceQueue.java
@@ -89,7 +89,7 @@ import javax.annotation.Nullable;
* </pre>
*
* @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public class FinalizableReferenceQueue implements Closeable {
/*
@@ -134,9 +134,10 @@ public class FinalizableReferenceQueue implements Closeable {
/** Reference to Finalizer.startFinalizer(). */
private static final Method startFinalizer;
+
static {
- Class<?> finalizer = loadFinalizer(
- new SystemLoader(), new DecoupledLoader(), new DirectLoader());
+ Class<?> finalizer =
+ loadFinalizer(new SystemLoader(), new DecoupledLoader(), new DirectLoader());
startFinalizer = getStartFinalizer(finalizer);
}
@@ -166,8 +167,11 @@ public class FinalizableReferenceQueue implements Closeable {
} catch (IllegalAccessException impossible) {
throw new AssertionError(impossible); // startFinalizer() is public
} catch (Throwable t) {
- logger.log(Level.INFO, "Failed to start reference finalizer thread."
- + " Reference cleanup will only occur when new references are created.", t);
+ logger.log(
+ Level.INFO,
+ "Failed to start reference finalizer thread."
+ + " Reference cleanup will only occur when new references are created.",
+ t);
}
this.threadStarted = threadStarted;
@@ -241,8 +245,7 @@ public class FinalizableReferenceQueue implements Closeable {
static class SystemLoader implements FinalizerLoader {
// This is used by the ClassLoader-leak test in FinalizableReferenceQueueTest to disable
// finding Finalizer on the system class path even if it is there.
- @VisibleForTesting
- static boolean disabled;
+ @VisibleForTesting static boolean disabled;
@Override
public Class<?> loadFinalizer() {
@@ -275,10 +278,11 @@ public class FinalizableReferenceQueue implements Closeable {
* it would prevent our class loader from getting garbage collected.
*/
static class DecoupledLoader implements FinalizerLoader {
- private static final String LOADING_ERROR = "Could not load Finalizer in its own class loader."
- + "Loading Finalizer in the current class loader instead. As a result, you will not be able"
- + "to garbage collect this class loader. To support reclaiming this class loader, either"
- + "resolve the underlying issue, or move Google Collections to your system class path.";
+ private static final String LOADING_ERROR =
+ "Could not load Finalizer in its own class loader. Loading Finalizer in the current class "
+ + "loader instead. As a result, you will not be able to garbage collect this class "
+ + "loader. To support reclaiming this class loader, either resolve the underlying "
+ + "issue, or move Guava to your system class path.";
@Override
public Class<?> loadFinalizer() {
@@ -350,10 +354,7 @@ public class FinalizableReferenceQueue implements Closeable {
static Method getStartFinalizer(Class<?> finalizer) {
try {
return finalizer.getMethod(
- "startFinalizer",
- Class.class,
- ReferenceQueue.class,
- PhantomReference.class);
+ "startFinalizer", Class.class, ReferenceQueue.class, PhantomReference.class);
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
diff --git a/guava/src/com/google/common/base/FinalizableSoftReference.java b/guava/src/com/google/common/base/FinalizableSoftReference.java
index 88607f4..74726c1 100644
--- a/guava/src/com/google/common/base/FinalizableSoftReference.java
+++ b/guava/src/com/google/common/base/FinalizableSoftReference.java
@@ -25,7 +25,7 @@ import java.lang.ref.SoftReference;
* ReferenceQueue}.
*
* @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public abstract class FinalizableSoftReference<T> extends SoftReference<T>
implements FinalizableReference {
diff --git a/guava/src/com/google/common/base/FinalizableWeakReference.java b/guava/src/com/google/common/base/FinalizableWeakReference.java
index b14d023..d128df5 100644
--- a/guava/src/com/google/common/base/FinalizableWeakReference.java
+++ b/guava/src/com/google/common/base/FinalizableWeakReference.java
@@ -25,7 +25,7 @@ import java.lang.ref.WeakReference;
* ReferenceQueue}.
*
* @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public abstract class FinalizableWeakReference<T> extends WeakReference<T>
implements FinalizableReference {
diff --git a/guava/src/com/google/common/base/Function.java b/guava/src/com/google/common/base/Function.java
index f969b4a..f39e2ea 100644
--- a/guava/src/com/google/common/base/Function.java
+++ b/guava/src/com/google/common/base/Function.java
@@ -26,11 +26,11 @@ import javax.annotation.Nullable;
* <p>The {@link Functions} class provides common functions and related utilites.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the use of {@code
+ * "https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code
* Function}</a>.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public interface Function<F, T> {
@@ -48,7 +48,8 @@ public interface Function<F, T> {
* @throws NullPointerException if {@code input} is null and this function does not accept null
* arguments
*/
- @Nullable T apply(@Nullable F input);
+ @Nullable
+ T apply(@Nullable F input);
/**
* Indicates whether another object is equal to this function.
diff --git a/guava/src/com/google/common/base/FunctionalEquivalence.java b/guava/src/com/google/common/base/FunctionalEquivalence.java
index a5e9c13..c28f6b9 100644
--- a/guava/src/com/google/common/base/FunctionalEquivalence.java
+++ b/guava/src/com/google/common/base/FunctionalEquivalence.java
@@ -33,45 +33,47 @@ import javax.annotation.Nullable;
*/
@Beta
@GwtCompatible
-final class FunctionalEquivalence<F, T> extends Equivalence<F>
- implements Serializable {
+final class FunctionalEquivalence<F, T> extends Equivalence<F> implements Serializable {
private static final long serialVersionUID = 0;
private final Function<F, ? extends T> function;
private final Equivalence<T> resultEquivalence;
- FunctionalEquivalence(
- Function<F, ? extends T> function, Equivalence<T> resultEquivalence) {
+ FunctionalEquivalence(Function<F, ? extends T> function, Equivalence<T> resultEquivalence) {
this.function = checkNotNull(function);
this.resultEquivalence = checkNotNull(resultEquivalence);
}
- @Override protected boolean doEquivalent(F a, F b) {
+ @Override
+ protected boolean doEquivalent(F a, F b) {
return resultEquivalence.equivalent(function.apply(a), function.apply(b));
}
- @Override protected int doHash(F a) {
+ @Override
+ protected int doHash(F a) {
return resultEquivalence.hash(function.apply(a));
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof FunctionalEquivalence) {
FunctionalEquivalence<?, ?> that = (FunctionalEquivalence<?, ?>) obj;
- return function.equals(that.function)
- && resultEquivalence.equals(that.resultEquivalence);
+ return function.equals(that.function) && resultEquivalence.equals(that.resultEquivalence);
}
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Objects.hashCode(function, resultEquivalence);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return resultEquivalence + ".onResultOf(" + function + ")";
}
}
diff --git a/guava/src/com/google/common/base/Functions.java b/guava/src/com/google/common/base/Functions.java
index 669fd9a..da5626d 100644
--- a/guava/src/com/google/common/base/Functions.java
+++ b/guava/src/com/google/common/base/Functions.java
@@ -25,22 +25,24 @@ import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
import java.util.Map;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Static utility methods pertaining to {@code Function} instances.
*
* <p>All methods return serializable functions as long as they're given serializable parameters.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the use of {@code
+ * "https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code
* Function}</a>.
*
* @author Mike Bostock
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
+ at CheckReturnValue
public final class Functions {
private Functions() {}
@@ -62,12 +64,13 @@ public final class Functions {
@Override
public String apply(Object o) {
- checkNotNull(o); // eager for GWT.
+ checkNotNull(o); // eager for GWT.
return o.toString();
}
- @Override public String toString() {
- return "toString";
+ @Override
+ public String toString() {
+ return "Functions.toStringFunction()";
}
}
@@ -90,8 +93,9 @@ public final class Functions {
return o;
}
- @Override public String toString() {
- return "identity";
+ @Override
+ public String toString() {
+ return "Functions.identity()";
}
}
@@ -122,7 +126,8 @@ public final class Functions {
return result;
}
- @Override public boolean equals(@Nullable Object o) {
+ @Override
+ public boolean equals(@Nullable Object o) {
if (o instanceof FunctionForMapNoDefault) {
FunctionForMapNoDefault<?, ?> that = (FunctionForMapNoDefault<?, ?>) o;
return map.equals(that.map);
@@ -130,12 +135,14 @@ public final class Functions {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return map.hashCode();
}
- @Override public String toString() {
- return "forMap(" + map + ")";
+ @Override
+ public String toString() {
+ return "Functions.forMap(" + map + ")";
}
private static final long serialVersionUID = 0;
@@ -170,7 +177,8 @@ public final class Functions {
return (result != null || map.containsKey(key)) ? result : defaultValue;
}
- @Override public boolean equals(@Nullable Object o) {
+ @Override
+ public boolean equals(@Nullable Object o) {
if (o instanceof ForMapWithDefault) {
ForMapWithDefault<?, ?> that = (ForMapWithDefault<?, ?>) o;
return map.equals(that.map) && Objects.equal(defaultValue, that.defaultValue);
@@ -178,12 +186,15 @@ public final class Functions {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Objects.hashCode(map, defaultValue);
}
- @Override public String toString() {
- return "forMap(" + map + ", defaultValue=" + defaultValue + ")";
+ @Override
+ public String toString() {
+ // TODO(cpovirk): maybe remove "defaultValue=" to make this look like the method call does
+ return "Functions.forMap(" + map + ", defaultValue=" + defaultValue + ")";
}
private static final long serialVersionUID = 0;
@@ -216,7 +227,8 @@ public final class Functions {
return g.apply(f.apply(a));
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof FunctionComposition) {
FunctionComposition<?, ?, ?> that = (FunctionComposition<?, ?, ?>) obj;
return f.equals(that.f) && g.equals(that.g);
@@ -224,11 +236,14 @@ public final class Functions {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return f.hashCode() ^ g.hashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
+ // TODO(cpovirk): maybe make this look like the method call does ("Functions.compose(...)")
return g + "(" + f + ")";
}
@@ -258,7 +273,8 @@ public final class Functions {
return predicate.apply(t);
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof PredicateFunction) {
PredicateFunction<?> that = (PredicateFunction<?>) obj;
return predicate.equals(that.predicate);
@@ -266,12 +282,14 @@ public final class Functions {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return predicate.hashCode();
}
- @Override public String toString() {
- return "forPredicate(" + predicate + ")";
+ @Override
+ public String toString() {
+ return "Functions.forPredicate(" + predicate + ")";
}
private static final long serialVersionUID = 0;
@@ -299,7 +317,8 @@ public final class Functions {
return value;
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof ConstantFunction) {
ConstantFunction<?> that = (ConstantFunction<?>) obj;
return Objects.equal(value, that.value);
@@ -307,12 +326,14 @@ public final class Functions {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return (value == null) ? 0 : value.hashCode();
}
- @Override public String toString() {
- return "constant(" + value + ")";
+ @Override
+ public String toString() {
+ return "Functions.constant(" + value + ")";
}
private static final long serialVersionUID = 0;
@@ -321,7 +342,7 @@ public final class Functions {
/**
* Returns a function that always returns the result of invoking {@link Supplier#get} on {@code
* supplier}, regardless of its input.
- *
+ *
* @since 10.0
*/
@Beta
@@ -331,33 +352,37 @@ public final class Functions {
/** @see Functions#forSupplier*/
private static class SupplierFunction<T> implements Function<Object, T>, Serializable {
-
+
private final Supplier<T> supplier;
private SupplierFunction(Supplier<T> supplier) {
this.supplier = checkNotNull(supplier);
}
- @Override public T apply(@Nullable Object input) {
+ @Override
+ public T apply(@Nullable Object input) {
return supplier.get();
}
-
- @Override public boolean equals(@Nullable Object obj) {
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof SupplierFunction) {
SupplierFunction<?> that = (SupplierFunction<?>) obj;
return this.supplier.equals(that.supplier);
}
return false;
}
-
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
return supplier.hashCode();
}
-
- @Override public String toString() {
- return "forSupplier(" + supplier + ")";
+
+ @Override
+ public String toString() {
+ return "Functions.forSupplier(" + supplier + ")";
}
-
+
private static final long serialVersionUID = 0;
}
}
diff --git a/guava/src/com/google/common/base/Joiner.java b/guava/src/com/google/common/base/Joiner.java
index 7f4a80a..df78e3b 100644
--- a/guava/src/com/google/common/base/Joiner.java
+++ b/guava/src/com/google/common/base/Joiner.java
@@ -55,18 +55,19 @@ import javax.annotation.Nullable;
* Joiner joiner = Joiner.on(',');
* joiner.skipNulls(); // does nothing!
* return joiner.join("wrong", null, "wrong");}</pre>
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/StringsExplained#Joiner">{@code Joiner}</a>.
+ * "https://github.com/google/guava/wiki/StringsExplained#joiner">{@code Joiner}</a>.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public class Joiner {
/**
* Returns a joiner which automatically places {@code separator} between consecutive elements.
*/
+ @CheckReturnValue
public static Joiner on(String separator) {
return new Joiner(separator);
}
@@ -74,6 +75,7 @@ public class Joiner {
/**
* Returns a joiner which automatically places {@code separator} between consecutive elements.
*/
+ @CheckReturnValue
public static Joiner on(char separator) {
return new Joiner(String.valueOf(separator));
}
@@ -127,7 +129,7 @@ public class Joiner {
*/
public final <A extends Appendable> A appendTo(
A appendable, @Nullable Object first, @Nullable Object second, Object... rest)
- throws IOException {
+ throws IOException {
return appendTo(appendable, iterable(first, second, rest));
}
@@ -179,6 +181,7 @@ public class Joiner {
* Returns a string containing the string representation of each of {@code parts}, using the
* previously configured separator between each.
*/
+ @CheckReturnValue
public final String join(Iterable<?> parts) {
return join(parts.iterator());
}
@@ -189,6 +192,7 @@ public class Joiner {
*
* @since 11.0
*/
+ @CheckReturnValue
public final String join(Iterator<?> parts) {
return appendTo(new StringBuilder(), parts).toString();
}
@@ -197,6 +201,7 @@ public class Joiner {
* Returns a string containing the string representation of each of {@code parts}, using the
* previously configured separator between each.
*/
+ @CheckReturnValue
public final String join(Object[] parts) {
return join(Arrays.asList(parts));
}
@@ -205,6 +210,7 @@ public class Joiner {
* Returns a string containing the string representation of each argument, using the previously
* configured separator between each.
*/
+ @CheckReturnValue
public final String join(@Nullable Object first, @Nullable Object second, Object... rest) {
return join(iterable(first, second, rest));
}
@@ -217,15 +223,18 @@ public class Joiner {
public Joiner useForNull(final String nullText) {
checkNotNull(nullText);
return new Joiner(this) {
- @Override CharSequence toString(@Nullable Object part) {
+ @Override
+ CharSequence toString(@Nullable Object part) {
return (part == null) ? nullText : Joiner.this.toString(part);
}
- @Override public Joiner useForNull(String nullText) {
+ @Override
+ public Joiner useForNull(String nullText) {
throw new UnsupportedOperationException("already specified useForNull");
}
- @Override public Joiner skipNulls() {
+ @Override
+ public Joiner skipNulls() {
throw new UnsupportedOperationException("already specified useForNull");
}
};
@@ -238,8 +247,8 @@ public class Joiner {
@CheckReturnValue
public Joiner skipNulls() {
return new Joiner(this) {
- @Override public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts)
- throws IOException {
+ @Override
+ public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
checkNotNull(appendable, "appendable");
checkNotNull(parts, "parts");
while (parts.hasNext()) {
@@ -259,11 +268,13 @@ public class Joiner {
return appendable;
}
- @Override public Joiner useForNull(String nullText) {
+ @Override
+ public Joiner useForNull(String nullText) {
throw new UnsupportedOperationException("already specified skipNulls");
}
- @Override public MapJoiner withKeyValueSeparator(String kvs) {
+ @Override
+ public MapJoiner withKeyValueSeparator(String kvs) {
throw new UnsupportedOperationException("can't use .skipNulls() with maps");
}
};
@@ -294,7 +305,7 @@ public class Joiner {
* key1=[A, B]&key2=C}.
* </ul>
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public static final class MapJoiner {
private final Joiner joiner;
@@ -326,6 +337,7 @@ public class Joiner {
* Returns a string containing the string representation of each entry of {@code map}, using the
* previously configured separator and key-value separator.
*/
+ @CheckReturnValue
public String join(Map<?, ?> map) {
return join(map.entrySet());
}
@@ -404,6 +416,7 @@ public class Joiner {
* @since 10.0
*/
@Beta
+ @CheckReturnValue
public String join(Iterable<? extends Entry<?, ?>> entries) {
return join(entries.iterator());
}
@@ -415,6 +428,7 @@ public class Joiner {
* @since 11.0
*/
@Beta
+ @CheckReturnValue
public String join(Iterator<? extends Entry<?, ?>> entries) {
return appendTo(new StringBuilder(), entries).toString();
}
@@ -430,7 +444,7 @@ public class Joiner {
}
CharSequence toString(Object part) {
- checkNotNull(part); // checkNotNull for GWT (do not optimize).
+ checkNotNull(part); // checkNotNull for GWT (do not optimize).
return (part instanceof CharSequence) ? (CharSequence) part : part.toString();
}
@@ -438,11 +452,13 @@ public class Joiner {
final Object first, final Object second, final Object[] rest) {
checkNotNull(rest);
return new AbstractList<Object>() {
- @Override public int size() {
+ @Override
+ public int size() {
return rest.length + 2;
}
- @Override public Object get(int index) {
+ @Override
+ public Object get(int index) {
switch (index) {
case 0:
return first;
diff --git a/guava/src/com/google/common/base/MoreObjects.java b/guava/src/com/google/common/base/MoreObjects.java
index ef4f804..f87a892 100644
--- a/guava/src/com/google/common/base/MoreObjects.java
+++ b/guava/src/com/google/common/base/MoreObjects.java
@@ -20,6 +20,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
+import java.util.Arrays;
+
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -27,7 +30,7 @@ import javax.annotation.Nullable;
* {@link java.util.Objects}.
*
* <p>See the Guava User Guide on <a
- * href="http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained">writing
+ * href="https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained">writing
* {@code Object} methods with {@code MoreObjects}</a>.
*
* @author Laurence Gonsalves
@@ -46,8 +49,9 @@ public final class MoreObjects {
*
* @return {@code first} if it is non-null; otherwise {@code second} if it is non-null
* @throws NullPointerException if both {@code first} and {@code second} are null
- * @since 18.0 (since 3.0 as {@code Objects.firstNonNull()}.
+ * @since 18.0 (since 3.0 as {@code Objects.firstNonNull()}).
*/
+ @CheckReturnValue
public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
return first != null ? first : checkNotNull(second);
}
@@ -89,10 +93,11 @@ public final class MoreObjects {
*
* @param self the object to generate the string for (typically {@code this}), used only for its
* class name
- * @since 18.0 (since 2.0 as {@code Objects.toStringHelper()}.
+ * @since 18.0 (since 2.0 as {@code Objects.toStringHelper()}).
*/
+ @CheckReturnValue
public static ToStringHelper toStringHelper(Object self) {
- return new ToStringHelper(simpleName(self.getClass()));
+ return new ToStringHelper(self.getClass().getSimpleName());
}
/**
@@ -103,10 +108,11 @@ public final class MoreObjects {
* <p>Note that in GWT, class names are often obfuscated.
*
* @param clazz the {@link Class} of the instance
- * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}.
+ * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}).
*/
+ @CheckReturnValue
public static ToStringHelper toStringHelper(Class<?> clazz) {
- return new ToStringHelper(simpleName(clazz));
+ return new ToStringHelper(clazz.getSimpleName());
}
/**
@@ -115,40 +121,18 @@ public final class MoreObjects {
* Object#getClass()}.
*
* @param className the name of the instance type
- * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}.
+ * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}).
*/
+ @CheckReturnValue
public static ToStringHelper toStringHelper(String className) {
return new ToStringHelper(className);
}
/**
- * {@link Class#getSimpleName()} is not GWT compatible yet, so we
- * provide our own implementation.
- */
- // Package-private so Objects can call it.
- static String simpleName(Class<?> clazz) {
- String name = clazz.getName();
-
- // the nth anonymous class has a class name ending in "Outer$n"
- // and local inner classes have names ending in "Outer.$1Inner"
- name = name.replaceAll("\\$[0-9]+", "\\$");
-
- // we want the name of the inner class all by its lonesome
- int start = name.lastIndexOf('$');
-
- // if this isn't an inner class, just find the start of the
- // top level class name.
- if (start == -1) {
- start = name.lastIndexOf('.');
- }
- return name.substring(start + 1);
- }
-
- /**
* Support class for {@link MoreObjects#toStringHelper}.
*
* @author Jason Lee
- * @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}.
+ * @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}).
*/
public static final class ToStringHelper {
private final String className;
@@ -168,7 +152,7 @@ public final class MoreObjects {
* properties with null value. The order of calling this method, relative
* to the {@code add()}/{@code addValue()} methods, is not significant.
*
- * @since 18.0 (since 12.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 12.0 as {@code Objects.ToStringHelper.omitNullValues()}).
*/
public ToStringHelper omitNullValues() {
omitNullValues = true;
@@ -189,7 +173,7 @@ public final class MoreObjects {
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
*/
public ToStringHelper add(String name, boolean value) {
return addHolder(name, String.valueOf(value));
@@ -199,7 +183,7 @@ public final class MoreObjects {
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
*/
public ToStringHelper add(String name, char value) {
return addHolder(name, String.valueOf(value));
@@ -209,7 +193,7 @@ public final class MoreObjects {
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
*/
public ToStringHelper add(String name, double value) {
return addHolder(name, String.valueOf(value));
@@ -219,7 +203,7 @@ public final class MoreObjects {
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
*/
public ToStringHelper add(String name, float value) {
return addHolder(name, String.valueOf(value));
@@ -229,7 +213,7 @@ public final class MoreObjects {
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
*/
public ToStringHelper add(String name, int value) {
return addHolder(name, String.valueOf(value));
@@ -239,7 +223,7 @@ public final class MoreObjects {
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
*/
public ToStringHelper add(String name, long value) {
return addHolder(name, String.valueOf(value));
@@ -250,8 +234,6 @@ public final class MoreObjects {
*
* <p>It is strongly encouraged to use {@link #add(String, Object)} instead
* and give value a readable name.
- *
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
*/
public ToStringHelper addValue(@Nullable Object value) {
return addHolder(value);
@@ -260,12 +242,10 @@ public final class MoreObjects {
/**
* Adds an unnamed value to the formatted output.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
- *
* <p>It is strongly encouraged to use {@link #add(String, boolean)} instead
* and give value a readable name.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
*/
public ToStringHelper addValue(boolean value) {
return addHolder(String.valueOf(value));
@@ -277,7 +257,7 @@ public final class MoreObjects {
* <p>It is strongly encouraged to use {@link #add(String, char)} instead
* and give value a readable name.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
*/
public ToStringHelper addValue(char value) {
return addHolder(String.valueOf(value));
@@ -289,7 +269,7 @@ public final class MoreObjects {
* <p>It is strongly encouraged to use {@link #add(String, double)} instead
* and give value a readable name.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
*/
public ToStringHelper addValue(double value) {
return addHolder(String.valueOf(value));
@@ -301,7 +281,7 @@ public final class MoreObjects {
* <p>It is strongly encouraged to use {@link #add(String, float)} instead
* and give value a readable name.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
*/
public ToStringHelper addValue(float value) {
return addHolder(String.valueOf(value));
@@ -313,7 +293,7 @@ public final class MoreObjects {
* <p>It is strongly encouraged to use {@link #add(String, int)} instead
* and give value a readable name.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
*/
public ToStringHelper addValue(int value) {
return addHolder(String.valueOf(value));
@@ -325,7 +305,7 @@ public final class MoreObjects {
* <p>It is strongly encouraged to use {@link #add(String, long)} instead
* and give value a readable name.
*
- * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
+ * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
*/
public ToStringHelper addValue(long value) {
return addHolder(String.valueOf(value));
@@ -341,22 +321,31 @@ public final class MoreObjects {
* limited reuse of the helper instance. The helper allows duplication of
* properties (multiple name/value pairs with the same name can be added).
*/
- @Override public String toString() {
+ @CheckReturnValue
+ @Override
+ public String toString() {
// create a copy to keep it consistent in case value changes
boolean omitNullValuesSnapshot = omitNullValues;
String nextSeparator = "";
- StringBuilder builder = new StringBuilder(32).append(className)
- .append('{');
- for (ValueHolder valueHolder = holderHead.next; valueHolder != null;
+ StringBuilder builder = new StringBuilder(32).append(className).append('{');
+ for (ValueHolder valueHolder = holderHead.next;
+ valueHolder != null;
valueHolder = valueHolder.next) {
- if (!omitNullValuesSnapshot || valueHolder.value != null) {
+ Object value = valueHolder.value;
+ if (!omitNullValuesSnapshot || value != null) {
builder.append(nextSeparator);
nextSeparator = ", ";
if (valueHolder.name != null) {
builder.append(valueHolder.name).append('=');
}
- builder.append(valueHolder.value);
+ if (value != null && value.getClass().isArray()) {
+ Object[] objectArray = {value};
+ String arrayString = Arrays.deepToString(objectArray);
+ builder.append(arrayString.substring(1, arrayString.length() - 1));
+ } else {
+ builder.append(value);
+ }
}
}
return builder.append('}').toString();
diff --git a/guava/src/com/google/common/base/Objects.java b/guava/src/com/google/common/base/Objects.java
index 214ac55..62817da 100644
--- a/guava/src/com/google/common/base/Objects.java
+++ b/guava/src/com/google/common/base/Objects.java
@@ -29,11 +29,11 @@ import javax.annotation.Nullable;
* Helper functions that can operate on any {@code Object}.
*
* <p>See the Guava User Guide on <a
- * href="http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained">writing
+ * href="https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained">writing
* {@code Object} methods with {@code Objects}</a>.
*
* @author Laurence Gonsalves
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public final class Objects {
@@ -80,6 +80,7 @@ public final class Objects {
* <p><b>Note for Java 7 and later:</b> This method should be treated as
* deprecated; use {@link java.util.Objects#hash} instead.
*/
+ @CheckReturnValue
public static int hashCode(@Nullable Object... objects) {
return Arrays.hashCode(objects);
}
@@ -125,9 +126,10 @@ public final class Objects {
* @deprecated Use {@link MoreObjects#toStringHelper(Object)} instead. This
* method is scheduled for removal in June 2016.
*/
+ @CheckReturnValue
@Deprecated
public static ToStringHelper toStringHelper(Object self) {
- return new ToStringHelper(MoreObjects.simpleName(self.getClass()));
+ return new ToStringHelper(self.getClass().getSimpleName());
}
/**
@@ -142,9 +144,10 @@ public final class Objects {
* @deprecated Use {@link MoreObjects#toStringHelper(Class)} instead. This
* method is scheduled for removal in June 2016.
*/
+ @CheckReturnValue
@Deprecated
public static ToStringHelper toStringHelper(Class<?> clazz) {
- return new ToStringHelper(MoreObjects.simpleName(clazz));
+ return new ToStringHelper(clazz.getSimpleName());
}
/**
@@ -157,6 +160,7 @@ public final class Objects {
* @deprecated Use {@link MoreObjects#toStringHelper(String)} instead. This
* method is scheduled for removal in June 2016.
*/
+ @CheckReturnValue
@Deprecated
public static ToStringHelper toStringHelper(String className) {
return new ToStringHelper(className);
@@ -181,6 +185,7 @@ public final class Objects {
* @deprecated Use {@link MoreObjects#firstNonNull} instead. This method is
* scheduled for removal in June 2016.
*/
+ @CheckReturnValue
@Deprecated
public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
return MoreObjects.firstNonNull(first, second);
@@ -382,13 +387,14 @@ public final class Objects {
* limited reuse of the helper instance. The helper allows duplication of
* properties (multiple name/value pairs with the same name can be added).
*/
- @Override public String toString() {
+ @Override
+ public String toString() {
// create a copy to keep it consistent in case value changes
boolean omitNullValuesSnapshot = omitNullValues;
String nextSeparator = "";
- StringBuilder builder = new StringBuilder(32).append(className)
- .append('{');
- for (ValueHolder valueHolder = holderHead.next; valueHolder != null;
+ StringBuilder builder = new StringBuilder(32).append(className).append('{');
+ for (ValueHolder valueHolder = holderHead.next;
+ valueHolder != null;
valueHolder = valueHolder.next) {
if (!omitNullValuesSnapshot || valueHolder.value != null) {
builder.append(nextSeparator);
diff --git a/guava/src/com/google/common/base/Optional.java b/guava/src/com/google/common/base/Optional.java
index a0a0425..6c4724b 100644
--- a/guava/src/com/google/common/base/Optional.java
+++ b/guava/src/com/google/common/base/Optional.java
@@ -25,6 +25,7 @@ import java.io.Serializable;
import java.util.Iterator;
import java.util.Set;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -47,7 +48,7 @@ import javax.annotation.Nullable;
* have no value" (present in the map, with value {@code Optional.absent()})
* <li>To wrap nullable references for storage in a collection that does not support
* {@code null} (though there are
- * <a href="http://code.google.com/p/guava-libraries/wiki/LivingWithNullHostileCollections">
+ * <a href="https://github.com/google/guava/wiki/LivingWithNullHostileCollections">
* several other approaches to this</a> that should be considered first)
* </ul>
*
@@ -58,8 +59,25 @@ import javax.annotation.Nullable;
* <p>This class is not intended as a direct analogue of any existing "option" or "maybe"
* construct from other programming environments, though it may bear some similarities.
*
+ * <p><b>Comparison to {@code java.util.Optional} (JDK 8 and higher):</b> A new {@code Optional}
+ * class was added for Java 8. The two classes are extremely similar, but incompatible (they cannot
+ * share a common supertype). <i>All</i> known differences are listed either here or with the
+ * relevant methods below.
+ *
+ * <ul>
+ * <li>This class is serializable; {@code java.util.Optional} is not.
+ * <li>{@code java.util.Optional} has the additional methods {@code ifPresent}, {@code filter},
+ * {@code flatMap}, and {@code orElseThrow}.
+ * <li>{@code java.util} offers the primitive-specialized versions {@code OptionalInt}, {@code
+ * OptionalLong} and {@code OptionalDouble}, the use of which is recommended; Guava does not
+ * have these.
+ * </ul>
+ *
+ * <p><b>There are no plans to deprecate this class in the foreseeable future.</b> However, we do
+ * gently recommend that you prefer the new, standard Java class whenever possible.
+ *
* <p>See the Guava User Guide article on <a
- * href="http://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional">
+ * href="https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained#optional">
* using {@code Optional}</a>.
*
* @param <T> the type of instance that can be contained. {@code Optional} is naturally
@@ -69,17 +87,26 @@ import javax.annotation.Nullable;
* @author Kevin Bourrillion
* @since 10.0
*/
+ at CheckReturnValue
@GwtCompatible(serializable = true)
public abstract class Optional<T> implements Serializable {
/**
* Returns an {@code Optional} instance with no contained reference.
+ *
+ * <p><b>Comparison to {@code java.util.Optional}:</b> this method is equivalent to Java 8's
+ * {@code Optional.empty}.
*/
public static <T> Optional<T> absent() {
return Absent.withType();
}
/**
- * Returns an {@code Optional} instance containing the given non-null reference.
+ * Returns an {@code Optional} instance containing the given non-null reference. To have {@code
+ * null} treated as {@link #absent}, use {@link #fromNullable} instead.
+ *
+ * <p><b>Comparison to {@code java.util.Optional}:</b> no differences.
+ *
+ * @throws NullPointerException if {@code reference} is null
*/
public static <T> Optional<T> of(T reference) {
return new Present<T>(checkNotNull(reference));
@@ -88,6 +115,9 @@ public abstract class Optional<T> implements Serializable {
/**
* If {@code nullableReference} is non-null, returns an {@code Optional} instance containing that
* reference; otherwise returns {@link Optional#absent}.
+ *
+ * <p><b>Comparison to {@code java.util.Optional}:</b> this method is equivalent to Java 8's
+ * {@code Optional.ofNullable}.
*/
public static <T> Optional<T> fromNullable(@Nullable T nullableReference) {
return (nullableReference == null)
@@ -99,6 +129,8 @@ public abstract class Optional<T> implements Serializable {
/**
* Returns {@code true} if this holder contains a (non-null) instance.
+ *
+ * <p><b>Comparison to {@code java.util.Optional}:</b> no differences.
*/
public abstract boolean isPresent();
@@ -106,8 +138,13 @@ public abstract class Optional<T> implements Serializable {
* Returns the contained instance, which must be present. If the instance might be
* absent, use {@link #or(Object)} or {@link #orNull} instead.
*
+ * <p><b>Comparison to {@code java.util.Optional}:</b> when the value is absent, this method
+ * throws {@link IllegalStateException}, whereas the Java 8 counterpart throws {@link
+ * NoSuchElementException}.
+ *
* @throws IllegalStateException if the instance is absent ({@link #isPresent} returns
- * {@code false})
+ * {@code false}); depending on this <i>specific</i> exception type (over the more general
+ * {@link RuntimeException}) is discouraged
*/
public abstract T get();
@@ -139,20 +176,34 @@ public abstract class Optional<T> implements Serializable {
* FluentIterable<? extends Number> numbers = getSomeNumbers();
* Optional<Number> first = (Optional) numbers.first();
* Number value = first.or(0.5); // fine}</pre>
+ *
+ * <p><b>Comparison to {@code java.util.Optional}:</b> this method is similar to Java 8's
+ * {@code Optional.orElse}, but will not accept {@code null} as a {@code defaultValue} ({@link
+ * #orNull} must be used instead). As a result, the value returned by this method is guaranteed
+ * non-null, which is not the case for the {@code java.util} equivalent.
*/
public abstract T or(T defaultValue);
/**
* Returns this {@code Optional} if it has a value present; {@code secondChoice}
* otherwise.
+ *
+ * <p><b>Comparison to {@code java.util.Optional}:</b> this method has no equivalent in Java 8's
+ * {@code Optional} class; write {@code thisOptional.isPresent() ? thisOptional : secondChoice}
+ * instead.
*/
public abstract Optional<T> or(Optional<? extends T> secondChoice);
/**
- * Returns the contained instance if it is present; {@code supplier.get()} otherwise. If the
- * supplier returns {@code null}, a {@link NullPointerException} is thrown.
+ * Returns the contained instance if it is present; {@code supplier.get()} otherwise.
*
- * @throws NullPointerException if the supplier returns {@code null}
+ * <p><b>Comparison to {@code java.util.Optional}:</b> this method is similar to Java 8's
+ * {@code Optional.orElseGet}, except when {@code supplier} returns {@code null}. In this case
+ * this method throws an exception, whereas the Java 8 method returns the {@code null} to the
+ * caller.
+ *
+ * @throws NullPointerException if this optional's value is absent and the supplier returns
+ * {@code null}
*/
@Beta
public abstract T or(Supplier<? extends T> supplier);
@@ -160,6 +211,9 @@ public abstract class Optional<T> implements Serializable {
/**
* Returns the contained instance if it is present; {@code null} otherwise. If the
* instance is known to be present, use {@link #get()} instead.
+ *
+ * <p><b>Comparison to {@code java.util.Optional}:</b> this method is equivalent to Java 8's
+ * {@code Optional.orElse(null)}.
*/
@Nullable
public abstract T orNull();
@@ -168,17 +222,30 @@ public abstract class Optional<T> implements Serializable {
* Returns an immutable singleton {@link Set} whose only element is the contained instance
* if it is present; an empty immutable {@link Set} otherwise.
*
+ * <p><b>Comparison to {@code java.util.Optional}:</b> this method has no equivalent in Java 8's
+ * {@code Optional} class. However, this common usage: <pre> {@code
+ *
+ * for (Foo foo : possibleFoo.asSet()) {
+ * doSomethingWith(foo);
+ * }}</pre>
+ *
+ * ... can be replaced with: <pre> {@code
+ *
+ * possibleFoo.ifPresent(foo -> doSomethingWith(foo));}</pre>
+ *
* @since 11.0
*/
public abstract Set<T> asSet();
/**
* If the instance is present, it is transformed with the given {@link Function}; otherwise,
- * {@link Optional#absent} is returned. If the function returns {@code null}, a
- * {@link NullPointerException} is thrown.
+ * {@link Optional#absent} is returned.
*
- * @throws NullPointerException if the function returns {@code null}
+ * <p><b>Comparison to {@code java.util.Optional}:</b> this method is similar to Java 8's
+ * {@code Optional.map}, except when {@code function} returns {@code null}. In this case this
+ * method throws an exception, whereas the Java 8 method returns {@code Optional.absent()}.
*
+ * @throws NullPointerException if the function returns {@code null}
* @since 12.0
*/
public abstract <V> Optional<V> transform(Function<? super T, V> function);
@@ -188,19 +255,26 @@ public abstract class Optional<T> implements Serializable {
* the contained references are {@linkplain Object#equals equal} to each other or both
* are absent. Note that {@code Optional} instances of differing parameterized types can
* be equal.
+ *
+ * <p><b>Comparison to {@code java.util.Optional}:</b> no differences.
*/
@Override
public abstract boolean equals(@Nullable Object object);
/**
* Returns a hash code for this instance.
+ *
+ * <p><b>Comparison to {@code java.util.Optional}:</b> this class leaves the specific choice of
+ * hash code unspecified, unlike the Java 8 equivalent.
*/
@Override
public abstract int hashCode();
/**
- * Returns a string representation for this instance. The form of this string
- * representation is unspecified.
+ * Returns a string representation for this instance.
+ *
+ * <p><b>Comparison to {@code java.util.Optional}:</b> this class leaves the specific string
+ * representation unspecified, unlike the Java 8 equivalent.
*/
@Override
public abstract String toString();
@@ -210,6 +284,10 @@ public abstract class Optional<T> implements Serializable {
* skipping over occurrences of {@link Optional#absent}. Iterators are unmodifiable and are
* evaluated lazily.
*
+ * <p><b>Comparison to {@code java.util.Optional}:</b> this method has no equivalent in Java 8's
+ * {@code Optional} class; use
+ * {@code optionals.stream().filter(Optional::isPresent).map(Optional::get)} instead.
+ *
* @since 11.0 (generics widened in 13.0)
*/
@Beta
diff --git a/guava/src/com/google/common/base/PairwiseEquivalence.java b/guava/src/com/google/common/base/PairwiseEquivalence.java
index 23ab539..d409d24 100644
--- a/guava/src/com/google/common/base/PairwiseEquivalence.java
+++ b/guava/src/com/google/common/base/PairwiseEquivalence.java
@@ -24,8 +24,7 @@ import java.util.Iterator;
import javax.annotation.Nullable;
@GwtCompatible(serializable = true)
-final class PairwiseEquivalence<T> extends Equivalence<Iterable<T>>
- implements Serializable {
+final class PairwiseEquivalence<T> extends Equivalence<Iterable<T>> implements Serializable {
final Equivalence<? super T> elementEquivalence;
diff --git a/guava/src/com/google/common/base/Preconditions.java b/guava/src/com/google/common/base/Preconditions.java
index bd84f05..a27205f 100644
--- a/guava/src/com/google/common/base/Preconditions.java
+++ b/guava/src/com/google/common/base/Preconditions.java
@@ -69,7 +69,7 @@ import javax.annotation.Nullable;
* <p>It is of course possible to use the methods of this class to check for invalid conditions
* which are <i>not the caller's fault</i>. Doing so is <b>not recommended</b> because it is
* misleading to future readers of the code and of stack traces. See
- * <a href="http://code.google.com/p/guava-libraries/wiki/ConditionalFailuresExplained">Conditional
+ * <a href="https://github.com/google/guava/wiki/ConditionalFailuresExplained">Conditional
* failures explained</a> in the Guava User Guide for more advice.
*
* <h3>{@code java.util.Objects.requireNonNull()}</h3>
@@ -87,11 +87,11 @@ import javax.annotation.Nullable;
* <h3>More information</h3>
*
* <p>See the Guava User Guide on
- * <a href="http://code.google.com/p/guava-libraries/wiki/PreconditionsExplained">using {@code
+ * <a href="https://github.com/google/guava/wiki/PreconditionsExplained">using {@code
* Preconditions}</a>.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public final class Preconditions {
@@ -138,7 +138,8 @@ public final class Preconditions {
* @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or
* {@code errorMessageArgs} is null (don't let this happen)
*/
- public static void checkArgument(boolean expression,
+ public static void checkArgument(
+ boolean expression,
@Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs) {
if (!expression) {
@@ -190,7 +191,8 @@ public final class Preconditions {
* @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or
* {@code errorMessageArgs} is null (don't let this happen)
*/
- public static void checkState(boolean expression,
+ public static void checkState(
+ boolean expression,
@Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs) {
if (!expression) {
@@ -242,9 +244,8 @@ public final class Preconditions {
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
- public static <T> T checkNotNull(T reference,
- @Nullable String errorMessageTemplate,
- @Nullable Object... errorMessageArgs) {
+ public static <T> T checkNotNull(
+ T reference, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) {
if (reference == null) {
// If either of these parameters is null, the right thing happens anyway
throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs));
@@ -303,8 +304,7 @@ public final class Preconditions {
* @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
- public static int checkElementIndex(
- int index, int size, @Nullable String desc) {
+ public static int checkElementIndex(int index, int size, @Nullable String desc) {
// Carefully optimized for execution by hotspot (explanatory comment above)
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
diff --git a/guava/src/com/google/common/base/Predicate.java b/guava/src/com/google/common/base/Predicate.java
index 7345742..43defb8 100644
--- a/guava/src/com/google/common/base/Predicate.java
+++ b/guava/src/com/google/common/base/Predicate.java
@@ -26,11 +26,11 @@ import javax.annotation.Nullable;
* <p>The {@link Predicates} class provides common predicates and related utilities.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the use of {@code
+ * "https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code
* Predicate}</a>.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public interface Predicate<T> {
diff --git a/guava/src/com/google/common/base/Predicates.java b/guava/src/com/google/common/base/Predicates.java
index ba5fe1f..67c04cf 100644
--- a/guava/src/com/google/common/base/Predicates.java
+++ b/guava/src/com/google/common/base/Predicates.java
@@ -29,6 +29,7 @@ import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -38,12 +39,13 @@ import javax.annotation.Nullable;
* serializable parameters.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the
+ * "https://github.com/google/guava/wiki/FunctionalExplained">the
* use of {@code Predicate}</a>.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class Predicates {
private Predicates() {}
@@ -102,8 +104,7 @@ public final class Predicates {
* components} is empty, the returned predicate will always evaluate to {@code
* true}.
*/
- public static <T> Predicate<T> and(
- Iterable<? extends Predicate<? super T>> components) {
+ public static <T> Predicate<T> and(Iterable<? extends Predicate<? super T>> components) {
return new AndPredicate<T>(defensiveCopy(components));
}
@@ -126,10 +127,8 @@ public final class Predicates {
* order, and evaluation will be "short-circuited" as soon as a false
* predicate is found.
*/
- public static <T> Predicate<T> and(Predicate<? super T> first,
- Predicate<? super T> second) {
- return new AndPredicate<T>(Predicates.<T>asList(
- checkNotNull(first), checkNotNull(second)));
+ public static <T> Predicate<T> and(Predicate<? super T> first, Predicate<? super T> second) {
+ return new AndPredicate<T>(Predicates.<T>asList(checkNotNull(first), checkNotNull(second)));
}
/**
@@ -141,8 +140,7 @@ public final class Predicates {
* components} is empty, the returned predicate will always evaluate to {@code
* false}.
*/
- public static <T> Predicate<T> or(
- Iterable<? extends Predicate<? super T>> components) {
+ public static <T> Predicate<T> or(Iterable<? extends Predicate<? super T>> components) {
return new OrPredicate<T>(defensiveCopy(components));
}
@@ -165,10 +163,8 @@ public final class Predicates {
* order, and evaluation will be "short-circuited" as soon as a
* true predicate is found.
*/
- public static <T> Predicate<T> or(
- Predicate<? super T> first, Predicate<? super T> second) {
- return new OrPredicate<T>(Predicates.<T>asList(
- checkNotNull(first), checkNotNull(second)));
+ public static <T> Predicate<T> or(Predicate<? super T> first, Predicate<? super T> second) {
+ return new OrPredicate<T>(Predicates.<T>asList(checkNotNull(first), checkNotNull(second)));
}
/**
@@ -176,9 +172,7 @@ public final class Predicates {
* tested {@code equals()} the given target or both are null.
*/
public static <T> Predicate<T> equalTo(@Nullable T target) {
- return (target == null)
- ? Predicates.<T>isNull()
- : new IsEqualToPredicate<T>(target);
+ return (target == null) ? Predicates.<T>isNull() : new IsEqualToPredicate<T>(target);
}
/**
@@ -275,37 +269,49 @@ public final class Predicates {
enum ObjectPredicate implements Predicate<Object> {
/** @see Predicates#alwaysTrue() */
ALWAYS_TRUE {
- @Override public boolean apply(@Nullable Object o) {
+ @Override
+ public boolean apply(@Nullable Object o) {
return true;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.alwaysTrue()";
}
},
/** @see Predicates#alwaysFalse() */
ALWAYS_FALSE {
- @Override public boolean apply(@Nullable Object o) {
+ @Override
+ public boolean apply(@Nullable Object o) {
return false;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.alwaysFalse()";
}
},
/** @see Predicates#isNull() */
IS_NULL {
- @Override public boolean apply(@Nullable Object o) {
+ @Override
+ public boolean apply(@Nullable Object o) {
return o == null;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.isNull()";
}
},
/** @see Predicates#notNull() */
NOT_NULL {
- @Override public boolean apply(@Nullable Object o) {
+ @Override
+ public boolean apply(@Nullable Object o) {
return o != null;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.notNull()";
}
};
@@ -323,23 +329,31 @@ public final class Predicates {
NotPredicate(Predicate<T> predicate) {
this.predicate = checkNotNull(predicate);
}
+
@Override
public boolean apply(@Nullable T t) {
return !predicate.apply(t);
}
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
return ~predicate.hashCode();
}
- @Override public boolean equals(@Nullable Object obj) {
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof NotPredicate) {
NotPredicate<?> that = (NotPredicate<?>) obj;
return predicate.equals(that.predicate);
}
return false;
}
- @Override public String toString() {
- return "Predicates.not(" + predicate.toString() + ")";
+
+ @Override
+ public String toString() {
+ return "Predicates.not(" + predicate + ")";
}
+
private static final long serialVersionUID = 0;
}
@@ -352,6 +366,7 @@ public final class Predicates {
private AndPredicate(List<? extends Predicate<? super T>> components) {
this.components = components;
}
+
@Override
public boolean apply(@Nullable T t) {
// Avoid using the Iterator to avoid generating garbage (issue 820).
@@ -362,20 +377,27 @@ public final class Predicates {
}
return true;
}
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
// add a random number to avoid collisions with OrPredicate
return components.hashCode() + 0x12472c2c;
}
- @Override public boolean equals(@Nullable Object obj) {
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof AndPredicate) {
AndPredicate<?> that = (AndPredicate<?>) obj;
return components.equals(that.components);
}
return false;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.and(" + COMMA_JOINER.join(components) + ")";
}
+
private static final long serialVersionUID = 0;
}
@@ -386,6 +408,7 @@ public final class Predicates {
private OrPredicate(List<? extends Predicate<? super T>> components) {
this.components = components;
}
+
@Override
public boolean apply(@Nullable T t) {
// Avoid using the Iterator to avoid generating garbage (issue 820).
@@ -396,106 +419,134 @@ public final class Predicates {
}
return false;
}
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
// add a random number to avoid collisions with AndPredicate
return components.hashCode() + 0x053c91cf;
}
- @Override public boolean equals(@Nullable Object obj) {
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof OrPredicate) {
OrPredicate<?> that = (OrPredicate<?>) obj;
return components.equals(that.components);
}
return false;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.or(" + COMMA_JOINER.join(components) + ")";
}
+
private static final long serialVersionUID = 0;
}
/** @see Predicates#equalTo(Object) */
- private static class IsEqualToPredicate<T>
- implements Predicate<T>, Serializable {
+ private static class IsEqualToPredicate<T> implements Predicate<T>, Serializable {
private final T target;
private IsEqualToPredicate(T target) {
this.target = target;
}
+
@Override
public boolean apply(T t) {
return target.equals(t);
}
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
return target.hashCode();
}
- @Override public boolean equals(@Nullable Object obj) {
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof IsEqualToPredicate) {
IsEqualToPredicate<?> that = (IsEqualToPredicate<?>) obj;
return target.equals(that.target);
}
return false;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.equalTo(" + target + ")";
}
+
private static final long serialVersionUID = 0;
}
/** @see Predicates#instanceOf(Class) */
@GwtIncompatible("Class.isInstance")
- private static class InstanceOfPredicate
- implements Predicate<Object>, Serializable {
+ private static class InstanceOfPredicate implements Predicate<Object>, Serializable {
private final Class<?> clazz;
private InstanceOfPredicate(Class<?> clazz) {
this.clazz = checkNotNull(clazz);
}
+
@Override
public boolean apply(@Nullable Object o) {
return clazz.isInstance(o);
}
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
return clazz.hashCode();
}
- @Override public boolean equals(@Nullable Object obj) {
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof InstanceOfPredicate) {
InstanceOfPredicate that = (InstanceOfPredicate) obj;
return clazz == that.clazz;
}
return false;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.instanceOf(" + clazz.getName() + ")";
}
+
private static final long serialVersionUID = 0;
}
/** @see Predicates#assignableFrom(Class) */
@GwtIncompatible("Class.isAssignableFrom")
- private static class AssignableFromPredicate
- implements Predicate<Class<?>>, Serializable {
+ private static class AssignableFromPredicate implements Predicate<Class<?>>, Serializable {
private final Class<?> clazz;
private AssignableFromPredicate(Class<?> clazz) {
this.clazz = checkNotNull(clazz);
}
+
@Override
public boolean apply(Class<?> input) {
return clazz.isAssignableFrom(input);
}
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
return clazz.hashCode();
}
- @Override public boolean equals(@Nullable Object obj) {
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof AssignableFromPredicate) {
AssignableFromPredicate that = (AssignableFromPredicate) obj;
return clazz == that.clazz;
}
return false;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Predicates.assignableFrom(" + clazz.getName() + ")";
}
+
private static final long serialVersionUID = 0;
}
@@ -518,7 +569,8 @@ public final class Predicates {
}
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof InPredicate) {
InPredicate<?> that = (InPredicate<?>) obj;
return target.equals(that.target);
@@ -526,19 +578,21 @@ public final class Predicates {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return target.hashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Predicates.in(" + target + ")";
}
+
private static final long serialVersionUID = 0;
}
/** @see Predicates#compose(Predicate, Function) */
- private static class CompositionPredicate<A, B>
- implements Predicate<A>, Serializable {
+ private static class CompositionPredicate<A, B> implements Predicate<A>, Serializable {
final Predicate<B> p;
final Function<A, ? extends B> f;
@@ -552,7 +606,8 @@ public final class Predicates {
return p.apply(f.apply(a));
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof CompositionPredicate) {
CompositionPredicate<?, ?> that = (CompositionPredicate<?, ?>) obj;
return f.equals(that.f) && p.equals(that.p);
@@ -560,12 +615,15 @@ public final class Predicates {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return f.hashCode() ^ p.hashCode();
}
- @Override public String toString() {
- return p.toString() + "(" + f.toString() + ")";
+ @Override
+ public String toString() {
+ // TODO(cpovirk): maybe make this look like the method call does ("Predicates.compose(...)")
+ return p + "(" + f + ")";
}
private static final long serialVersionUID = 0;
@@ -573,8 +631,7 @@ public final class Predicates {
/** @see Predicates#contains(Pattern) */
@GwtIncompatible("Only used by other GWT-incompatible code.")
- private static class ContainsPatternPredicate
- implements Predicate<CharSequence>, Serializable {
+ private static class ContainsPatternPredicate implements Predicate<CharSequence>, Serializable {
final Pattern pattern;
ContainsPatternPredicate(Pattern pattern) {
@@ -586,14 +643,16 @@ public final class Predicates {
return pattern.matcher(t).find();
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
// Pattern uses Object.hashCode, so we have to reach
// inside to build a hashCode consistent with equals.
return Objects.hashCode(pattern.pattern(), pattern.flags());
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof ContainsPatternPredicate) {
ContainsPatternPredicate that = (ContainsPatternPredicate) obj;
@@ -605,7 +664,8 @@ public final class Predicates {
return false;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
String patternString = Objects.toStringHelper(pattern)
.add("pattern", pattern.pattern())
.add("pattern.flags", pattern.flags())
@@ -618,14 +678,14 @@ public final class Predicates {
/** @see Predicates#containsPattern(String) */
@GwtIncompatible("Only used by other GWT-incompatible code.")
- private static class ContainsPatternFromStringPredicate
- extends ContainsPatternPredicate {
+ private static class ContainsPatternFromStringPredicate extends ContainsPatternPredicate {
ContainsPatternFromStringPredicate(String string) {
super(Pattern.compile(string));
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Predicates.containsPattern(" + pattern.pattern() + ")";
}
diff --git a/guava/src/com/google/common/base/Present.java b/guava/src/com/google/common/base/Present.java
index bcde922..b5103b7 100644
--- a/guava/src/com/google/common/base/Present.java
+++ b/guava/src/com/google/common/base/Present.java
@@ -36,43 +36,54 @@ final class Present<T> extends Optional<T> {
this.reference = reference;
}
- @Override public boolean isPresent() {
+ @Override
+ public boolean isPresent() {
return true;
}
- @Override public T get() {
+ @Override
+ public T get() {
return reference;
}
- @Override public T or(T defaultValue) {
+ @Override
+ public T or(T defaultValue) {
checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)");
return reference;
}
- @Override public Optional<T> or(Optional<? extends T> secondChoice) {
+ @Override
+ public Optional<T> or(Optional<? extends T> secondChoice) {
checkNotNull(secondChoice);
return this;
}
- @Override public T or(Supplier<? extends T> supplier) {
+ @Override
+ public T or(Supplier<? extends T> supplier) {
checkNotNull(supplier);
return reference;
}
- @Override public T orNull() {
+ @Override
+ public T orNull() {
return reference;
}
- @Override public Set<T> asSet() {
+ @Override
+ public Set<T> asSet() {
return Collections.singleton(reference);
}
-
- @Override public <V> Optional<V> transform(Function<? super T, V> function) {
- return new Present<V>(checkNotNull(function.apply(reference),
- "the Function passed to Optional.transform() must not return null."));
+
+ @Override
+ public <V> Optional<V> transform(Function<? super T, V> function) {
+ return new Present<V>(
+ checkNotNull(
+ function.apply(reference),
+ "the Function passed to Optional.transform() must not return null."));
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object instanceof Present) {
Present<?> other = (Present<?>) object;
return reference.equals(other.reference);
@@ -80,11 +91,13 @@ final class Present<T> extends Optional<T> {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return 0x598df91c + reference.hashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Optional.of(" + reference + ")";
}
diff --git a/guava/src/com/google/common/base/SmallCharMatcher.java b/guava/src/com/google/common/base/SmallCharMatcher.java
index efd173d..2bea0eb 100644
--- a/guava/src/com/google/common/base/SmallCharMatcher.java
+++ b/guava/src/com/google/common/base/SmallCharMatcher.java
@@ -18,7 +18,7 @@ package com.google.common.base;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.CharMatcher.FastMatcher;
+import com.google.common.base.CharMatcher.NamedFastMatcher;
import java.util.BitSet;
@@ -29,20 +29,19 @@ import java.util.BitSet;
* @author Christopher Swenson
*/
@GwtIncompatible("no precomputation is done in GWT")
-final class SmallCharMatcher extends FastMatcher {
+final class SmallCharMatcher extends NamedFastMatcher {
static final int MAX_SIZE = 1023;
private final char[] table;
private final boolean containsZero;
private final long filter;
- private SmallCharMatcher(char[] table, long filter, boolean containsZero,
- String description) {
+ private SmallCharMatcher(char[] table, long filter, boolean containsZero, String description) {
super(description);
this.table = table;
this.filter = filter;
this.containsZero = containsZero;
}
-
+
private static final int C1 = 0xcc9e2d51;
private static final int C2 = 0x1b873593;
@@ -68,13 +67,14 @@ final class SmallCharMatcher extends FastMatcher {
// Represents how tightly we can pack things, as a maximum.
private static final double DESIRED_LOAD_FACTOR = 0.5;
- /**
- * Returns an array size suitable for the backing array of a hash table that
- * uses open addressing with linear probing in its implementation. The
- * returned size is the smallest power of two that can hold setSize elements
- * with the desired load factor.
- */
- @VisibleForTesting static int chooseTableSize(int setSize) {
+ /**
+ * Returns an array size suitable for the backing array of a hash table that
+ * uses open addressing with linear probing in its implementation. The
+ * returned size is the smallest power of two that can hold setSize elements
+ * with the desired load factor.
+ */
+ @VisibleForTesting
+ static int chooseTableSize(int setSize) {
if (setSize == 1) {
return 2;
}
diff --git a/guava/src/com/google/common/base/Splitter.java b/guava/src/com/google/common/base/Splitter.java
index ce0fc01..6c45952 100644
--- a/guava/src/com/google/common/base/Splitter.java
+++ b/guava/src/com/google/common/base/Splitter.java
@@ -90,7 +90,7 @@ import javax.annotation.CheckReturnValue;
* note that a round-trip between the two should be assumed to be lossy.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/StringsExplained#Splitter">
+ * "https://github.com/google/guava/wiki/StringsExplained#splitter">
* {@code Splitter}</a>.
*
* @author Julien Silland
@@ -110,8 +110,7 @@ public final class Splitter {
this(strategy, false, CharMatcher.NONE, Integer.MAX_VALUE);
}
- private Splitter(Strategy strategy, boolean omitEmptyStrings,
- CharMatcher trimmer, int limit) {
+ private Splitter(Strategy strategy, boolean omitEmptyStrings, CharMatcher trimmer, int limit) {
this.strategy = strategy;
this.omitEmptyStrings = omitEmptyStrings;
this.trimmer = trimmer;
@@ -126,6 +125,7 @@ public final class Splitter {
* @param separator the character to recognize as a separator
* @return a splitter, with default settings, that recognizes that separator
*/
+ @CheckReturnValue
public static Splitter on(char separator) {
return on(CharMatcher.is(separator));
}
@@ -140,23 +140,27 @@ public final class Splitter {
* character is a separator
* @return a splitter, with default settings, that uses this matcher
*/
+ @CheckReturnValue
public static Splitter on(final CharMatcher separatorMatcher) {
checkNotNull(separatorMatcher);
- return new Splitter(new Strategy() {
- @Override public SplittingIterator iterator(
- Splitter splitter, final CharSequence toSplit) {
- return new SplittingIterator(splitter, toSplit) {
- @Override int separatorStart(int start) {
- return separatorMatcher.indexIn(toSplit, start);
- }
+ return new Splitter(
+ new Strategy() {
+ @Override
+ public SplittingIterator iterator(Splitter splitter, final CharSequence toSplit) {
+ return new SplittingIterator(splitter, toSplit) {
+ @Override
+ int separatorStart(int start) {
+ return separatorMatcher.indexIn(toSplit, start);
+ }
- @Override int separatorEnd(int separatorPosition) {
- return separatorPosition + 1;
+ @Override
+ int separatorEnd(int separatorPosition) {
+ return separatorPosition + 1;
+ }
+ };
}
- };
- }
- });
+ });
}
/**
@@ -167,36 +171,40 @@ public final class Splitter {
* @param separator the literal, nonempty string to recognize as a separator
* @return a splitter, with default settings, that recognizes that separator
*/
+ @CheckReturnValue
public static Splitter on(final String separator) {
- checkArgument(separator.length() != 0,
- "The separator may not be the empty string.");
-
- return new Splitter(new Strategy() {
- @Override public SplittingIterator iterator(
- Splitter splitter, CharSequence toSplit) {
- return new SplittingIterator(splitter, toSplit) {
- @Override public int separatorStart(int start) {
- int separatorLength = separator.length();
-
- positions:
- for (int p = start, last = toSplit.length() - separatorLength;
- p <= last; p++) {
- for (int i = 0; i < separatorLength; i++) {
- if (toSplit.charAt(i + p) != separator.charAt(i)) {
- continue positions;
+ checkArgument(separator.length() != 0, "The separator may not be the empty string.");
+ if (separator.length() == 1) {
+ return Splitter.on(separator.charAt(0));
+ }
+ return new Splitter(
+ new Strategy() {
+ @Override
+ public SplittingIterator iterator(Splitter splitter, CharSequence toSplit) {
+ return new SplittingIterator(splitter, toSplit) {
+ @Override
+ public int separatorStart(int start) {
+ int separatorLength = separator.length();
+
+ positions:
+ for (int p = start, last = toSplit.length() - separatorLength; p <= last; p++) {
+ for (int i = 0; i < separatorLength; i++) {
+ if (toSplit.charAt(i + p) != separator.charAt(i)) {
+ continue positions;
+ }
+ }
+ return p;
}
+ return -1;
}
- return p;
- }
- return -1;
- }
- @Override public int separatorEnd(int separatorPosition) {
- return separatorPosition + separator.length();
+ @Override
+ public int separatorEnd(int separatorPosition) {
+ return separatorPosition + separator.length();
+ }
+ };
}
- };
- }
- });
+ });
}
/**
@@ -211,27 +219,33 @@ public final class Splitter {
* @throws IllegalArgumentException if {@code separatorPattern} matches the
* empty string
*/
+ @CheckReturnValue
@GwtIncompatible("java.util.regex")
public static Splitter on(final Pattern separatorPattern) {
checkNotNull(separatorPattern);
- checkArgument(!separatorPattern.matcher("").matches(),
- "The pattern may not match the empty string: %s", separatorPattern);
-
- return new Splitter(new Strategy() {
- @Override public SplittingIterator iterator(
- final Splitter splitter, CharSequence toSplit) {
- final Matcher matcher = separatorPattern.matcher(toSplit);
- return new SplittingIterator(splitter, toSplit) {
- @Override public int separatorStart(int start) {
- return matcher.find(start) ? matcher.start() : -1;
- }
+ checkArgument(
+ !separatorPattern.matcher("").matches(),
+ "The pattern may not match the empty string: %s",
+ separatorPattern);
+
+ return new Splitter(
+ new Strategy() {
+ @Override
+ public SplittingIterator iterator(final Splitter splitter, CharSequence toSplit) {
+ final Matcher matcher = separatorPattern.matcher(toSplit);
+ return new SplittingIterator(splitter, toSplit) {
+ @Override
+ public int separatorStart(int start) {
+ return matcher.find(start) ? matcher.start() : -1;
+ }
- @Override public int separatorEnd(int separatorPosition) {
- return matcher.end();
+ @Override
+ public int separatorEnd(int separatorPosition) {
+ return matcher.end();
+ }
+ };
}
- };
- }
- });
+ });
}
/**
@@ -249,6 +263,7 @@ public final class Splitter {
* @throws IllegalArgumentException if {@code separatorPattern} matches the
* empty string
*/
+ @CheckReturnValue
@GwtIncompatible("java.util.regex")
public static Splitter onPattern(String separatorPattern) {
return on(Pattern.compile(separatorPattern));
@@ -273,24 +288,28 @@ public final class Splitter {
* pieces
* @throws IllegalArgumentException if {@code length} is zero or negative
*/
+ @CheckReturnValue
public static Splitter fixedLength(final int length) {
checkArgument(length > 0, "The length may not be less than 1");
- return new Splitter(new Strategy() {
- @Override public SplittingIterator iterator(
- final Splitter splitter, CharSequence toSplit) {
- return new SplittingIterator(splitter, toSplit) {
- @Override public int separatorStart(int start) {
- int nextChunkStart = start + length;
- return (nextChunkStart < toSplit.length() ? nextChunkStart : -1);
- }
+ return new Splitter(
+ new Strategy() {
+ @Override
+ public SplittingIterator iterator(final Splitter splitter, CharSequence toSplit) {
+ return new SplittingIterator(splitter, toSplit) {
+ @Override
+ public int separatorStart(int start) {
+ int nextChunkStart = start + length;
+ return (nextChunkStart < toSplit.length() ? nextChunkStart : -1);
+ }
- @Override public int separatorEnd(int separatorPosition) {
- return separatorPosition;
+ @Override
+ public int separatorEnd(int separatorPosition) {
+ return separatorPosition;
+ }
+ };
}
- };
- }
- });
+ });
}
/**
@@ -319,7 +338,8 @@ public final class Splitter {
/**
* Returns a splitter that behaves equivalently to {@code this} splitter but
* stops splitting after it reaches the limit.
- * The limit defines the maximum number of items returned by the iterator.
+ * The limit defines the maximum number of items returned by the iterator, or
+ * the maximum size of the list returned by {@link #splitToList}.
*
* <p>For example,
* {@code Splitter.on(',').limit(3).split("a,b,c,d")} returns an iterable
@@ -329,9 +349,9 @@ public final class Splitter {
* returns an iterable containing {@code ["a", "b", "c,d"}.
* When trim is requested, all entries, including the last are trimmed. Hence
* {@code Splitter.on(',').limit(3).trimResults().split(" a , b , c , d ")}
- * results in @{code ["a", "b", "c , d"]}.
+ * results in {@code ["a", "b", "c , d"]}.
*
- * @param limit the maximum number of items returns
+ * @param limit the maximum number of items returned
* @return a splitter with the desired configuration
* @since 9.0
*/
@@ -382,14 +402,18 @@ public final class Splitter {
* @param sequence the sequence of characters to split
* @return an iteration over the segments split from the parameter.
*/
+ @CheckReturnValue
public Iterable<String> split(final CharSequence sequence) {
checkNotNull(sequence);
return new Iterable<String>() {
- @Override public Iterator<String> iterator() {
+ @Override
+ public Iterator<String> iterator() {
return splittingIterator(sequence);
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return Joiner.on(", ")
.appendTo(new StringBuilder().append('['), this)
.append(']')
@@ -411,6 +435,7 @@ public final class Splitter {
* @return an immutable list of the segments split from the parameter
* @since 15.0
*/
+ @CheckReturnValue
@Beta
public List<String> splitToList(CharSequence sequence) {
checkNotNull(sequence);
@@ -471,8 +496,7 @@ public final class Splitter {
*/
@Beta
public static final class MapSplitter {
- private static final String INVALID_ENTRY_MESSAGE =
- "Chunk [%s] is not a valid entry";
+ private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry";
private final Splitter outerSplitter;
private final Splitter entrySplitter;
@@ -496,6 +520,7 @@ public final class Splitter {
* @throws IllegalArgumentException if the specified sequence does not split
* into valid map entries, or if there are duplicate keys
*/
+ @CheckReturnValue
public Map<String, String> split(CharSequence sequence) {
Map<String, String> map = new LinkedHashMap<String, String>();
for (String entry : outerSplitter.split(sequence)) {
@@ -547,7 +572,8 @@ public final class Splitter {
this.toSplit = toSplit;
}
- @Override protected String computeNext() {
+ @Override
+ protected String computeNext() {
/*
* The returned string will be from the end of the last match to the
* beginning of the next one. nextStart is the start position of the
diff --git a/guava/src/com/google/common/base/StandardSystemProperty.java b/guava/src/com/google/common/base/StandardSystemProperty.java
index a3c1766..2173458 100644
--- a/guava/src/com/google/common/base/StandardSystemProperty.java
+++ b/guava/src/com/google/common/base/StandardSystemProperty.java
@@ -19,6 +19,7 @@ package com.google.common.base;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -29,6 +30,7 @@ import javax.annotation.Nullable;
*/
@Beta
@GwtIncompatible("java.lang.System#getProperty")
+ at CheckReturnValue
public enum StandardSystemProperty {
/** Java Runtime Environment version. */
@@ -140,7 +142,8 @@ public enum StandardSystemProperty {
/**
* Returns a string representation of this system property.
*/
- @Override public String toString() {
+ @Override
+ public String toString() {
return key() + "=" + value();
}
}
diff --git a/guava/src/com/google/common/base/Stopwatch.java b/guava/src/com/google/common/base/Stopwatch.java
index f11fe62..51be949 100644
--- a/guava/src/com/google/common/base/Stopwatch.java
+++ b/guava/src/com/google/common/base/Stopwatch.java
@@ -26,12 +26,14 @@ import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
+import java.util.Locale;
import java.util.concurrent.TimeUnit;
+import javax.annotation.CheckReturnValue;
+
/**
* An object that measures elapsed time in nanoseconds. It is useful to measure
* elapsed time using this class instead of direct calls to {@link
@@ -71,7 +73,6 @@ import java.util.concurrent.TimeUnit;
* @author Kevin Bourrillion
* @since 10.0
*/
- at Beta
@GwtCompatible(emulated = true)
public final class Stopwatch {
private final Ticker ticker;
@@ -85,6 +86,7 @@ public final class Stopwatch {
*
* @since 15.0
*/
+ @CheckReturnValue
public static Stopwatch createUnstarted() {
return new Stopwatch();
}
@@ -95,6 +97,7 @@ public final class Stopwatch {
*
* @since 15.0
*/
+ @CheckReturnValue
public static Stopwatch createUnstarted(Ticker ticker) {
return new Stopwatch(ticker);
}
@@ -105,6 +108,7 @@ public final class Stopwatch {
*
* @since 15.0
*/
+ @CheckReturnValue
public static Stopwatch createStarted() {
return new Stopwatch().start();
}
@@ -115,28 +119,15 @@ public final class Stopwatch {
*
* @since 15.0
*/
+ @CheckReturnValue
public static Stopwatch createStarted(Ticker ticker) {
return new Stopwatch(ticker).start();
}
- /**
- * Creates (but does not start) a new stopwatch using {@link System#nanoTime}
- * as its time source.
- *
- * @deprecated Use {@link Stopwatch#createUnstarted()} instead.
- */
- @Deprecated
Stopwatch() {
- this(Ticker.systemTicker());
+ this.ticker = Ticker.systemTicker();
}
- /**
- * Creates (but does not start) a new stopwatch, using the specified time
- * source.
- *
- * @deprecated Use {@link Stopwatch#createUnstarted(Ticker)} instead.
- */
- @Deprecated
Stopwatch(Ticker ticker) {
this.ticker = checkNotNull(ticker, "ticker");
}
@@ -146,6 +137,7 @@ public final class Stopwatch {
* and {@link #stop()} has not been called since the last call to {@code
* start()}.
*/
+ @CheckReturnValue
public boolean isRunning() {
return isRunning;
}
@@ -204,6 +196,7 @@ public final class Stopwatch {
*
* @since 14.0 (since 10.0 as {@code elapsedTime()})
*/
+ @CheckReturnValue
public long elapsed(TimeUnit desiredUnit) {
return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
}
@@ -212,14 +205,15 @@ public final class Stopwatch {
* Returns a string representation of the current elapsed time.
*/
@GwtIncompatible("String.format()")
- @Override public String toString() {
+ @Override
+ public String toString() {
long nanos = elapsedNanos();
TimeUnit unit = chooseUnit(nanos);
double value = (double) nanos / NANOSECONDS.convert(1, unit);
// Too bad this functionality is not exposed as a regular method call
- return String.format("%.4g %s", value, abbreviate(unit));
+ return String.format(Locale.ROOT, "%.4g %s", value, abbreviate(unit));
}
private static TimeUnit chooseUnit(long nanos) {
diff --git a/guava/src/com/google/common/base/Strings.java b/guava/src/com/google/common/base/Strings.java
index fa4d0bd..4e4c2f6 100644
--- a/guava/src/com/google/common/base/Strings.java
+++ b/guava/src/com/google/common/base/Strings.java
@@ -24,6 +24,7 @@ import com.google.common.annotations.VisibleForTesting;
import java.util.Formatter;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -33,6 +34,7 @@ import javax.annotation.Nullable;
* @author Kevin Bourrillion
* @since 3.0
*/
+ at CheckReturnValue
@GwtCompatible
public final class Strings {
private Strings() {}
@@ -96,7 +98,7 @@ public final class Strings {
* @return the padded string
*/
public static String padStart(String string, int minLength, char padChar) {
- checkNotNull(string); // eager for GWT.
+ checkNotNull(string); // eager for GWT.
if (string.length() >= minLength) {
return string;
}
@@ -128,7 +130,7 @@ public final class Strings {
* @return the padded string
*/
public static String padEnd(String string, int minLength, char padChar) {
- checkNotNull(string); // eager for GWT.
+ checkNotNull(string); // eager for GWT.
if (string.length() >= minLength) {
return string;
}
@@ -152,7 +154,7 @@ public final class Strings {
* @throws IllegalArgumentException if {@code count} is negative
*/
public static String repeat(String string, int count) {
- checkNotNull(string); // eager for GWT.
+ checkNotNull(string); // eager for GWT.
if (count <= 1) {
checkArgument(count >= 0, "invalid count: %s", count);
@@ -164,8 +166,7 @@ public final class Strings {
final long longSize = (long) len * (long) count;
final int size = (int) longSize;
if (size != longSize) {
- throw new ArrayIndexOutOfBoundsException(
- "Required array size too large: " + longSize);
+ throw new ArrayIndexOutOfBoundsException("Required array size too large: " + longSize);
}
final char[] array = new char[size];
@@ -215,8 +216,7 @@ public final class Strings {
int maxSuffixLength = Math.min(a.length(), b.length());
int s = 0;
- while (s < maxSuffixLength
- && a.charAt(a.length() - s - 1) == b.charAt(b.length() - s - 1)) {
+ while (s < maxSuffixLength && a.charAt(a.length() - s - 1) == b.charAt(b.length() - s - 1)) {
s++;
}
if (validSurrogatePairAt(a, a.length() - s - 1)
@@ -232,7 +232,8 @@ public final class Strings {
*/
@VisibleForTesting
static boolean validSurrogatePairAt(CharSequence string, int index) {
- return index >= 0 && index <= (string.length() - 2)
+ return index >= 0
+ && index <= (string.length() - 2)
&& Character.isHighSurrogate(string.charAt(index))
&& Character.isLowSurrogate(string.charAt(index + 1));
}
diff --git a/guava/src/com/google/common/base/Supplier.java b/guava/src/com/google/common/base/Supplier.java
index ab8b908..aca0b32 100644
--- a/guava/src/com/google/common/base/Supplier.java
+++ b/guava/src/com/google/common/base/Supplier.java
@@ -24,7 +24,7 @@ import com.google.common.annotations.GwtCompatible;
* guarantees are implied by this interface.
*
* @author Harry Heymann
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public interface Supplier<T> {
diff --git a/guava/src/com/google/common/base/Suppliers.java b/guava/src/com/google/common/base/Suppliers.java
index fab3bec..838e64f 100644
--- a/guava/src/com/google/common/base/Suppliers.java
+++ b/guava/src/com/google/common/base/Suppliers.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.VisibleForTesting;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -33,8 +34,9 @@ import javax.annotation.Nullable;
*
* @author Laurence Gonsalves
* @author Harry Heymann
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
+ at CheckReturnValue
@GwtCompatible
public final class Suppliers {
private Suppliers() {}
@@ -46,15 +48,13 @@ public final class Suppliers {
* {@code function} to that value. Note that the resulting supplier will not
* call {@code supplier} or invoke {@code function} until it is called.
*/
- public static <F, T> Supplier<T> compose(
- Function<? super F, T> function, Supplier<F> supplier) {
+ public static <F, T> Supplier<T> compose(Function<? super F, T> function, Supplier<F> supplier) {
Preconditions.checkNotNull(function);
Preconditions.checkNotNull(supplier);
return new SupplierComposition<F, T>(function, supplier);
}
- private static class SupplierComposition<F, T>
- implements Supplier<T>, Serializable {
+ private static class SupplierComposition<F, T> implements Supplier<T>, Serializable {
final Function<? super F, T> function;
final Supplier<F> supplier;
@@ -63,11 +63,13 @@ public final class Suppliers {
this.supplier = supplier;
}
- @Override public T get() {
+ @Override
+ public T get() {
return function.apply(supplier.get());
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof SupplierComposition) {
SupplierComposition<?, ?> that = (SupplierComposition<?, ?>) obj;
return function.equals(that.function) && supplier.equals(that.supplier);
@@ -75,11 +77,13 @@ public final class Suppliers {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Objects.hashCode(function, supplier);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Suppliers.compose(" + function + ", " + supplier + ")";
}
@@ -92,9 +96,10 @@ public final class Suppliers {
* {@code get()}. See:
* <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
*
- * <p>The returned supplier is thread-safe. The supplier's serialized form
- * does not contain the cached value, which will be recalculated when {@code
- * get()} is called on the reserialized instance.
+ * <p>The returned supplier is thread-safe. The delegate's {@code get()}
+ * method will be invoked at most once. The supplier's serialized form does
+ * not contain the cached value, which will be recalculated when {@code get()}
+ * is called on the reserialized instance.
*
* <p>If {@code delegate} is an instance created by an earlier call to {@code
* memoize}, it is returned directly.
@@ -117,7 +122,8 @@ public final class Suppliers {
this.delegate = delegate;
}
- @Override public T get() {
+ @Override
+ public T get() {
// A 2-field variant of Double Checked Locking.
if (!initialized) {
synchronized (this) {
@@ -132,7 +138,8 @@ public final class Suppliers {
return value;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Suppliers.memoize(" + delegate + ")";
}
@@ -162,22 +169,22 @@ public final class Suppliers {
return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
}
- @VisibleForTesting static class ExpiringMemoizingSupplier<T>
- implements Supplier<T>, Serializable {
+ @VisibleForTesting
+ static class ExpiringMemoizingSupplier<T> implements Supplier<T>, Serializable {
final Supplier<T> delegate;
final long durationNanos;
transient volatile T value;
// The special value 0 means "not yet initialized".
transient volatile long expirationNanos;
- ExpiringMemoizingSupplier(
- Supplier<T> delegate, long duration, TimeUnit unit) {
+ ExpiringMemoizingSupplier(Supplier<T> delegate, long duration, TimeUnit unit) {
this.delegate = Preconditions.checkNotNull(delegate);
this.durationNanos = unit.toNanos(duration);
Preconditions.checkArgument(duration > 0);
}
- @Override public T get() {
+ @Override
+ public T get() {
// Another variant of Double Checked Locking.
//
// We use two volatile reads. We could reduce this to one by
@@ -188,7 +195,7 @@ public final class Suppliers {
long now = Platform.systemNanoTime();
if (nanos == 0 || now - nanos >= 0) {
synchronized (this) {
- if (nanos == expirationNanos) { // recheck for lost race
+ if (nanos == expirationNanos) { // recheck for lost race
T t = delegate.get();
value = t;
nanos = now + durationNanos;
@@ -202,11 +209,11 @@ public final class Suppliers {
return value;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
// This is a little strange if the unit the user provided was not NANOS,
// but we don't want to store the unit just for toString
- return "Suppliers.memoizeWithExpiration(" + delegate + ", " +
- durationNanos + ", NANOS)";
+ return "Suppliers.memoizeWithExpiration(" + delegate + ", " + durationNanos + ", NANOS)";
}
private static final long serialVersionUID = 0;
@@ -219,19 +226,20 @@ public final class Suppliers {
return new SupplierOfInstance<T>(instance);
}
- private static class SupplierOfInstance<T>
- implements Supplier<T>, Serializable {
+ private static class SupplierOfInstance<T> implements Supplier<T>, Serializable {
final T instance;
SupplierOfInstance(@Nullable T instance) {
this.instance = instance;
}
- @Override public T get() {
+ @Override
+ public T get() {
return instance;
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof SupplierOfInstance) {
SupplierOfInstance<?> that = (SupplierOfInstance<?>) obj;
return Objects.equal(instance, that.instance);
@@ -239,11 +247,13 @@ public final class Suppliers {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Objects.hashCode(instance);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Suppliers.ofInstance(" + instance + ")";
}
@@ -258,21 +268,22 @@ public final class Suppliers {
return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
}
- private static class ThreadSafeSupplier<T>
- implements Supplier<T>, Serializable {
+ private static class ThreadSafeSupplier<T> implements Supplier<T>, Serializable {
final Supplier<T> delegate;
ThreadSafeSupplier(Supplier<T> delegate) {
this.delegate = delegate;
}
- @Override public T get() {
+ @Override
+ public T get() {
synchronized (delegate) {
return delegate.get();
}
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Suppliers.synchronizedSupplier(" + delegate + ")";
}
@@ -298,11 +309,13 @@ public final class Suppliers {
INSTANCE;
// Note: This makes T a "pass-through type"
- @Override public Object apply(Supplier<Object> input) {
+ @Override
+ public Object apply(Supplier<Object> input) {
return input.get();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Suppliers.supplierFunction()";
}
}
diff --git a/guava/src/com/google/common/base/Throwables.java b/guava/src/com/google/common/base/Throwables.java
index 5e4d6ec..04b64bb 100644
--- a/guava/src/com/google/common/base/Throwables.java
+++ b/guava/src/com/google/common/base/Throwables.java
@@ -17,23 +17,29 @@
package com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableList;
import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Static utility methods pertaining to instances of {@link Throwable}.
*
* <p>See the Guava User Guide entry on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ThrowablesExplained">
- * Throwables</a>.
+ * "https://github.com/google/guava/wiki/ThrowablesExplained">Throwables</a>.
*
* @author Kevin Bourrillion
* @author Ben Yu
@@ -43,8 +49,8 @@ public final class Throwables {
private Throwables() {}
/**
- * Propagates {@code throwable} exactly as-is, if and only if it is an
- * instance of {@code declaredType}. Example usage:
+ * Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@code
+ * declaredType}. Example usage:
* <pre>
* try {
* someMethodThatCouldThrowAnything();
@@ -66,8 +72,8 @@ public final class Throwables {
}
/**
- * Propagates {@code throwable} exactly as-is, if and only if it is an
- * instance of {@link RuntimeException} or {@link Error}. Example usage:
+ * Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@link
+ * RuntimeException} or {@link Error}. Example usage:
* <pre>
* try {
* someMethodThatCouldThrowAnything();
@@ -85,9 +91,8 @@ public final class Throwables {
}
/**
- * Propagates {@code throwable} exactly as-is, if and only if it is an
- * instance of {@link RuntimeException}, {@link Error}, or
- * {@code declaredType}. Example usage:
+ * Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@link
+ * RuntimeException}, {@link Error}, or {@code declaredType}. Example usage:
* <pre>
* try {
* someMethodThatCouldThrowAnything();
@@ -100,8 +105,7 @@ public final class Throwables {
* </pre>
*
* @param throwable the Throwable to possibly propagate
- * @param declaredType the single checked exception type declared by the
- * calling method
+ * @param declaredType the single checked exception type declared by the calling method
*/
public static <X extends Throwable> void propagateIfPossible(
@Nullable Throwable throwable, Class<X> declaredType) throws X {
@@ -110,35 +114,31 @@ public final class Throwables {
}
/**
- * Propagates {@code throwable} exactly as-is, if and only if it is an
- * instance of {@link RuntimeException}, {@link Error}, {@code declaredType1},
- * or {@code declaredType2}. In the unlikely case that you have three or more
- * declared checked exception types, you can handle them all by invoking these
- * methods repeatedly. See usage example in {@link
+ * Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@link
+ * RuntimeException}, {@link Error}, {@code declaredType1}, or {@code declaredType2}. In the
+ * unlikely case that you have three or more declared checked exception types, you can handle them
+ * all by invoking these methods repeatedly. See usage example in {@link
* #propagateIfPossible(Throwable, Class)}.
*
* @param throwable the Throwable to possibly propagate
- * @param declaredType1 any checked exception type declared by the calling
- * method
- * @param declaredType2 any other checked exception type declared by the
- * calling method
+ * @param declaredType1 any checked exception type declared by the calling method
+ * @param declaredType2 any other checked exception type declared by the calling method
*/
- public static <X1 extends Throwable, X2 extends Throwable>
- void propagateIfPossible(@Nullable Throwable throwable,
- Class<X1> declaredType1, Class<X2> declaredType2) throws X1, X2 {
+ public static <X1 extends Throwable, X2 extends Throwable> void propagateIfPossible(
+ @Nullable Throwable throwable, Class<X1> declaredType1, Class<X2> declaredType2)
+ throws X1, X2 {
checkNotNull(declaredType2);
propagateIfInstanceOf(throwable, declaredType1);
propagateIfPossible(throwable, declaredType2);
}
/**
- * Propagates {@code throwable} as-is if it is an instance of
- * {@link RuntimeException} or {@link Error}, or else as a last resort, wraps
- * it in a {@code RuntimeException} then propagates.
+ * Propagates {@code throwable} as-is if it is an instance of {@link RuntimeException} or {@link
+ * Error}, or else as a last resort, wraps it in a {@code RuntimeException} and then propagates.
* <p>
- * This method always throws an exception. The {@code RuntimeException} return
- * type is only for client code to make Java type system happy in case a
- * return value is required by the enclosing method. Example usage:
+ * This method always throws an exception. The {@code RuntimeException} return type is only for
+ * client code to make Java type system happy in case a return value is required by the enclosing
+ * method. Example usage:
* <pre>
* T doSomething() {
* try {
@@ -152,8 +152,8 @@ public final class Throwables {
* </pre>
*
* @param throwable the Throwable to propagate
- * @return nothing will ever be returned; this return type is only for your
- * convenience, as illustrated in the example above
+ * @return nothing will ever be returned; this return type is only for your convenience, as
+ * illustrated in the example above
*/
public static RuntimeException propagate(Throwable throwable) {
propagateIfPossible(checkNotNull(throwable));
@@ -165,10 +165,10 @@ public final class Throwables {
* chain provides context from when the error or exception was initially
* detected. Example usage:
* <pre>
- * assertEquals("Unable to assign a customer id",
- * Throwables.getRootCause(e).getMessage());
+ * assertEquals("Unable to assign a customer id", Throwables.getRootCause(e).getMessage());
* </pre>
*/
+ @CheckReturnValue
public static Throwable getRootCause(Throwable throwable) {
Throwable cause;
while ((cause = throwable.getCause()) != null) {
@@ -178,23 +178,22 @@ public final class Throwables {
}
/**
- * Gets a {@code Throwable} cause chain as a list. The first entry in the
- * list will be {@code throwable} followed by its cause hierarchy. Note
- * that this is a snapshot of the cause chain and will not reflect
- * any subsequent changes to the cause chain.
+ * Gets a {@code Throwable} cause chain as a list. The first entry in the list will be {@code
+ * throwable} followed by its cause hierarchy. Note that this is a snapshot of the cause chain
+ * and will not reflect any subsequent changes to the cause chain.
*
- * <p>Here's an example of how it can be used to find specific types
- * of exceptions in the cause chain:
+ * <p>Here's an example of how it can be used to find specific types of exceptions in the cause
+ * chain:
*
* <pre>
* Iterables.filter(Throwables.getCausalChain(e), IOException.class));
* </pre>
*
* @param throwable the non-null {@code Throwable} to extract causes from
- * @return an unmodifiable list containing the cause chain starting with
- * {@code throwable}
+ * @return an unmodifiable list containing the cause chain starting with {@code throwable}
*/
@Beta // TODO(kevinb): decide best return type
+ @CheckReturnValue
public static List<Throwable> getCausalChain(Throwable throwable) {
checkNotNull(throwable);
List<Throwable> causes = new ArrayList<Throwable>(4);
@@ -206,15 +205,176 @@ public final class Throwables {
}
/**
- * Returns a string containing the result of
- * {@link Throwable#toString() toString()}, followed by the full, recursive
- * stack trace of {@code throwable}. Note that you probably should not be
- * parsing the resulting string; if you need programmatic access to the stack
- * frames, you can call {@link Throwable#getStackTrace()}.
+ * Returns a string containing the result of {@link Throwable#toString() toString()}, followed by
+ * the full, recursive stack trace of {@code throwable}. Note that you probably should not be
+ * parsing the resulting string; if you need programmatic access to the stack frames, you can call
+ * {@link Throwable#getStackTrace()}.
*/
+ @CheckReturnValue
public static String getStackTraceAsString(Throwable throwable) {
StringWriter stringWriter = new StringWriter();
throwable.printStackTrace(new PrintWriter(stringWriter));
return stringWriter.toString();
}
+
+ /**
+ * Returns the stack trace of {@code throwable}, possibly providing slower iteration over the full
+ * trace but faster iteration over parts of the trace. Here, "slower" and "faster" are defined in
+ * comparison to the normal way to access the stack trace, {@link Throwable#getStackTrace()
+ * throwable.getStackTrace()}. Note, however, that this method's special implementation is not
+ * available for all platforms and configurations. If that implementation is unavailable, this
+ * method falls back to {@code getStackTrace}. Callers that require the special implementation can
+ * check its availability with {@link #lazyStackTraceIsLazy()}.
+ *
+ * <p>The expected (but not guaranteed) performance of the special implementation differs from
+ * {@code getStackTrace} in one main way: The {@code lazyStackTrace} call itself returns quickly
+ * by delaying the per-stack-frame work until each element is accessed. Roughly speaking:
+ *
+ * <ul>
+ * <li>{@code getStackTrace} takes {@code stackSize} time to return but then negligible time to
+ * retrieve each element of the returned list.
+ * <li>{@code lazyStackTrace} takes negligible time to return but then {@code 1/stackSize} time to
+ * retrieve each element of the returned list (probably slightly more than {@code 1/stackSize}).
+ * </ul>
+ *
+ * <p>Note: The special implementation does not respect calls to {@link Throwable#setStackTrace
+ * throwable.setStackTrace}. Instead, it always reflects the original stack trace from the
+ * exception's creation.
+ *
+ * @since 19.0
+ */
+ // TODO(cpovirk): Say something about the possibility that List access could fail at runtime?
+ @Beta
+ @CheckReturnValue
+ public static List<StackTraceElement> lazyStackTrace(Throwable throwable) {
+ return lazyStackTraceIsLazy()
+ ? jlaStackTrace(throwable)
+ : unmodifiableList(asList(throwable.getStackTrace()));
+ }
+
+ /**
+ * Returns whether {@link #lazyStackTrace} will use the special implementation described in its
+ * documentation.
+ *
+ * @since 19.0
+ */
+ @Beta
+ @CheckReturnValue
+ public static boolean lazyStackTraceIsLazy() {
+ return getStackTraceElementMethod != null & getStackTraceDepthMethod != null;
+ }
+
+ private static List<StackTraceElement> jlaStackTrace(final Throwable t) {
+ checkNotNull(t);
+ /*
+ * TODO(cpovirk): Consider optimizing iterator() to catch IOOBE instead of doing bounds checks.
+ *
+ * TODO(cpovirk): Consider the UnsignedBytes pattern if it performs faster and doesn't cause
+ * AOSP grief.
+ */
+ return new AbstractList<StackTraceElement>() {
+ @Override
+ public StackTraceElement get(int n) {
+ return (StackTraceElement)
+ invokeAccessibleNonThrowingMethod(getStackTraceElementMethod, jla, t, n);
+ }
+
+ @Override
+ public int size() {
+ return (Integer) invokeAccessibleNonThrowingMethod(getStackTraceDepthMethod, jla, t);
+ }
+ };
+ }
+
+ private static Object invokeAccessibleNonThrowingMethod(
+ Method method, Object receiver, Object... params) {
+ try {
+ return method.invoke(receiver, params);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw propagate(e.getCause());
+ }
+ }
+
+ /** JavaLangAccess class name to load using reflection */
+ private static final String JAVA_LANG_ACCESS_CLASSNAME = "sun.misc.JavaLangAccess";
+
+ /** SharedSecrets class name to load using reflection */
+ @VisibleForTesting static final String SHARED_SECRETS_CLASSNAME = "sun.misc.SharedSecrets";
+
+ /** Access to some fancy internal JVM internals. */
+ @Nullable private static final Object jla = getJLA();
+
+ /**
+ * The "getStackTraceElementMethod" method, only available on some JDKs so we use reflection to
+ * find it when available. When this is null, use the slow way.
+ */
+ @Nullable
+ private static final Method getStackTraceElementMethod = (jla == null) ? null : getGetMethod();
+
+ /**
+ * The "getStackTraceDepth" method, only available on some JDKs so we use reflection to find it
+ * when available. When this is null, use the slow way.
+ */
+ @Nullable
+ private static final Method getStackTraceDepthMethod = (jla == null) ? null : getSizeMethod();
+
+ /**
+ * Returns the JavaLangAccess class that is present in all Sun JDKs. It is not whitelisted for
+ * AppEngine, and not present in non-Sun JDKs.
+ */
+ @Nullable
+ private static Object getJLA() {
+ try {
+ /*
+ * We load sun.misc.* classes using reflection since Android doesn't support these classes and
+ * would result in compilation failure if we directly refer to these classes.
+ */
+ Class<?> sharedSecrets = Class.forName(SHARED_SECRETS_CLASSNAME, false, null);
+ Method langAccess = sharedSecrets.getMethod("getJavaLangAccess");
+ return langAccess.invoke(null);
+ } catch (ThreadDeath death) {
+ throw death;
+ } catch (Throwable t) {
+ /*
+ * This is not one of AppEngine's whitelisted classes, so even in Sun JDKs, this can fail with
+ * a NoClassDefFoundError. Other apps might deny access to sun.misc packages.
+ */
+ return null;
+ }
+ }
+
+ /**
+ * Returns the Method that can be used to resolve an individual StackTraceElement, or null if that
+ * method cannot be found (it is only to be found in fairly recent JDKs).
+ */
+ @Nullable
+ private static Method getGetMethod() {
+ return getJlaMethod("getStackTraceElement", Throwable.class, int.class);
+ }
+
+ /**
+ * Returns the Method that can be used to return the size of a stack, or null if that method
+ * cannot be found (it is only to be found in fairly recent JDKs).
+ */
+ @Nullable
+ private static Method getSizeMethod() {
+ return getJlaMethod("getStackTraceDepth", Throwable.class);
+ }
+
+ @Nullable
+ private static Method getJlaMethod(String name, Class<?>... parameterTypes) throws ThreadDeath {
+ try {
+ return Class.forName(JAVA_LANG_ACCESS_CLASSNAME, false, null).getMethod(name, parameterTypes);
+ } catch (ThreadDeath death) {
+ throw death;
+ } catch (Throwable t) {
+ /*
+ * Either the JavaLangAccess class itself is not found, or the method is not supported on the
+ * JVM.
+ */
+ return null;
+ }
+ }
}
diff --git a/guava/src/com/google/common/base/Ticker.java b/guava/src/com/google/common/base/Ticker.java
index 6c34aef..670163b 100644
--- a/guava/src/com/google/common/base/Ticker.java
+++ b/guava/src/com/google/common/base/Ticker.java
@@ -19,6 +19,8 @@ package com.google.common.base;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
+import javax.annotation.CheckReturnValue;
+
/**
* A time source; returns a time value representing the number of nanoseconds elapsed since some
* fixed but arbitrary point in time. Note that most users should use {@link Stopwatch} instead of
@@ -28,7 +30,7 @@ import com.google.common.annotations.GwtCompatible;
*
* @author Kevin Bourrillion
* @since 10.0
- * (<a href="http://code.google.com/p/guava-libraries/wiki/Compatibility"
+ * (<a href="https://github.com/google/guava/wiki/Compatibility"
* >mostly source-compatible</a> since 9.0)
*/
@Beta
@@ -50,14 +52,16 @@ public abstract class Ticker {
*
* @since 10.0
*/
+ @CheckReturnValue
public static Ticker systemTicker() {
return SYSTEM_TICKER;
}
- private static final Ticker SYSTEM_TICKER = new Ticker() {
- @Override
- public long read() {
- return Platform.systemNanoTime();
- }
- };
+ private static final Ticker SYSTEM_TICKER =
+ new Ticker() {
+ @Override
+ public long read() {
+ return Platform.systemNanoTime();
+ }
+ };
}
diff --git a/guava/src/com/google/common/base/Utf8.java b/guava/src/com/google/common/base/Utf8.java
index 5a333e1..106491e 100644
--- a/guava/src/com/google/common/base/Utf8.java
+++ b/guava/src/com/google/common/base/Utf8.java
@@ -15,10 +15,14 @@
package com.google.common.base;
import static com.google.common.base.Preconditions.checkPositionIndexes;
+import static java.lang.Character.MAX_SURROGATE;
+import static java.lang.Character.MIN_SURROGATE;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
+import javax.annotation.CheckReturnValue;
+
/**
* Low-level, high-performance utility methods related to the {@linkplain Charsets#UTF_8 UTF-8}
* character encoding. UTF-8 is defined in section D92 of
@@ -45,6 +49,7 @@ public final class Utf8 {
* @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
* surrogates)
*/
+ @CheckReturnValue
public static int encodedLength(CharSequence sequence) {
// Warning to maintainers: this implementation is highly optimized.
int utf16Length = sequence.length();
@@ -60,7 +65,7 @@ public final class Utf8 {
for (; i < utf16Length; i++) {
char c = sequence.charAt(i);
if (c < 0x800) {
- utf8Length += ((0x7f - c) >>> 31); // branch free!
+ utf8Length += ((0x7f - c) >>> 31); // branch free!
} else {
utf8Length += encodedLengthGeneral(sequence, i);
break;
@@ -69,8 +74,8 @@ public final class Utf8 {
if (utf8Length < utf16Length) {
// Necessary and sufficient condition for overflow because of maximum 3x expansion
- throw new IllegalArgumentException("UTF-8 length does not fit in int: "
- + (utf8Length + (1L << 32)));
+ throw new IllegalArgumentException(
+ "UTF-8 length does not fit in int: " + (utf8Length + (1L << 32)));
}
return utf8Length;
}
@@ -85,11 +90,10 @@ public final class Utf8 {
} else {
utf8Length += 2;
// jdk7+: if (Character.isSurrogate(c)) {
- if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
+ if (MIN_SURROGATE <= c && c <= MAX_SURROGATE) {
// Check that we have a well-formed surrogate pair.
- int cp = Character.codePointAt(sequence, i);
- if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
- throw new IllegalArgumentException("Unpaired surrogate at index " + i);
+ if (Character.codePointAt(sequence, i) == c) {
+ throw new IllegalArgumentException(unpairedSurrogateMsg(i));
}
i++;
}
@@ -108,6 +112,7 @@ public final class Utf8 {
* <p>This method returns {@code true} if and only if {@code Arrays.equals(bytes, new
* String(bytes, UTF_8).getBytes(UTF_8))} does, but is more efficient in both time and space.
*/
+ @CheckReturnValue
public static boolean isWellFormed(byte[] bytes) {
return isWellFormed(bytes, 0, bytes.length);
}
@@ -121,6 +126,7 @@ public final class Utf8 {
* @param off the offset in the buffer of the first byte to read
* @param len the number of bytes to read from the buffer
*/
+ @CheckReturnValue
public static boolean isWellFormed(byte[] bytes, int off, int len) {
int end = off + len;
checkPositionIndexes(off, end, bytes.length);
@@ -192,5 +198,9 @@ public final class Utf8 {
}
}
+ private static String unpairedSurrogateMsg(int i) {
+ return "Unpaired surrogate at index " + i;
+ }
+
private Utf8() {}
}
diff --git a/guava/src/com/google/common/base/Verify.java b/guava/src/com/google/common/base/Verify.java
index d2c5615..f6d77b4 100644
--- a/guava/src/com/google/common/base/Verify.java
+++ b/guava/src/com/google/common/base/Verify.java
@@ -81,7 +81,7 @@ import javax.annotation.Nullable;
* <h3>More information</h3>
*
* See
- * <a href="http://code.google.com/p/guava-libraries/wiki/ConditionalFailuresExplained">Conditional
+ * <a href="https://github.com/google/guava/wiki/ConditionalFailuresExplained">Conditional
* failures explained</a> in the Guava User Guide for advice on when this class should be used.
*
* @since 17.0
@@ -92,6 +92,8 @@ public final class Verify {
/**
* Ensures that {@code expression} is {@code true}, throwing a {@code VerifyException} with no
* message otherwise.
+ *
+ * @throws VerifyException if {@code expression} is {@code false}
*/
public static void verify(boolean expression) {
if (!expression) {
@@ -129,6 +131,7 @@ public final class Verify {
* message otherwise.
*
* @return {@code reference}, guaranteed to be non-null, for convenience
+ * @throws VerifyException if {@code reference} is {@code null}
*/
public static <T> T verifyNotNull(@Nullable T reference) {
return verifyNotNull(reference, "expected a non-null reference");
@@ -148,6 +151,7 @@ public final class Verify {
* template. Arguments are converted to strings using
* {@link String#valueOf(Object)}.
* @return {@code reference}, guaranteed to be non-null, for convenience
+ * @throws VerifyException if {@code reference} is {@code null}
*/
public static <T> T verifyNotNull(
@Nullable T reference,
diff --git a/guava/src/com/google/common/base/VerifyException.java b/guava/src/com/google/common/base/VerifyException.java
index 2354d8e..bbcacd7 100644
--- a/guava/src/com/google/common/base/VerifyException.java
+++ b/guava/src/com/google/common/base/VerifyException.java
@@ -21,7 +21,7 @@ import javax.annotation.Nullable;
/**
* Exception thrown upon the failure of a
- * <a href="http://code.google.com/p/guava-libraries/wiki/ConditionalFailuresExplained">verification
+ * <a href="https://github.com/google/guava/wiki/ConditionalFailuresExplained">verification
* check</a>, including those performed by the convenience methods of the {@link Verify} class.
*
* @since 17.0
@@ -36,4 +36,24 @@ public class VerifyException extends RuntimeException {
public VerifyException(@Nullable String message) {
super(message);
}
+
+ /**
+ * Constructs a {@code VerifyException} with the cause {@code cause} and a message that is
+ * {@code null} if {@code cause} is null, and {@code cause.toString()} otherwise.
+ *
+ * @since 19.0
+ */
+ public VerifyException(@Nullable Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a {@code VerifyException} with the message {@code message} and the cause
+ * {@code cause}.
+ *
+ * @since 19.0
+ */
+ public VerifyException(@Nullable String message, @Nullable Throwable cause) {
+ super(message, cause);
+ }
}
diff --git a/guava/src/com/google/common/base/internal/Finalizer.java b/guava/src/com/google/common/base/internal/Finalizer.java
index 3191e0f..9469489 100644
--- a/guava/src/com/google/common/base/internal/Finalizer.java
+++ b/guava/src/com/google/common/base/internal/Finalizer.java
@@ -33,9 +33,9 @@ import java.util.logging.Logger;
* of our published API. It is public so we can access it reflectively across
* class loaders in secure environments.
*
- * <p>This class can't depend on other Google Collections code. If we were
+ * <p>This class can't depend on other Guava code. If we were
* to load this class in the same class loader as the rest of
- * Google Collections, this thread would keep an indirect strong reference
+ * Guava, this thread would keep an indirect strong reference
* to the class loader and prevent it from being garbage collected. This
* poses a problem for environments where you want to throw away the class
* loader. For example, dynamically reloading a web application or unloading
@@ -48,12 +48,10 @@ import java.util.logging.Logger;
*/
public class Finalizer implements Runnable {
- private static final Logger logger
- = Logger.getLogger(Finalizer.class.getName());
+ private static final Logger logger = Logger.getLogger(Finalizer.class.getName());
/** Name of FinalizableReference.class. */
- private static final String FINALIZABLE_REFERENCE
- = "com.google.common.base.FinalizableReference";
+ private static final String FINALIZABLE_REFERENCE = "com.google.common.base.FinalizableReference";
/**
* Starts the Finalizer thread. FinalizableReferenceQueue calls this method
@@ -78,8 +76,7 @@ public class Finalizer implements Runnable {
* collected, at which point, Finalizer can stop running
*/
if (!finalizableReferenceClass.getName().equals(FINALIZABLE_REFERENCE)) {
- throw new IllegalArgumentException(
- "Expected " + FINALIZABLE_REFERENCE + ".");
+ throw new IllegalArgumentException("Expected " + FINALIZABLE_REFERENCE + ".");
}
Finalizer finalizer = new Finalizer(finalizableReferenceClass, queue, frqReference);
@@ -92,8 +89,10 @@ public class Finalizer implements Runnable {
inheritableThreadLocals.set(thread, null);
}
} catch (Throwable t) {
- logger.log(Level.INFO, "Failed to clear thread local values inherited"
- + " by reference finalizer thread.", t);
+ logger.log(
+ Level.INFO,
+ "Failed to clear thread local values inherited by reference finalizer thread.",
+ t);
}
thread.start();
@@ -103,8 +102,7 @@ public class Finalizer implements Runnable {
private final PhantomReference<Object> frqReference;
private final ReferenceQueue<Object> queue;
- private static final Field inheritableThreadLocals
- = getInheritableThreadLocalsField();
+ private static final Field inheritableThreadLocals = getInheritableThreadLocalsField();
/** Constructs a new finalizer thread. */
private Finalizer(
@@ -113,8 +111,8 @@ public class Finalizer implements Runnable {
PhantomReference<Object> frqReference) {
this.queue = queue;
- this.finalizableReferenceClassReference
- = new WeakReference<Class<?>>(finalizableReferenceClass);
+ this.finalizableReferenceClassReference =
+ new WeakReference<Class<?>>(finalizableReferenceClass);
// Keep track of the FRQ that started us so we know when to stop.
this.frqReference = frqReference;
@@ -131,7 +129,9 @@ public class Finalizer implements Runnable {
if (!cleanUp(queue.remove())) {
break;
}
- } catch (InterruptedException e) { /* ignore */ }
+ } catch (InterruptedException e) {
+ // ignore
+ }
}
}
@@ -178,8 +178,7 @@ public class Finalizer implements Runnable {
* Looks up FinalizableReference.finalizeReferent() method.
*/
private Method getFinalizeReferentMethod() {
- Class<?> finalizableReferenceClass
- = finalizableReferenceClassReference.get();
+ Class<?> finalizableReferenceClass = finalizableReferenceClassReference.get();
if (finalizableReferenceClass == null) {
/*
* FinalizableReference's class loader was reclaimed. While there's a
@@ -200,14 +199,14 @@ public class Finalizer implements Runnable {
public static Field getInheritableThreadLocalsField() {
try {
- Field inheritableThreadLocals
- = Thread.class.getDeclaredField("inheritableThreadLocals");
+ Field inheritableThreadLocals = Thread.class.getDeclaredField("inheritableThreadLocals");
inheritableThreadLocals.setAccessible(true);
return inheritableThreadLocals;
} catch (Throwable t) {
- logger.log(Level.INFO, "Couldn't access Thread.inheritableThreadLocals."
- + " Reference finalizer threads will inherit thread local"
- + " values.");
+ logger.log(
+ Level.INFO,
+ "Couldn't access Thread.inheritableThreadLocals. Reference finalizer threads will "
+ + "inherit thread local values.");
return null;
}
}
diff --git a/guava/src/com/google/common/cache/AbstractCache.java b/guava/src/com/google/common/cache/AbstractCache.java
index 7e54174..7506cdb 100644
--- a/guava/src/com/google/common/cache/AbstractCache.java
+++ b/guava/src/com/google/common/cache/AbstractCache.java
@@ -16,7 +16,6 @@
package com.google.common.cache;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
@@ -40,7 +39,6 @@ import java.util.concurrent.ExecutionException;
* @author Charles Fry
* @since 10.0
*/
- at Beta
@GwtCompatible
public abstract class AbstractCache<K, V> implements Cache<K, V> {
@@ -142,7 +140,6 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
*
* @since 10.0
*/
- @Beta
public interface StatsCounter {
/**
* Records cache hits. This should be called when a cache request returns a cached value.
@@ -204,7 +201,6 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
*
* @since 10.0
*/
- @Beta
public static final class SimpleStatsCounter implements StatsCounter {
private final LongAddable hitCount = LongAddables.create();
private final LongAddable missCount = LongAddables.create();
diff --git a/guava/src/com/google/common/cache/AbstractLoadingCache.java b/guava/src/com/google/common/cache/AbstractLoadingCache.java
index 6a12c40..ded9f7b 100644
--- a/guava/src/com/google/common/cache/AbstractLoadingCache.java
+++ b/guava/src/com/google/common/cache/AbstractLoadingCache.java
@@ -16,7 +16,6 @@
package com.google.common.cache;
-import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.UncheckedExecutionException;
@@ -40,7 +39,6 @@ import java.util.concurrent.ExecutionException;
* @author Charles Fry
* @since 11.0
*/
- at Beta
public abstract class AbstractLoadingCache<K, V>
extends AbstractCache<K, V> implements LoadingCache<K, V> {
diff --git a/guava/src/com/google/common/cache/Cache.java b/guava/src/com/google/common/cache/Cache.java
index 9313c5f..344821c 100644
--- a/guava/src/com/google/common/cache/Cache.java
+++ b/guava/src/com/google/common/cache/Cache.java
@@ -16,7 +16,6 @@
package com.google.common.cache;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ExecutionError;
@@ -37,15 +36,9 @@ import javax.annotation.Nullable;
* <p>Implementations of this interface are expected to be thread-safe, and can be safely accessed
* by multiple concurrent threads.
*
- * <p>Note that while this class is still annotated as {@link Beta}, the API is frozen from a
- * consumer's standpoint. In other words existing methods are all considered {@code non-Beta} and
- * won't be changed without going through an 18 month deprecation cycle; however new methods may be
- * added at any time.
- *
* @author Charles Fry
* @since 10.0
*/
- at Beta
@GwtCompatible
public interface Cache<K, V> {
diff --git a/guava/src/com/google/common/cache/CacheBuilder.java b/guava/src/com/google/common/cache/CacheBuilder.java
index ba8ed11..4ced26f 100644
--- a/guava/src/com/google/common/cache/CacheBuilder.java
+++ b/guava/src/com/google/common/cache/CacheBuilder.java
@@ -20,7 +20,6 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Ascii;
@@ -58,6 +57,7 @@ import javax.annotation.CheckReturnValue;
* <li>accumulation of cache access statistics
* </ul>
*
+ *
* <p>These features are all optional; caches can be created using all or none of them. By default
* cache instances created by {@code CacheBuilder} will not perform any type of eviction.
*
@@ -139,7 +139,7 @@ import javax.annotation.CheckReturnValue;
* <i>not</i> include cache contents, but only configuration.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CachesExplained">caching</a> for a higher-level
+ * "https://github.com/google/guava/wiki/CachesExplained">caching</a> for a higher-level
* explanation.
*
* @param <K> the base key type for all caches created by this builder
@@ -253,7 +253,6 @@ public final class CacheBuilder<K, V> {
*
* @since 12.0
*/
- @Beta
@GwtIncompatible("To be supported")
public static CacheBuilder<Object, Object> from(CacheBuilderSpec spec) {
return spec.toCacheBuilder()
@@ -267,7 +266,6 @@ public final class CacheBuilder<K, V> {
* @param spec a String in the format specified by {@link CacheBuilderSpec}
* @since 12.0
*/
- @Beta
@GwtIncompatible("To be supported")
public static CacheBuilder<Object, Object> from(String spec) {
return from(CacheBuilderSpec.parse(spec));
@@ -674,7 +672,6 @@ public final class CacheBuilder<K, V> {
* @throws IllegalStateException if the refresh interval was already set
* @since 11.0
*/
- @Beta
@GwtIncompatible("To be supported (synchronously).")
public CacheBuilder<K, V> refreshAfterWrite(long duration, TimeUnit unit) {
checkNotNull(unit);
@@ -689,11 +686,11 @@ public final class CacheBuilder<K, V> {
}
/**
- * Specifies a nanosecond-precision time source for use in determining when entries should be
- * expired. By default, {@link System#nanoTime} is used.
+ * Specifies a nanosecond-precision time source for this cache. By default,
+ * {@link System#nanoTime} is used.
*
- * <p>The primary intent of this method is to facilitate testing of caches which have been
- * configured with {@link #expireAfterWrite} or {@link #expireAfterAccess}.
+ * <p>The primary intent of this method is to facilitate testing of caches with a fake or mock
+ * time source.
*
* @throws IllegalStateException if a ticker was already set
*/
@@ -762,7 +759,7 @@ public final class CacheBuilder<K, V> {
statsCounterSupplier = CACHE_STATS_COUNTER;
return this;
}
-
+
boolean isRecordingStats() {
return statsCounterSupplier == CACHE_STATS_COUNTER;
}
@@ -784,7 +781,7 @@ public final class CacheBuilder<K, V> {
* @return a cache having the requested features
*/
public <K1 extends K, V1 extends V> LoadingCache<K1, V1> build(
- CacheLoader<? super K1, V1> loader) {
+ CacheLoader<? super K1, V1> loader) {
checkWeightWithWeigher();
return new LocalCache.LocalLoadingCache<K1, V1>(this, loader);
}
diff --git a/guava/src/com/google/common/cache/CacheBuilderSpec.java b/guava/src/com/google/common/cache/CacheBuilderSpec.java
index 919366e..979b70b 100644
--- a/guava/src/com/google/common/cache/CacheBuilderSpec.java
+++ b/guava/src/com/google/common/cache/CacheBuilderSpec.java
@@ -18,7 +18,6 @@ package com.google.common.cache;
import static com.google.common.base.Preconditions.checkArgument;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
@@ -28,6 +27,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.List;
+import java.util.Locale;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
@@ -79,7 +79,6 @@ import javax.annotation.Nullable;
* @author Adam Winer
* @since 12.0
*/
- at Beta
public final class CacheBuilderSpec {
/** Parses a single value. */
private interface ValueParser {
@@ -295,7 +294,7 @@ public final class CacheBuilderSpec {
parseInteger(spec, Integer.parseInt(value));
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
- String.format("key %s value set to %s, must be integer", key, value), e);
+ format("key %s value set to %s, must be integer", key, value), e);
}
}
}
@@ -311,7 +310,7 @@ public final class CacheBuilderSpec {
parseLong(spec, Long.parseLong(value));
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
- String.format("key %s value set to %s, must be integer", key, value), e);
+ format("key %s value set to %s, must be integer", key, value), e);
}
}
}
@@ -433,7 +432,7 @@ public final class CacheBuilderSpec {
break;
default:
throw new IllegalArgumentException(
- String.format("key %s invalid format. was %s, must end with one of [dDhHmMsS]",
+ format("key %s invalid format. was %s, must end with one of [dDhHmMsS]",
key, value));
}
@@ -441,7 +440,7 @@ public final class CacheBuilderSpec {
parseDuration(spec, duration, timeUnit);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
- String.format("key %s value set to %s, must be integer", key, value));
+ format("key %s value set to %s, must be integer", key, value));
}
}
}
@@ -472,4 +471,8 @@ public final class CacheBuilderSpec {
spec.refreshTimeUnit = unit;
}
}
+
+ private static String format(String format, Object... args) {
+ return String.format(Locale.ROOT, format, args);
+ }
}
diff --git a/guava/src/com/google/common/cache/CacheLoader.java b/guava/src/com/google/common/cache/CacheLoader.java
index e60dd42..bbdb66d 100644
--- a/guava/src/com/google/common/cache/CacheLoader.java
+++ b/guava/src/com/google/common/cache/CacheLoader.java
@@ -18,7 +18,6 @@ package com.google.common.cache;
import static com.google.common.base.Preconditions.checkNotNull;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
@@ -133,7 +132,6 @@ public abstract class CacheLoader<K, V> {
* @param function the function to be used for loading values; must never return {@code null}
* @return a cache loader that loads values by passing each key to {@code function}
*/
- @Beta
public static <K, V> CacheLoader<K, V> from(Function<K, V> function) {
return new FunctionToCacheLoader<K, V>(function);
}
@@ -163,7 +161,6 @@ public abstract class CacheLoader<K, V> {
* @return a cache loader that loads values by calling {@link Supplier#get}, irrespective of the
* key
*/
- @Beta
public static <V> CacheLoader<Object, V> from(Supplier<V> supplier) {
return new SupplierToCacheLoader<V>(supplier);
}
@@ -177,7 +174,6 @@ public abstract class CacheLoader<K, V> {
*
* @since 17.0
*/
- @Beta
@GwtIncompatible("Executor + Futures")
public static <K, V> CacheLoader<K, V> asyncReloading(final CacheLoader<K, V> loader,
final Executor executor) {
@@ -225,7 +221,17 @@ public abstract class CacheLoader<K, V> {
private static final long serialVersionUID = 0;
}
- static final class UnsupportedLoadingOperationException extends UnsupportedOperationException {}
+ /**
+ * Exception thrown by {@code loadAll()} to indicate that it is not supported.
+ *
+ * @since 19.0
+ */
+ public static final class UnsupportedLoadingOperationException
+ extends UnsupportedOperationException {
+ // Package-private because this should only be thrown by loadAll() when it is not overridden.
+ // Cache implementors may want to catch it but should not need to be able to throw it.
+ UnsupportedLoadingOperationException() {}
+ }
/**
* Thrown to indicate that an invalid response was returned from a call to {@link CacheLoader}.
diff --git a/guava/src/com/google/common/cache/CacheStats.java b/guava/src/com/google/common/cache/CacheStats.java
index c37c769..cfee32e 100644
--- a/guava/src/com/google/common/cache/CacheStats.java
+++ b/guava/src/com/google/common/cache/CacheStats.java
@@ -18,7 +18,6 @@ package com.google.common.cache;
import static com.google.common.base.Preconditions.checkArgument;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
@@ -47,7 +46,6 @@ import javax.annotation.Nullable;
* </ul>
* <li>When an entry is evicted from the cache, {@code evictionCount} is incremented.
* <li>No stats are modified when a cache entry is invalidated or manually removed.
- * <li>No stats are modified on a query to {@link Cache#getIfPresent}.
* <li>No stats are modified by operations invoked on the {@linkplain Cache#asMap asMap} view of
* the cache.
* </ul>
@@ -59,7 +57,6 @@ import javax.annotation.Nullable;
* @author Charles Fry
* @since 10.0
*/
- at Beta
@GwtCompatible
public final class CacheStats {
private final long hitCount;
diff --git a/guava/src/com/google/common/cache/ForwardingCache.java b/guava/src/com/google/common/cache/ForwardingCache.java
index 44fe683..8cbe307 100644
--- a/guava/src/com/google/common/cache/ForwardingCache.java
+++ b/guava/src/com/google/common/cache/ForwardingCache.java
@@ -16,7 +16,6 @@
package com.google.common.cache;
-import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
import com.google.common.collect.ForwardingObject;
import com.google.common.collect.ImmutableMap;
@@ -36,7 +35,6 @@ import javax.annotation.Nullable;
* @author Charles Fry
* @since 10.0
*/
- at Beta
public abstract class ForwardingCache<K, V> extends ForwardingObject implements Cache<K, V> {
/** Constructor for use by subclasses. */
@@ -126,11 +124,10 @@ public abstract class ForwardingCache<K, V> extends ForwardingObject implements
/**
* A simplified version of {@link ForwardingCache} where subclasses can pass in an already
- * constructed {@link Cache} as the delegete.
+ * constructed {@link Cache} as the delegate.
*
* @since 10.0
*/
- @Beta
public abstract static class SimpleForwardingCache<K, V> extends ForwardingCache<K, V> {
private final Cache<K, V> delegate;
diff --git a/guava/src/com/google/common/cache/ForwardingLoadingCache.java b/guava/src/com/google/common/cache/ForwardingLoadingCache.java
index 93732ff..bac6823 100644
--- a/guava/src/com/google/common/cache/ForwardingLoadingCache.java
+++ b/guava/src/com/google/common/cache/ForwardingLoadingCache.java
@@ -16,7 +16,6 @@
package com.google.common.cache;
-import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
@@ -33,7 +32,6 @@ import java.util.concurrent.ExecutionException;
* @author Charles Fry
* @since 11.0
*/
- at Beta
public abstract class ForwardingLoadingCache<K, V>
extends ForwardingCache<K, V> implements LoadingCache<K, V> {
@@ -70,11 +68,10 @@ public abstract class ForwardingLoadingCache<K, V>
/**
* A simplified version of {@link ForwardingLoadingCache} where subclasses can pass in an already
- * constructed {@link LoadingCache} as the delegete.
+ * constructed {@link LoadingCache} as the delegate.
*
* @since 10.0
*/
- @Beta
public abstract static class SimpleForwardingLoadingCache<K, V>
extends ForwardingLoadingCache<K, V> {
private final LoadingCache<K, V> delegate;
diff --git a/guava/src/com/google/common/cache/LoadingCache.java b/guava/src/com/google/common/cache/LoadingCache.java
index da08448..c0e6db6 100644
--- a/guava/src/com/google/common/cache/LoadingCache.java
+++ b/guava/src/com/google/common/cache/LoadingCache.java
@@ -16,7 +16,6 @@
package com.google.common.cache;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
@@ -36,15 +35,9 @@ import java.util.concurrent.ExecutionException;
* <p>When evaluated as a {@link Function}, a cache yields the same result as invoking
* {@link #getUnchecked}.
*
- * <p>Note that while this class is still annotated as {@link Beta}, the API is frozen from a
- * consumer's standpoint. In other words existing methods are all considered {@code non-Beta} and
- * won't be changed without going through an 18 month deprecation cycle; however new methods may be
- * added at any time.
- *
* @author Charles Fry
* @since 11.0
*/
- at Beta
@GwtCompatible
public interface LoadingCache<K, V> extends Cache<K, V>, Function<K, V> {
@@ -67,7 +60,7 @@ public interface LoadingCache<K, V> extends Cache<K, V>, Function<K, V> {
*
* @throws ExecutionException if a checked exception was thrown while loading the value. ({@code
* ExecutionException} is thrown <a
- * href="http://code.google.com/p/guava-libraries/wiki/CachesExplained#Interruption">even if
+ * href="https://github.com/google/guava/wiki/CachesExplained#interruption">even if
* computation was interrupted by an {@code InterruptedException}</a>.)
* @throws UncheckedExecutionException if an unchecked exception was thrown while loading the
* value
@@ -118,7 +111,7 @@ public interface LoadingCache<K, V> extends Cache<K, V>, Function<K, V> {
*
* @throws ExecutionException if a checked exception was thrown while loading the value. ({@code
* ExecutionException} is thrown <a
- * href="http://code.google.com/p/guava-libraries/wiki/CachesExplained#Interruption">even if
+ * href="https://github.com/google/guava/wiki/CachesExplained#interruption">even if
* computation was interrupted by an {@code InterruptedException}</a>.)
* @throws UncheckedExecutionException if an unchecked exception was thrown while loading the
* values
diff --git a/guava/src/com/google/common/cache/LocalCache.java b/guava/src/com/google/common/cache/LocalCache.java
index 0c51d06..7b044f5 100644
--- a/guava/src/com/google/common/cache/LocalCache.java
+++ b/guava/src/com/google/common/cache/LocalCache.java
@@ -40,6 +40,7 @@ import com.google.common.cache.CacheLoader.UnsupportedLoadingOperationException;
import com.google.common.collect.AbstractSequentialIterator;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.primitives.Ints;
@@ -49,6 +50,8 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.common.util.concurrent.Uninterruptibles;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -61,6 +64,7 @@ import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractQueue;
import java.util.AbstractSet;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
@@ -923,7 +927,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
public void setPreviousInWriteQueue(ReferenceEntry<Object, Object> previous) {}
}
- static abstract class AbstractReferenceEntry<K, V> implements ReferenceEntry<K, V> {
+ abstract static class AbstractReferenceEntry<K, V> implements ReferenceEntry<K, V> {
@Override
public ValueReference<K, V> getValueReference() {
throw new UnsupportedOperationException();
@@ -2007,7 +2011,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
* comments.
*/
- final LocalCache<K, V> map;
+ @Weak final LocalCache<K, V> map;
/**
* The number of live elements in this segment's region.
@@ -2648,22 +2652,33 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
if (map.removalNotificationQueue != DISCARDING_QUEUE) {
V value = valueReference.get();
- RemovalNotification<K, V> notification = new RemovalNotification<K, V>(key, value, cause);
+ RemovalNotification<K, V> notification = RemovalNotification.create(key, value, cause);
map.removalNotificationQueue.offer(notification);
}
}
/**
- * Performs eviction if the segment is full. This should only be called prior to adding a new
- * entry and increasing {@code count}.
+ * Performs eviction if the segment is over capacity. Avoids flushing the entire cache if the
+ * newest entry exceeds the maximum weight all on its own.
+ *
+ * @param newest the most recently added entry
*/
@GuardedBy("this")
- void evictEntries() {
+ void evictEntries(ReferenceEntry<K, V> newest) {
if (!map.evictsBySize()) {
return;
}
drainRecencyQueue();
+
+ // If the newest entry by itself is too heavy for the segment, don't bother evicting
+ // anything else, just that
+ if (newest.getValueReference().getWeight() > maxSegmentWeight) {
+ if (!removeEntry(newest, newest.getHash(), RemovalCause.SIZE)) {
+ throw new AssertionError();
+ }
+ }
+
while (totalWeight > maxSegmentWeight) {
ReferenceEntry<K, V> e = getNextEvictable();
if (!removeEntry(e, e.getHash(), RemovalCause.SIZE)) {
@@ -2858,7 +2873,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
newCount = this.count + 1;
}
this.count = newCount; // write-volatile
- evictEntries();
+ evictEntries(e);
return null;
} else if (onlyIfAbsent) {
// Mimic
@@ -2871,7 +2886,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
++modCount;
enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED);
setValue(e, key, value, now);
- evictEntries();
+ evictEntries(e);
return entryValue;
}
}
@@ -2884,7 +2899,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
table.set(index, newEntry);
newCount = this.count + 1;
this.count = newCount; // write-volatile
- evictEntries();
+ evictEntries(newEntry);
return null;
} finally {
unlock();
@@ -2998,7 +3013,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
++modCount;
enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED);
setValue(e, key, newValue, now);
- evictEntries();
+ evictEntries(e);
return true;
} else {
// Mimic
@@ -3050,7 +3065,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
++modCount;
enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED);
setValue(e, key, newValue, now);
- evictEntries();
+ evictEntries(e);
return entryValue;
}
}
@@ -3144,7 +3159,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
setValue(e, key, newValue, now);
this.count = newCount; // write-volatile
- evictEntries();
+ evictEntries(e);
return true;
}
@@ -3160,7 +3175,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
setValue(newEntry, key, newValue, now);
table.set(index, newEntry);
this.count = newCount; // write-volatile
- evictEntries();
+ evictEntries(newEntry);
return true;
} finally {
unlock();
@@ -3520,9 +3535,9 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
public ListenableFuture<V> loadFuture(K key, CacheLoader<? super K, V> loader) {
- stopwatch.start();
- V previousValue = oldValue.get();
try {
+ stopwatch.start();
+ V previousValue = oldValue.get();
if (previousValue == null) {
V newValue = loader.load(key);
return set(newValue) ? futureValue : Futures.immediateFuture(newValue);
@@ -3541,10 +3556,11 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
});
} catch (Throwable t) {
+ ListenableFuture<V> result = setException(t) ? futureValue : fullyFailedFuture(t);
if (t instanceof InterruptedException) {
Thread.currentThread().interrupt();
}
- return setException(t) ? futureValue : fullyFailedFuture(t);
+ return result;
}
}
@@ -3900,7 +3916,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
Segment<K, V>[] segments = this.segments;
long sum = 0;
for (int i = 0; i < segments.length; ++i) {
- sum += segments[i].count;
+ sum += Math.max(0, segments[i].count); // see https://github.com/google/guava/issues/2108
}
return sum;
}
@@ -4113,17 +4129,16 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
// in time it was present somewhere int the map. This becomes increasingly unlikely as
// CONTAINS_VALUE_RETRIES increases, though without locking it is theoretically possible.
long now = ticker.read();
- final Segment<K,V>[] segments = this.segments;
+ final Segment<K, V>[] segments = this.segments;
long last = -1L;
for (int i = 0; i < CONTAINS_VALUE_RETRIES; i++) {
long sum = 0L;
for (Segment<K, V> segment : segments) {
// ensure visibility of most recent completed write
- @SuppressWarnings({"UnusedDeclaration", "unused"})
- int c = segment.count; // read-volatile
+ int unused = segment.count; // read-volatile
AtomicReferenceArray<ReferenceEntry<K, V>> table = segment.table;
- for (int j = 0 ; j < table.length(); j++) {
+ for (int j = 0; j < table.length(); j++) {
for (ReferenceEntry<K, V> e = table.get(j); e != null; e = e.getNext()) {
V v = segment.getLiveValue(e, now);
if (v != null && valueEquivalence.equivalent(value, v)) {
@@ -4435,7 +4450,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
abstract class AbstractCacheSet<T> extends AbstractSet<T> {
- final ConcurrentMap<?, ?> map;
+ @Weak final ConcurrentMap<?, ?> map;
AbstractCacheSet(ConcurrentMap<?, ?> map) {
this.map = map;
@@ -4455,8 +4470,29 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
public void clear() {
map.clear();
}
+
+ // super.toArray() may misbehave if size() is inaccurate, at least on old versions of Android.
+ // https://code.google.com/p/android/issues/detail?id=36519 / http://r.android.com/47508
+
+ @Override
+ public Object[] toArray() {
+ return toArrayList(this).toArray();
+ }
+
+ @Override
+ public <E> E[] toArray(E[] a) {
+ return toArrayList(this).toArray(a);
+ }
+ }
+
+ private static <E> ArrayList<E> toArrayList(Collection<E> c) {
+ // Avoid calling ArrayList(Collection), which may call back into toArray.
+ ArrayList<E> result = new ArrayList<E>(c.size());
+ Iterators.addAll(result, c.iterator());
+ return result;
}
+ @WeakOuter
final class KeySet extends AbstractCacheSet<K> {
KeySet(ConcurrentMap<?, ?> map) {
@@ -4479,6 +4515,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
}
+ @WeakOuter
final class Values extends AbstractCollection<V> {
private final ConcurrentMap<?, ?> map;
@@ -4507,8 +4544,22 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
public boolean contains(Object o) {
return map.containsValue(o);
}
+
+ // super.toArray() may misbehave if size() is inaccurate, at least on old versions of Android.
+ // https://code.google.com/p/android/issues/detail?id=36519 / http://r.android.com/47508
+
+ @Override
+ public Object[] toArray() {
+ return toArrayList(this).toArray();
+ }
+
+ @Override
+ public <E> E[] toArray(E[] a) {
+ return toArrayList(this).toArray(a);
+ }
}
+ @WeakOuter
final class EntrySet extends AbstractCacheSet<Entry<K, V>> {
EntrySet(ConcurrentMap<?, ?> map) {
diff --git a/guava/src/com/google/common/cache/LongAddables.java b/guava/src/com/google/common/cache/LongAddables.java
index a110c6c..4428d30 100644
--- a/guava/src/com/google/common/cache/LongAddables.java
+++ b/guava/src/com/google/common/cache/LongAddables.java
@@ -34,7 +34,7 @@ final class LongAddables {
static {
Supplier<LongAddable> supplier;
try {
- new LongAdder();
+ new LongAdder(); // trigger static initialization of the LongAdder class, which may fail
supplier = new Supplier<LongAddable>() {
@Override
public LongAddable get() {
diff --git a/guava/src/com/google/common/cache/RemovalCause.java b/guava/src/com/google/common/cache/RemovalCause.java
index 0be9b5b..29082f0 100644
--- a/guava/src/com/google/common/cache/RemovalCause.java
+++ b/guava/src/com/google/common/cache/RemovalCause.java
@@ -16,7 +16,6 @@
package com.google.common.cache;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import java.util.Iterator;
@@ -29,7 +28,6 @@ import java.util.concurrent.ConcurrentMap;
* @author Charles Fry
* @since 10.0
*/
- at Beta
@GwtCompatible
public enum RemovalCause {
/**
diff --git a/guava/src/com/google/common/cache/RemovalListener.java b/guava/src/com/google/common/cache/RemovalListener.java
index 270a7c4..09bd3cf 100644
--- a/guava/src/com/google/common/cache/RemovalListener.java
+++ b/guava/src/com/google/common/cache/RemovalListener.java
@@ -16,7 +16,6 @@
package com.google.common.cache;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
@@ -36,11 +35,13 @@ import com.google.common.annotations.GwtCompatible;
* @author Charles Fry
* @since 10.0
*/
- at Beta
@GwtCompatible
public interface RemovalListener<K, V> {
/**
* Notifies the listener that a removal occurred at some point in the past.
+ *
+ * <p>This does not always signify that the key is now absent from the cache,
+ * as it may have already been re-added.
*/
// Technically should accept RemovalNotification<? extends K, ? extends V>, but because
// RemovalNotification is guaranteed covariant, let's make users' lives simpler.
diff --git a/guava/src/com/google/common/cache/RemovalListeners.java b/guava/src/com/google/common/cache/RemovalListeners.java
index dbb9efc..974ef04 100644
--- a/guava/src/com/google/common/cache/RemovalListeners.java
+++ b/guava/src/com/google/common/cache/RemovalListeners.java
@@ -18,8 +18,6 @@ package com.google.common.cache;
import static com.google.common.base.Preconditions.checkNotNull;
-import com.google.common.annotations.Beta;
-
import java.util.concurrent.Executor;
/**
@@ -28,7 +26,6 @@ import java.util.concurrent.Executor;
* @author Charles Fry
* @since 10.0
*/
- at Beta
public final class RemovalListeners {
private RemovalListeners() {}
diff --git a/guava/src/com/google/common/cache/RemovalNotification.java b/guava/src/com/google/common/cache/RemovalNotification.java
index f6df2f3..7dd9ba4 100644
--- a/guava/src/com/google/common/cache/RemovalNotification.java
+++ b/guava/src/com/google/common/cache/RemovalNotification.java
@@ -18,7 +18,6 @@ package com.google.common.cache;
import static com.google.common.base.Preconditions.checkNotNull;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
@@ -37,14 +36,25 @@ import javax.annotation.Nullable;
* @author Charles Fry
* @since 10.0
*/
- at Beta
@GwtCompatible
public final class RemovalNotification<K, V> implements Entry<K, V> {
@Nullable private final K key;
@Nullable private final V value;
private final RemovalCause cause;
- RemovalNotification(@Nullable K key, @Nullable V value, RemovalCause cause) {
+ /**
+ * Creates a new {@code RemovalNotification} for the given {@code key}/{@code value} pair, with
+ * the given {@code cause} for the removal. The {@code key} and/or {@code value} may be
+ * {@code null} if they were already garbage collected.
+ *
+ * @since 19.0
+ */
+ public static <K, V> RemovalNotification<K, V> create(
+ @Nullable K key, @Nullable V value, RemovalCause cause) {
+ return new RemovalNotification(key, value, cause);
+ }
+
+ private RemovalNotification(@Nullable K key, @Nullable V value, RemovalCause cause) {
this.key = key;
this.value = value;
this.cause = checkNotNull(cause);
diff --git a/guava/src/com/google/common/cache/Weigher.java b/guava/src/com/google/common/cache/Weigher.java
index 5720cb8..9ed07d1 100644
--- a/guava/src/com/google/common/cache/Weigher.java
+++ b/guava/src/com/google/common/cache/Weigher.java
@@ -14,7 +14,6 @@
package com.google.common.cache;
-import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
@@ -23,7 +22,6 @@ import com.google.common.annotations.GwtCompatible;
* @author Charles Fry
* @since 11.0
*/
- at Beta
@GwtCompatible
public interface Weigher<K, V> {
diff --git a/guava/src/com/google/common/cache/package-info.java b/guava/src/com/google/common/cache/package-info.java
index ea0297b..878f29e 100644
--- a/guava/src/com/google/common/cache/package-info.java
+++ b/guava/src/com/google/common/cache/package-info.java
@@ -24,7 +24,7 @@
* {@link com.google.common.cache.CacheStats}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CachesExplained">caches</a>.
+ * "https://github.com/google/guava/wiki/CachesExplained">caches</a>.
*
* <p>This package is a part of the open-source
* <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
diff --git a/guava/src/com/google/common/collect/AbstractBiMap.java b/guava/src/com/google/common/collect/AbstractBiMap.java
index 9cefd6c..3ede377 100644
--- a/guava/src/com/google/common/collect/AbstractBiMap.java
+++ b/guava/src/com/google/common/collect/AbstractBiMap.java
@@ -23,6 +23,7 @@ import static com.google.common.collect.CollectPreconditions.checkRemove;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Objects;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -63,7 +64,8 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
inverse = forward;
}
- @Override protected Map<K, V> delegate() {
+ @Override
+ protected Map<K, V> delegate() {
return delegate;
}
@@ -101,13 +103,15 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
// Query Operations (optimizations)
- @Override public boolean containsValue(@Nullable Object value) {
+ @Override
+ public boolean containsValue(@Nullable Object value) {
return inverse.containsKey(value);
}
// Modification Operations
- @Override public V put(@Nullable K key, @Nullable V value) {
+ @Override
+ public V put(@Nullable K key, @Nullable V value) {
return putInBothMaps(key, value, false);
}
@@ -133,15 +137,15 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
return oldValue;
}
- private void updateInverseMap(
- K key, boolean containedKey, V oldValue, V newValue) {
+ private void updateInverseMap(K key, boolean containedKey, V oldValue, V newValue) {
if (containedKey) {
removeFromInverseMap(oldValue);
}
inverse.delegate.put(newValue, key);
}
- @Override public V remove(@Nullable Object key) {
+ @Override
+ public V remove(@Nullable Object key) {
return containsKey(key) ? removeFromBothMaps(key) : null;
}
@@ -157,13 +161,15 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
// Bulk Operations
- @Override public void putAll(Map<? extends K, ? extends V> map) {
+ @Override
+ public void putAll(Map<? extends K, ? extends V> map) {
for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
- @Override public void clear() {
+ @Override
+ public void clear() {
delegate.clear();
inverse.delegate.clear();
}
@@ -177,21 +183,26 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
private transient Set<K> keySet;
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
Set<K> result = keySet;
return (result == null) ? keySet = new KeySet() : result;
}
+ @WeakOuter
private class KeySet extends ForwardingSet<K> {
- @Override protected Set<K> delegate() {
+ @Override
+ protected Set<K> delegate() {
return delegate.keySet();
}
- @Override public void clear() {
+ @Override
+ public void clear() {
AbstractBiMap.this.clear();
}
- @Override public boolean remove(Object key) {
+ @Override
+ public boolean remove(Object key) {
if (!contains(key)) {
return false;
}
@@ -199,22 +210,26 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
return true;
}
- @Override public boolean removeAll(Collection<?> keysToRemove) {
+ @Override
+ public boolean removeAll(Collection<?> keysToRemove) {
return standardRemoveAll(keysToRemove);
}
- @Override public boolean retainAll(Collection<?> keysToRetain) {
+ @Override
+ public boolean retainAll(Collection<?> keysToRetain) {
return standardRetainAll(keysToRetain);
}
- @Override public Iterator<K> iterator() {
+ @Override
+ public Iterator<K> iterator() {
return Maps.keyIterator(entrySet().iterator());
}
}
private transient Set<V> valueSet;
- @Override public Set<V> values() {
+ @Override
+ public Set<V> values() {
/*
* We can almost reuse the inverse's keySet, except we have to fix the
* iteration order so that it is consistent with the forward map.
@@ -223,49 +238,60 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
return (result == null) ? valueSet = new ValueSet() : result;
}
+ @WeakOuter
private class ValueSet extends ForwardingSet<V> {
final Set<V> valuesDelegate = inverse.keySet();
- @Override protected Set<V> delegate() {
+ @Override
+ protected Set<V> delegate() {
return valuesDelegate;
}
- @Override public Iterator<V> iterator() {
+ @Override
+ public Iterator<V> iterator() {
return Maps.valueIterator(entrySet().iterator());
}
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
return standardToArray();
}
- @Override public <T> T[] toArray(T[] array) {
+ @Override
+ public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return standardToString();
}
}
private transient Set<Entry<K, V>> entrySet;
- @Override public Set<Entry<K, V>> entrySet() {
+ @Override
+ public Set<Entry<K, V>> entrySet() {
Set<Entry<K, V>> result = entrySet;
return (result == null) ? entrySet = new EntrySet() : result;
}
+ @WeakOuter
private class EntrySet extends ForwardingSet<Entry<K, V>> {
final Set<Entry<K, V>> esDelegate = delegate.entrySet();
- @Override protected Set<Entry<K, V>> delegate() {
+ @Override
+ protected Set<Entry<K, V>> delegate() {
return esDelegate;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
AbstractBiMap.this.clear();
}
- @Override public boolean remove(Object object) {
+ @Override
+ public boolean remove(Object object) {
if (!esDelegate.contains(object)) {
return false;
}
@@ -282,43 +308,47 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
return true;
}
- @Override public Iterator<Entry<K, V>> iterator() {
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
final Iterator<Entry<K, V>> iterator = esDelegate.iterator();
return new Iterator<Entry<K, V>>() {
Entry<K, V> entry;
- @Override public boolean hasNext() {
+ @Override
+ public boolean hasNext() {
return iterator.hasNext();
}
- @Override public Entry<K, V> next() {
+ @Override
+ public Entry<K, V> next() {
entry = iterator.next();
final Entry<K, V> finalEntry = entry;
return new ForwardingMapEntry<K, V>() {
- @Override protected Entry<K, V> delegate() {
+ @Override
+ protected Entry<K, V> delegate() {
return finalEntry;
}
- @Override public V setValue(V value) {
+ @Override
+ public V setValue(V value) {
// Preconditions keep the map and inverse consistent.
checkState(contains(this), "entry no longer in map");
// similar to putInBothMaps, but set via entry
if (Objects.equal(value, getValue())) {
return value;
}
- checkArgument(!containsValue(value),
- "value already present: %s", value);
+ checkArgument(!containsValue(value), "value already present: %s", value);
V oldValue = finalEntry.setValue(value);
- checkState(Objects.equal(value, get(getKey())),
- "entry no longer in map");
+ checkState(Objects.equal(value, get(getKey())), "entry no longer in map");
updateInverseMap(getKey(), true, oldValue, value);
return oldValue;
}
};
}
- @Override public void remove() {
+ @Override
+ public void remove() {
checkRemove(entry != null);
V value = entry.getValue();
iterator.remove();
@@ -329,22 +359,33 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
// See java.util.Collections.CheckedEntrySet for details on attacks.
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
return standardToArray();
}
- @Override public <T> T[] toArray(T[] array) {
+
+ @Override
+ public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
- @Override public boolean contains(Object o) {
+
+ @Override
+ public boolean contains(Object o) {
return Maps.containsEntryImpl(delegate(), o);
}
- @Override public boolean containsAll(Collection<?> c) {
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
return standardContainsAll(c);
}
- @Override public boolean removeAll(Collection<?> c) {
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
return standardRemoveAll(c);
}
- @Override public boolean retainAll(Collection<?> c) {
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
return standardRetainAll(c);
}
}
@@ -385,8 +426,7 @@ abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
@GwtIncompatible("java.io.ObjectInputStream")
@SuppressWarnings("unchecked") // reading data stored by writeObject
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
setInverse((AbstractBiMap<V, K>) stream.readObject());
}
diff --git a/guava/src/com/google/common/collect/AbstractIndexedListIterator.java b/guava/src/com/google/common/collect/AbstractIndexedListIterator.java
index a58a2a0..6072f2e 100644
--- a/guava/src/com/google/common/collect/AbstractIndexedListIterator.java
+++ b/guava/src/com/google/common/collect/AbstractIndexedListIterator.java
@@ -31,8 +31,7 @@ import java.util.NoSuchElementException;
* @author Jared Levy
*/
@GwtCompatible
-abstract class AbstractIndexedListIterator<E>
- extends UnmodifiableListIterator<E> {
+abstract class AbstractIndexedListIterator<E> extends UnmodifiableListIterator<E> {
private final int size;
private int position;
diff --git a/guava/src/com/google/common/collect/AbstractIterator.java b/guava/src/com/google/common/collect/AbstractIterator.java
index 70492e0..23a3421 100644
--- a/guava/src/com/google/common/collect/AbstractIterator.java
+++ b/guava/src/com/google/common/collect/AbstractIterator.java
@@ -56,7 +56,7 @@ import java.util.NoSuchElementException;
* <p>This class supports iterators that include null elements.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
// When making changes to this class, please also update the copy at
// com.google.common.base.AbstractIterator
diff --git a/guava/src/com/google/common/collect/AbstractListMultimap.java b/guava/src/com/google/common/collect/AbstractListMultimap.java
index 3759c93..3cedc6c 100644
--- a/guava/src/com/google/common/collect/AbstractListMultimap.java
+++ b/guava/src/com/google/common/collect/AbstractListMultimap.java
@@ -31,11 +31,11 @@ import javax.annotation.Nullable;
* List}.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
-abstract class AbstractListMultimap<K, V>
- extends AbstractMapBasedMultimap<K, V> implements ListMultimap<K, V> {
+abstract class AbstractListMultimap<K, V> extends AbstractMapBasedMultimap<K, V>
+ implements ListMultimap<K, V> {
/**
* Creates a new multimap that uses the provided map.
*
@@ -46,7 +46,8 @@ abstract class AbstractListMultimap<K, V>
super(map);
}
- @Override abstract List<V> createCollection();
+ @Override
+ abstract List<V> createCollection();
@Override
List<V> createUnmodifiableEmptyCollection() {
@@ -62,7 +63,8 @@ abstract class AbstractListMultimap<K, V>
* insertion ordering, this method returns a {@link List}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
- @Override public List<V> get(@Nullable K key) {
+ @Override
+ public List<V> get(@Nullable K key) {
return (List<V>) super.get(key);
}
@@ -73,7 +75,8 @@ abstract class AbstractListMultimap<K, V>
* insertion ordering, this method returns a {@link List}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
- @Override public List<V> removeAll(@Nullable Object key) {
+ @Override
+ public List<V> removeAll(@Nullable Object key) {
return (List<V>) super.removeAll(key);
}
@@ -84,8 +87,8 @@ abstract class AbstractListMultimap<K, V>
* insertion ordering, this method returns a {@link List}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
- @Override public List<V> replaceValues(
- @Nullable K key, Iterable<? extends V> values) {
+ @Override
+ public List<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
return (List<V>) super.replaceValues(key, values);
}
@@ -96,7 +99,8 @@ abstract class AbstractListMultimap<K, V>
* @param value value to store in the multimap
* @return {@code true} always
*/
- @Override public boolean put(@Nullable K key, @Nullable V value) {
+ @Override
+ public boolean put(@Nullable K key, @Nullable V value) {
return super.put(key, value);
}
@@ -106,7 +110,8 @@ abstract class AbstractListMultimap<K, V>
* <p>Though the method signature doesn't say so explicitly, the returned map
* has {@link List} values.
*/
- @Override public Map<K, Collection<V>> asMap() {
+ @Override
+ public Map<K, Collection<V>> asMap() {
return super.asMap();
}
@@ -117,7 +122,8 @@ abstract class AbstractListMultimap<K, V>
* contain the same values in the same order. If the value orderings disagree,
* the multimaps will not be considered equal.
*/
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return super.equals(object);
}
diff --git a/guava/src/com/google/common/collect/AbstractMapBasedMultimap.java b/guava/src/com/google/common/collect/AbstractMapBasedMultimap.java
index c39faab..fa4eae8 100644
--- a/guava/src/com/google/common/collect/AbstractMapBasedMultimap.java
+++ b/guava/src/com/google/common/collect/AbstractMapBasedMultimap.java
@@ -22,7 +22,8 @@ import static com.google.common.collect.CollectPreconditions.checkRemove;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
-import com.google.common.collect.Maps.ImprovedAbstractMap;
+import com.google.common.collect.Maps.ViewCachingAbstractMap;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.AbstractCollection;
@@ -230,7 +231,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return removeAll(key);
}
- // TODO(user): investigate atomic failure?
+ // TODO(lowasser): investigate atomic failure?
Collection<V> collection = getOrCreateCollection(key);
Collection<V> oldValues = createCollection();
oldValues.addAll(collection);
@@ -327,8 +328,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
}
- private List<V> wrapList(
- @Nullable K key, List<V> list, @Nullable WrappedCollection ancestor) {
+ private List<V> wrapList(@Nullable K key, List<V> list, @Nullable WrappedCollection ancestor) {
return (list instanceof RandomAccess)
? new RandomAccessWrappedList(key, list, ancestor)
: new WrappedList(key, list, ancestor);
@@ -351,19 +351,19 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
* removeIfEmpty}, and {@code addToMap} methods call the corresponding methods
* of the full wrapped collection.
*/
+ @WeakOuter
private class WrappedCollection extends AbstractCollection<V> {
final K key;
Collection<V> delegate;
final WrappedCollection ancestor;
final Collection<V> ancestorDelegate;
- WrappedCollection(@Nullable K key, Collection<V> delegate,
- @Nullable WrappedCollection ancestor) {
+ WrappedCollection(
+ @Nullable K key, Collection<V> delegate, @Nullable WrappedCollection ancestor) {
this.key = key;
this.delegate = delegate;
this.ancestor = ancestor;
- this.ancestorDelegate
- = (ancestor == null) ? null : ancestor.getDelegate();
+ this.ancestorDelegate = (ancestor == null) ? null : ancestor.getDelegate();
}
/**
@@ -418,12 +418,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
}
- @Override public int size() {
+ @Override
+ public int size() {
refreshIfEmpty();
return delegate.size();
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -431,12 +433,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return delegate.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
refreshIfEmpty();
return delegate.hashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
refreshIfEmpty();
return delegate.toString();
}
@@ -445,7 +449,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return delegate;
}
- @Override public Iterator<V> iterator() {
+ @Override
+ public Iterator<V> iterator() {
refreshIfEmpty();
return new WrappedIterator();
}
@@ -499,7 +504,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
}
- @Override public boolean add(V value) {
+ @Override
+ public boolean add(V value) {
refreshIfEmpty();
boolean wasEmpty = delegate.isEmpty();
boolean changed = delegate.add(value);
@@ -518,11 +524,12 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
// The following methods are provided for better performance.
- @Override public boolean addAll(Collection<? extends V> collection) {
+ @Override
+ public boolean addAll(Collection<? extends V> collection) {
if (collection.isEmpty()) {
return false;
}
- int oldSize = size(); // calls refreshIfEmpty
+ int oldSize = size(); // calls refreshIfEmpty
boolean changed = delegate.addAll(collection);
if (changed) {
int newSize = delegate.size();
@@ -534,27 +541,31 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return changed;
}
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
refreshIfEmpty();
return delegate.contains(o);
}
- @Override public boolean containsAll(Collection<?> c) {
+ @Override
+ public boolean containsAll(Collection<?> c) {
refreshIfEmpty();
return delegate.containsAll(c);
}
- @Override public void clear() {
- int oldSize = size(); // calls refreshIfEmpty
+ @Override
+ public void clear() {
+ int oldSize = size(); // calls refreshIfEmpty
if (oldSize == 0) {
return;
}
delegate.clear();
totalSize -= oldSize;
- removeIfEmpty(); // maybe shouldn't be removed if this is a sublist
+ removeIfEmpty(); // maybe shouldn't be removed if this is a sublist
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
refreshIfEmpty();
boolean changed = delegate.remove(o);
if (changed) {
@@ -564,11 +575,12 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return changed;
}
- @Override public boolean removeAll(Collection<?> c) {
+ @Override
+ public boolean removeAll(Collection<?> c) {
if (c.isEmpty()) {
return false;
}
- int oldSize = size(); // calls refreshIfEmpty
+ int oldSize = size(); // calls refreshIfEmpty
boolean changed = delegate.removeAll(c);
if (changed) {
int newSize = delegate.size();
@@ -578,9 +590,10 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return changed;
}
- @Override public boolean retainAll(Collection<?> c) {
+ @Override
+ public boolean retainAll(Collection<?> c) {
checkNotNull(c);
- int oldSize = size(); // calls refreshIfEmpty
+ int oldSize = size(); // calls refreshIfEmpty
boolean changed = delegate.retainAll(c);
if (changed) {
int newSize = delegate.size();
@@ -598,6 +611,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
/** Set decorator that stays in sync with the multimap values for a key. */
+ @WeakOuter
private class WrappedSet extends WrappedCollection implements Set<V> {
WrappedSet(@Nullable K key, Set<V> delegate) {
super(key, delegate, null);
@@ -608,7 +622,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
if (c.isEmpty()) {
return false;
}
- int oldSize = size(); // calls refreshIfEmpty
+ int oldSize = size(); // calls refreshIfEmpty
// Guava issue 1013: AbstractSet and most JDK set implementations are
// susceptible to quadratic removeAll performance on lists;
@@ -626,10 +640,9 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
/**
* SortedSet decorator that stays in sync with the multimap values for a key.
*/
- private class WrappedSortedSet extends WrappedCollection
- implements SortedSet<V> {
- WrappedSortedSet(@Nullable K key, SortedSet<V> delegate,
- @Nullable WrappedCollection ancestor) {
+ @WeakOuter
+ private class WrappedSortedSet extends WrappedCollection implements SortedSet<V> {
+ WrappedSortedSet(@Nullable K key, SortedSet<V> delegate, @Nullable WrappedCollection ancestor) {
super(key, delegate, ancestor);
}
@@ -658,7 +671,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
public SortedSet<V> headSet(V toElement) {
refreshIfEmpty();
return new WrappedSortedSet(
- getKey(), getSortedSetDelegate().headSet(toElement),
+ getKey(),
+ getSortedSetDelegate().headSet(toElement),
(getAncestor() == null) ? this : getAncestor());
}
@@ -666,7 +680,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
public SortedSet<V> subSet(V fromElement, V toElement) {
refreshIfEmpty();
return new WrappedSortedSet(
- getKey(), getSortedSetDelegate().subSet(fromElement, toElement),
+ getKey(),
+ getSortedSetDelegate().subSet(fromElement, toElement),
(getAncestor() == null) ? this : getAncestor());
}
@@ -674,12 +689,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
public SortedSet<V> tailSet(V fromElement) {
refreshIfEmpty();
return new WrappedSortedSet(
- getKey(), getSortedSetDelegate().tailSet(fromElement),
+ getKey(),
+ getSortedSetDelegate().tailSet(fromElement),
(getAncestor() == null) ? this : getAncestor());
}
}
@GwtIncompatible("NavigableSet")
+ @WeakOuter
class WrappedNavigableSet extends WrappedSortedSet implements NavigableSet<V> {
WrappedNavigableSet(
@Nullable K key, NavigableSet<V> delegate, @Nullable WrappedCollection ancestor) {
@@ -722,8 +739,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
private NavigableSet<V> wrap(NavigableSet<V> wrapped) {
- return new WrappedNavigableSet(key, wrapped,
- (getAncestor() == null) ? this : getAncestor());
+ return new WrappedNavigableSet(key, wrapped, (getAncestor() == null) ? this : getAncestor());
}
@Override
@@ -755,9 +771,9 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
/** List decorator that stays in sync with the multimap values for a key. */
+ @WeakOuter
private class WrappedList extends WrappedCollection implements List<V> {
- WrappedList(@Nullable K key, List<V> delegate,
- @Nullable WrappedCollection ancestor) {
+ WrappedList(@Nullable K key, List<V> delegate, @Nullable WrappedCollection ancestor) {
super(key, delegate, ancestor);
}
@@ -770,7 +786,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
if (c.isEmpty()) {
return false;
}
- int oldSize = size(); // calls refreshIfEmpty
+ int oldSize = size(); // calls refreshIfEmpty
boolean changed = getListDelegate().addAll(index, c);
if (changed) {
int newSize = getDelegate().size();
@@ -841,14 +857,14 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
@Override
public List<V> subList(int fromIndex, int toIndex) {
refreshIfEmpty();
- return wrapList(getKey(),
+ return wrapList(
+ getKey(),
getListDelegate().subList(fromIndex, toIndex),
(getAncestor() == null) ? this : getAncestor());
}
/** ListIterator decorator. */
- private class WrappedListIterator extends WrappedIterator
- implements ListIterator<V> {
+ private class WrappedListIterator extends WrappedIterator implements ListIterator<V> {
WrappedListIterator() {}
public WrappedListIterator(int index) {
@@ -900,10 +916,9 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
* List decorator that stays in sync with the multimap values for a key and
* supports rapid random access.
*/
- private class RandomAccessWrappedList extends WrappedList
- implements RandomAccess {
- RandomAccessWrappedList(@Nullable K key, List<V> delegate,
- @Nullable WrappedCollection ancestor) {
+ private class RandomAccessWrappedList extends WrappedList implements RandomAccess {
+ RandomAccessWrappedList(
+ @Nullable K key, List<V> delegate, @Nullable WrappedCollection ancestor) {
super(key, delegate, ancestor);
}
}
@@ -913,17 +928,19 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
// TreeMultimap uses NavigableKeySet explicitly, but we don't handle that here for GWT
// compatibility reasons
return (map instanceof SortedMap)
- ? new SortedKeySet((SortedMap<K, Collection<V>>) map) : new KeySet(map);
+ ? new SortedKeySet((SortedMap<K, Collection<V>>) map)
+ : new KeySet(map);
}
+ @WeakOuter
private class KeySet extends Maps.KeySet<K, Collection<V>> {
KeySet(final Map<K, Collection<V>> subMap) {
super(subMap);
}
- @Override public Iterator<K> iterator() {
- final Iterator<Map.Entry<K, Collection<V>>> entryIterator
- = map().entrySet().iterator();
+ @Override
+ public Iterator<K> iterator() {
+ final Iterator<Map.Entry<K, Collection<V>>> entryIterator = map().entrySet().iterator();
return new Iterator<K>() {
Map.Entry<K, Collection<V>> entry;
@@ -931,11 +948,13 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
public boolean hasNext() {
return entryIterator.hasNext();
}
+
@Override
public K next() {
entry = entryIterator.next();
return entry.getKey();
}
+
@Override
public void remove() {
checkRemove(entry != null);
@@ -949,7 +968,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
// The following methods are included for better performance.
- @Override public boolean remove(Object key) {
+ @Override
+ public boolean remove(Object key) {
int count = 0;
Collection<V> collection = map().remove(key);
if (collection != null) {
@@ -965,19 +985,23 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
Iterators.clear(iterator());
}
- @Override public boolean containsAll(Collection<?> c) {
+ @Override
+ public boolean containsAll(Collection<?> c) {
return map().keySet().containsAll(c);
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return this == object || this.map().keySet().equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return map().keySet().hashCode();
}
}
+ @WeakOuter
private class SortedKeySet extends KeySet implements SortedSet<K> {
SortedKeySet(SortedMap<K, Collection<V>> subMap) {
@@ -1020,6 +1044,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
@GwtIncompatible("NavigableSet")
+ @WeakOuter
class NavigableKeySet extends SortedKeySet implements NavigableSet<K> {
NavigableKeySet(NavigableMap<K, Collection<V>> subMap) {
super(subMap);
@@ -1166,7 +1191,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
* <p>The iterator generated by the returned collection traverses the values
* for one key, followed by the values of a second key, and so on.
*/
- @Override public Collection<V> values() {
+ @Override
+ public Collection<V> values() {
return super.values();
}
@@ -1224,10 +1250,12 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
// TreeMultimap uses NavigableAsMap explicitly, but we don't handle that here for GWT
// compatibility reasons
return (map instanceof SortedMap)
- ? new SortedAsMap((SortedMap<K, Collection<V>>) map) : new AsMap(map);
+ ? new SortedAsMap((SortedMap<K, Collection<V>>) map)
+ : new AsMap(map);
}
- private class AsMap extends ImprovedAbstractMap<K, Collection<V>> {
+ @WeakOuter
+ private class AsMap extends ViewCachingAbstractMap<K, Collection<V>> {
/**
* Usually the same as map, but smaller for the headMap(), tailMap(), or
* subMap() of a SortedAsMap.
@@ -1245,11 +1273,13 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
// The following methods are included for performance.
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return Maps.safeContainsKey(submap, key);
}
- @Override public Collection<V> get(Object key) {
+ @Override
+ public Collection<V> get(Object key) {
Collection<V> collection = Maps.safeGet(submap, key);
if (collection == null) {
return null;
@@ -1259,7 +1289,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return wrapCollection(k, collection);
}
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
return AbstractMapBasedMultimap.this.keySet();
}
@@ -1268,7 +1299,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return submap.size();
}
- @Override public Collection<V> remove(Object key) {
+ @Override
+ public Collection<V> remove(Object key) {
Collection<V> collection = submap.remove(key);
if (collection == null) {
return null;
@@ -1281,15 +1313,18 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return output;
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return this == object || submap.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return submap.hashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return submap.toString();
}
@@ -1307,23 +1342,27 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
return Maps.immutableEntry(key, wrapCollection(key, entry.getValue()));
}
+ @WeakOuter
class AsMapEntries extends Maps.EntrySet<K, Collection<V>> {
@Override
Map<K, Collection<V>> map() {
return AsMap.this;
}
- @Override public Iterator<Map.Entry<K, Collection<V>>> iterator() {
+ @Override
+ public Iterator<Map.Entry<K, Collection<V>>> iterator() {
return new AsMapIterator();
}
// The following methods are included for performance.
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
return Collections2.safeContains(submap.entrySet(), o);
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
if (!contains(o)) {
return false;
}
@@ -1335,8 +1374,7 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
/** Iterator across all keys and value collections. */
class AsMapIterator implements Iterator<Map.Entry<K, Collection<V>>> {
- final Iterator<Map.Entry<K, Collection<V>>> delegateIterator
- = submap.entrySet().iterator();
+ final Iterator<Map.Entry<K, Collection<V>>> delegateIterator = submap.entrySet().iterator();
Collection<V> collection;
@Override
@@ -1360,8 +1398,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
}
}
- private class SortedAsMap extends AsMap
- implements SortedMap<K, Collection<V>> {
+ @WeakOuter
+ private class SortedAsMap extends AsMap implements SortedMap<K, Collection<V>> {
SortedAsMap(SortedMap<K, Collection<V>> submap) {
super(submap);
}
@@ -1404,7 +1442,8 @@ abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V>
// returns a SortedSet, even though returning a Set would be sufficient to
// satisfy the SortedMap.keySet() interface
- @Override public SortedSet<K> keySet() {
+ @Override
+ public SortedSet<K> keySet() {
SortedSet<K> result = sortedKeySet;
return (result == null) ? sortedKeySet = createKeySet() : result;
}
diff --git a/guava/src/com/google/common/collect/AbstractMapBasedMultiset.java b/guava/src/com/google/common/collect/AbstractMapBasedMultiset.java
index 6041c09..7bfc37f 100644
--- a/guava/src/com/google/common/collect/AbstractMapBasedMultiset.java
+++ b/guava/src/com/google/common/collect/AbstractMapBasedMultiset.java
@@ -45,8 +45,7 @@ import javax.annotation.Nullable;
* @author Kevin Bourrillion
*/
@GwtCompatible(emulated = true)
-abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
- implements Serializable {
+abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E> implements Serializable {
private transient Map<E, Count> backingMap;
@@ -84,8 +83,7 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
@Override
Iterator<Entry<E>> entryIterator() {
- final Iterator<Map.Entry<E, Count>> backingEntries =
- backingMap.entrySet().iterator();
+ final Iterator<Map.Entry<E, Count>> backingEntries = backingMap.entrySet().iterator();
return new Iterator<Multiset.Entry<E>>() {
Map.Entry<E, Count> toRemove;
@@ -103,6 +101,7 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
public E getElement() {
return mapEntry.getKey();
}
+
@Override
public int getCount() {
Count count = mapEntry.getValue();
@@ -143,11 +142,13 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
// Optimizations - Query Operations
- @Override public int size() {
+ @Override
+ public int size() {
return Ints.saturatedCast(size);
}
- @Override public Iterator<E> iterator() {
+ @Override
+ public Iterator<E> iterator() {
return new MapBasedMultisetIterator();
}
@@ -197,7 +198,8 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
}
}
- @Override public int count(@Nullable Object element) {
+ @Override
+ public int count(@Nullable Object element) {
Count frequency = Maps.safeGet(backingMap, element);
return (frequency == null) ? 0 : frequency.get();
}
@@ -211,12 +213,12 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
* {@link Integer#MAX_VALUE} occurrences of {@code element} in this
* multiset.
*/
- @Override public int add(@Nullable E element, int occurrences) {
+ @Override
+ public int add(@Nullable E element, int occurrences) {
if (occurrences == 0) {
return count(element);
}
- checkArgument(
- occurrences > 0, "occurrences cannot be negative: %s", occurrences);
+ checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
Count frequency = backingMap.get(element);
int oldCount;
if (frequency == null) {
@@ -225,20 +227,19 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
} else {
oldCount = frequency.get();
long newCount = (long) oldCount + (long) occurrences;
- checkArgument(newCount <= Integer.MAX_VALUE,
- "too many occurrences: %s", newCount);
+ checkArgument(newCount <= Integer.MAX_VALUE, "too many occurrences: %s", newCount);
frequency.getAndAdd(occurrences);
}
size += occurrences;
return oldCount;
}
- @Override public int remove(@Nullable Object element, int occurrences) {
+ @Override
+ public int remove(@Nullable Object element, int occurrences) {
if (occurrences == 0) {
return count(element);
}
- checkArgument(
- occurrences > 0, "occurrences cannot be negative: %s", occurrences);
+ checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
Count frequency = backingMap.get(element);
if (frequency == null) {
return 0;
@@ -260,7 +261,8 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
}
// Roughly a 33% performance improvement over AbstractMultiset.setCount().
- @Override public int setCount(@Nullable E element, int count) {
+ @Override
+ public int setCount(@Nullable E element, int count) {
checkNonnegative(count, "count");
Count existingCounter;
@@ -291,7 +293,6 @@ abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E>
// Don't allow default serialization.
@GwtIncompatible("java.io.ObjectStreamException")
- @SuppressWarnings("unused") // actually used during deserialization
private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("Stream data required");
}
diff --git a/guava/src/com/google/common/collect/AbstractMapEntry.java b/guava/src/com/google/common/collect/AbstractMapEntry.java
index d790748..198212a 100644
--- a/guava/src/com/google/common/collect/AbstractMapEntry.java
+++ b/guava/src/com/google/common/collect/AbstractMapEntry.java
@@ -43,7 +43,8 @@ abstract class AbstractMapEntry<K, V> implements Entry<K, V> {
throw new UnsupportedOperationException();
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object instanceof Entry) {
Entry<?, ?> that = (Entry<?, ?>) object;
return Objects.equal(this.getKey(), that.getKey())
@@ -52,7 +53,8 @@ abstract class AbstractMapEntry<K, V> implements Entry<K, V> {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
K k = getKey();
V v = getValue();
return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode());
@@ -61,7 +63,8 @@ abstract class AbstractMapEntry<K, V> implements Entry<K, V> {
/**
* Returns a string representation of the form {@code {key}={value}}.
*/
- @Override public String toString() {
+ @Override
+ public String toString() {
return getKey() + "=" + getValue();
}
}
diff --git a/guava/src/com/google/common/collect/AbstractMultimap.java b/guava/src/com/google/common/collect/AbstractMultimap.java
index 9351956..6b94c12 100644
--- a/guava/src/com/google/common/collect/AbstractMultimap.java
+++ b/guava/src/com/google/common/collect/AbstractMultimap.java
@@ -19,6 +19,7 @@ package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.AbstractCollection;
import java.util.Collection;
@@ -31,7 +32,7 @@ import javax.annotation.Nullable;
/**
* A skeleton {@code Multimap} implementation, not necessarily in terms of a {@code Map}.
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible
@@ -57,7 +58,7 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
Collection<V> collection = asMap().get(key);
return collection != null && collection.contains(value);
}
-
+
@Override
public boolean remove(@Nullable Object key, @Nullable Object value) {
Collection<V> collection = asMap().get(key);
@@ -99,7 +100,7 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
putAll(key, values);
return result;
}
-
+
private transient Collection<Entry<K, V>> entries;
@Override
@@ -107,7 +108,7 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
Collection<Entry<K, V>> result = entries;
return (result == null) ? entries = createEntries() : result;
}
-
+
Collection<Entry<K, V>> createEntries() {
if (this instanceof SetMultimap) {
return new EntrySet();
@@ -115,7 +116,8 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
return new Entries();
}
}
-
+
+ @WeakOuter
private class Entries extends Multimaps.Entries<K, V> {
@Override
Multimap<K, V> multimap() {
@@ -127,7 +129,8 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
return entryIterator();
}
}
-
+
+ @WeakOuter
private class EntrySet extends Entries implements Set<Entry<K, V>> {
@Override
public int hashCode() {
@@ -137,9 +140,9 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
@Override
public boolean equals(@Nullable Object obj) {
return Sets.equalsImpl(this, obj);
- }
+ }
}
-
+
abstract Iterator<Entry<K, V>> entryIterator();
private transient Set<K> keySet;
@@ -153,66 +156,72 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
Set<K> createKeySet() {
return new Maps.KeySet<K, Collection<V>>(asMap());
}
-
+
private transient Multiset<K> keys;
-
+
@Override
public Multiset<K> keys() {
Multiset<K> result = keys;
return (result == null) ? keys = createKeys() : result;
}
-
+
Multiset<K> createKeys() {
return new Multimaps.Keys<K, V>(this);
}
-
+
private transient Collection<V> values;
-
+
@Override
public Collection<V> values() {
Collection<V> result = values;
return (result == null) ? values = createValues() : result;
}
-
+
Collection<V> createValues() {
return new Values();
}
+ @WeakOuter
class Values extends AbstractCollection<V> {
- @Override public Iterator<V> iterator() {
+ @Override
+ public Iterator<V> iterator() {
return valueIterator();
}
- @Override public int size() {
+ @Override
+ public int size() {
return AbstractMultimap.this.size();
}
- @Override public boolean contains(@Nullable Object o) {
+ @Override
+ public boolean contains(@Nullable Object o) {
return AbstractMultimap.this.containsValue(o);
}
- @Override public void clear() {
+ @Override
+ public void clear() {
AbstractMultimap.this.clear();
}
}
-
+
Iterator<V> valueIterator() {
return Maps.valueIterator(entries().iterator());
}
-
+
private transient Map<K, Collection<V>> asMap;
-
+
@Override
public Map<K, Collection<V>> asMap() {
Map<K, Collection<V>> result = asMap;
return (result == null) ? asMap = createAsMap() : result;
}
-
+
abstract Map<K, Collection<V>> createAsMap();
// Comparison and hashing
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return Multimaps.equalsImpl(this, object);
}
@@ -224,7 +233,8 @@ abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
*
* @see Map#hashCode
*/
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return asMap().hashCode();
}
diff --git a/guava/src/com/google/common/collect/AbstractMultiset.java b/guava/src/com/google/common/collect/AbstractMultiset.java
index a271e34..c55373f 100644
--- a/guava/src/com/google/common/collect/AbstractMultiset.java
+++ b/guava/src/com/google/common/collect/AbstractMultiset.java
@@ -20,6 +20,7 @@ import static com.google.common.collect.Multisets.setCountImpl;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.AbstractCollection;
import java.util.Collection;
@@ -44,23 +45,26 @@ import javax.annotation.Nullable;
* @author Louis Wasserman
*/
@GwtCompatible
-abstract class AbstractMultiset<E> extends AbstractCollection<E>
- implements Multiset<E> {
+abstract class AbstractMultiset<E> extends AbstractCollection<E> implements Multiset<E> {
// Query Operations
- @Override public int size() {
+ @Override
+ public int size() {
return Multisets.sizeImpl(this);
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return entrySet().isEmpty();
}
- @Override public boolean contains(@Nullable Object element) {
+ @Override
+ public boolean contains(@Nullable Object element) {
return count(element) > 0;
}
- @Override public Iterator<E> iterator() {
+ @Override
+ public Iterator<E> iterator() {
return Multisets.iteratorImpl(this);
}
@@ -76,7 +80,8 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
// Modification Operations
- @Override public boolean add(@Nullable E element) {
+ @Override
+ public boolean add(@Nullable E element) {
add(element, 1);
return true;
}
@@ -86,7 +91,8 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
throw new UnsupportedOperationException();
}
- @Override public boolean remove(@Nullable Object element) {
+ @Override
+ public boolean remove(@Nullable Object element) {
return remove(element, 1) > 0;
}
@@ -113,19 +119,23 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
* <p>This implementation is highly efficient when {@code elementsToAdd}
* is itself a {@link Multiset}.
*/
- @Override public boolean addAll(Collection<? extends E> elementsToAdd) {
+ @Override
+ public boolean addAll(Collection<? extends E> elementsToAdd) {
return Multisets.addAllImpl(this, elementsToAdd);
}
- @Override public boolean removeAll(Collection<?> elementsToRemove) {
+ @Override
+ public boolean removeAll(Collection<?> elementsToRemove) {
return Multisets.removeAllImpl(this, elementsToRemove);
}
- @Override public boolean retainAll(Collection<?> elementsToRetain) {
+ @Override
+ public boolean retainAll(Collection<?> elementsToRetain) {
return Multisets.retainAllImpl(this, elementsToRetain);
}
- @Override public void clear() {
+ @Override
+ public void clear() {
Iterators.clear(entryIterator());
}
@@ -150,6 +160,7 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
return new ElementSet();
}
+ @WeakOuter
class ElementSet extends Multisets.ElementSet<E> {
@Override
Multiset<E> multiset() {
@@ -163,7 +174,8 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
private transient Set<Entry<E>> entrySet;
- @Override public Set<Entry<E>> entrySet() {
+ @Override
+ public Set<Entry<E>> entrySet() {
Set<Entry<E>> result = entrySet;
if (result == null) {
entrySet = result = createEntrySet();
@@ -171,16 +183,20 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
return result;
}
+ @WeakOuter
class EntrySet extends Multisets.EntrySet<E> {
- @Override Multiset<E> multiset() {
+ @Override
+ Multiset<E> multiset() {
return AbstractMultiset.this;
}
- @Override public Iterator<Entry<E>> iterator() {
+ @Override
+ public Iterator<Entry<E>> iterator() {
return entryIterator();
}
- @Override public int size() {
+ @Override
+ public int size() {
return distinctElements();
}
}
@@ -198,7 +214,8 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
* of the same size and if, for each element, the two multisets have the same
* count.
*/
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return Multisets.equalsImpl(this, object);
}
@@ -208,7 +225,8 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
* <p>This implementation returns the hash code of {@link
* Multiset#entrySet()}.
*/
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return entrySet().hashCode();
}
@@ -218,7 +236,8 @@ abstract class AbstractMultiset<E> extends AbstractCollection<E>
* <p>This implementation returns the result of invoking {@code toString} on
* {@link Multiset#entrySet()}.
*/
- @Override public String toString() {
+ @Override
+ public String toString() {
return entrySet().toString();
}
}
diff --git a/guava/src/com/google/common/collect/AbstractNavigableMap.java b/guava/src/com/google/common/collect/AbstractNavigableMap.java
index f6defe6..cef4859 100644
--- a/guava/src/com/google/common/collect/AbstractNavigableMap.java
+++ b/guava/src/com/google/common/collect/AbstractNavigableMap.java
@@ -16,9 +16,9 @@
package com.google.common.collect;
-import java.util.AbstractMap;
+import com.google.common.collect.Maps.IteratorBasedAbstractMap;
+
import java.util.Iterator;
-import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.NoSuchElementException;
@@ -29,15 +29,16 @@ import javax.annotation.Nullable;
/**
* Skeletal implementation of {@link NavigableMap}.
- *
+ *
* @author Louis Wasserman
*/
-abstract class AbstractNavigableMap<K, V> extends AbstractMap<K, V> implements NavigableMap<K, V> {
+abstract class AbstractNavigableMap<K, V> extends IteratorBasedAbstractMap<K, V>
+ implements NavigableMap<K, V> {
@Override
@Nullable
public abstract V get(@Nullable Object key);
-
+
@Override
@Nullable
public Entry<K, V> firstEntry() {
@@ -126,8 +127,6 @@ abstract class AbstractNavigableMap<K, V> extends AbstractMap<K, V> implements N
return Maps.keyOrNull(higherEntry(key));
}
- abstract Iterator<Entry<K, V>> entryIterator();
-
abstract Iterator<Entry<K, V>> descendingEntryIterator();
@Override
@@ -156,24 +155,6 @@ abstract class AbstractNavigableMap<K, V> extends AbstractMap<K, V> implements N
}
@Override
- public abstract int size();
-
- @Override
- public Set<Entry<K, V>> entrySet() {
- return new Maps.EntrySet<K, V>() {
- @Override
- Map<K, V> map() {
- return AbstractNavigableMap.this;
- }
-
- @Override
- public Iterator<Entry<K, V>> iterator() {
- return entryIterator();
- }
- };
- }
-
- @Override
public NavigableSet<K> descendingKeySet() {
return descendingMap().navigableKeySet();
}
@@ -182,7 +163,7 @@ abstract class AbstractNavigableMap<K, V> extends AbstractMap<K, V> implements N
public NavigableMap<K, V> descendingMap() {
return new DescendingMap();
}
-
+
private final class DescendingMap extends Maps.DescendingMap<K, V> {
@Override
NavigableMap<K, V> forward() {
@@ -194,5 +175,4 @@ abstract class AbstractNavigableMap<K, V> extends AbstractMap<K, V> implements N
return descendingEntryIterator();
}
}
-
}
diff --git a/guava/src/com/google/common/collect/AbstractRangeSet.java b/guava/src/com/google/common/collect/AbstractRangeSet.java
index dff3547..19af0e7 100644
--- a/guava/src/com/google/common/collect/AbstractRangeSet.java
+++ b/guava/src/com/google/common/collect/AbstractRangeSet.java
@@ -46,7 +46,7 @@ abstract class AbstractRangeSet<C extends Comparable> implements RangeSet<C> {
public void remove(Range<C> range) {
throw new UnsupportedOperationException();
}
-
+
@Override
public void clear() {
remove(Range.<C>all());
diff --git a/guava/src/com/google/common/collect/AbstractSequentialIterator.java b/guava/src/com/google/common/collect/AbstractSequentialIterator.java
index c6567f5..b933a57 100644
--- a/guava/src/com/google/common/collect/AbstractSequentialIterator.java
+++ b/guava/src/com/google/common/collect/AbstractSequentialIterator.java
@@ -30,7 +30,7 @@ import javax.annotation.Nullable;
*
* <p>Example: <pre> {@code
*
- * Iterator<Integer> powersOfTwo =
+ * Iterator<Integer> powersOfTwo =
* new AbstractSequentialIterator<Integer>(1) {
* protected Integer computeNext(Integer previous) {
* return (previous == 1 << 30) ? null : previous * 2;
@@ -41,8 +41,7 @@ import javax.annotation.Nullable;
* @since 12.0 (in Guava as {@code AbstractLinkedIterator} since 8.0)
*/
@GwtCompatible
-public abstract class AbstractSequentialIterator<T>
- extends UnmodifiableIterator<T> {
+public abstract class AbstractSequentialIterator<T> extends UnmodifiableIterator<T> {
private T nextOrNull;
/**
diff --git a/guava/src/com/google/common/collect/AbstractSetMultimap.java b/guava/src/com/google/common/collect/AbstractSetMultimap.java
index e43d8b1..94b7136 100644
--- a/guava/src/com/google/common/collect/AbstractSetMultimap.java
+++ b/guava/src/com/google/common/collect/AbstractSetMultimap.java
@@ -32,8 +32,8 @@ import javax.annotation.Nullable;
* @author Jared Levy
*/
@GwtCompatible
-abstract class AbstractSetMultimap<K, V>
- extends AbstractMapBasedMultimap<K, V> implements SetMultimap<K, V> {
+abstract class AbstractSetMultimap<K, V> extends AbstractMapBasedMultimap<K, V>
+ implements SetMultimap<K, V> {
/**
* Creates a new multimap that uses the provided map.
*
@@ -44,9 +44,11 @@ abstract class AbstractSetMultimap<K, V>
super(map);
}
- @Override abstract Set<V> createCollection();
+ @Override
+ abstract Set<V> createCollection();
- @Override Set<V> createUnmodifiableEmptyCollection() {
+ @Override
+ Set<V> createUnmodifiableEmptyCollection() {
return ImmutableSet.of();
}
@@ -59,7 +61,8 @@ abstract class AbstractSetMultimap<K, V>
* method returns a {@link Set}, instead of the {@link Collection} specified
* in the {@link Multimap} interface.
*/
- @Override public Set<V> get(@Nullable K key) {
+ @Override
+ public Set<V> get(@Nullable K key) {
return (Set<V>) super.get(key);
}
@@ -70,7 +73,8 @@ abstract class AbstractSetMultimap<K, V>
* method returns a {@link Set}, instead of the {@link Collection} specified
* in the {@link Multimap} interface.
*/
- @Override public Set<Map.Entry<K, V>> entries() {
+ @Override
+ public Set<Map.Entry<K, V>> entries() {
return (Set<Map.Entry<K, V>>) super.entries();
}
@@ -81,7 +85,8 @@ abstract class AbstractSetMultimap<K, V>
* method returns a {@link Set}, instead of the {@link Collection} specified
* in the {@link Multimap} interface.
*/
- @Override public Set<V> removeAll(@Nullable Object key) {
+ @Override
+ public Set<V> removeAll(@Nullable Object key) {
return (Set<V>) super.removeAll(key);
}
@@ -94,8 +99,8 @@ abstract class AbstractSetMultimap<K, V>
*
* <p>Any duplicates in {@code values} will be stored in the multimap once.
*/
- @Override public Set<V> replaceValues(
- @Nullable K key, Iterable<? extends V> values) {
+ @Override
+ public Set<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
return (Set<V>) super.replaceValues(key, values);
}
@@ -105,7 +110,8 @@ abstract class AbstractSetMultimap<K, V>
* <p>Though the method signature doesn't say so explicitly, the returned map
* has {@link Set} values.
*/
- @Override public Map<K, Collection<V>> asMap() {
+ @Override
+ public Map<K, Collection<V>> asMap() {
return super.asMap();
}
@@ -117,7 +123,8 @@ abstract class AbstractSetMultimap<K, V>
* @return {@code true} if the method increased the size of the multimap, or
* {@code false} if the multimap already contained the key-value pair
*/
- @Override public boolean put(@Nullable K key, @Nullable V value) {
+ @Override
+ public boolean put(@Nullable K key, @Nullable V value) {
return super.put(key, value);
}
@@ -128,7 +135,8 @@ abstract class AbstractSetMultimap<K, V>
* contain the same values. Equality does not depend on the ordering of keys
* or values.
*/
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return super.equals(object);
}
diff --git a/guava/src/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java b/guava/src/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java
index c561b87..8cf09dd 100644
--- a/guava/src/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java
+++ b/guava/src/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java
@@ -24,11 +24,11 @@ import java.util.SortedSet;
/**
* Basic implementation of a {@link SortedSetMultimap} with a sorted key set.
- *
- * This superclass allows {@code TreeMultimap} to override methods to return
+ *
+ * <p>This superclass allows {@code TreeMultimap} to override methods to return
* navigable set and map types in non-GWT only, while GWT code will inherit the
* SortedMap/SortedSet overrides.
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible
@@ -52,5 +52,4 @@ abstract class AbstractSortedKeySortedSetMultimap<K, V> extends AbstractSortedSe
public SortedSet<K> keySet() {
return (SortedSet<K>) super.keySet();
}
-
}
diff --git a/guava/src/com/google/common/collect/AbstractSortedMultiset.java b/guava/src/com/google/common/collect/AbstractSortedMultiset.java
index 7c277f8..7bec2db 100644
--- a/guava/src/com/google/common/collect/AbstractSortedMultiset.java
+++ b/guava/src/com/google/common/collect/AbstractSortedMultiset.java
@@ -17,6 +17,7 @@ package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.Comparator;
import java.util.Iterator;
@@ -99,8 +100,11 @@ abstract class AbstractSortedMultiset<E> extends AbstractMultiset<E> implements
}
@Override
- public SortedMultiset<E> subMultiset(@Nullable E fromElement, BoundType fromBoundType,
- @Nullable E toElement, BoundType toBoundType) {
+ public SortedMultiset<E> subMultiset(
+ @Nullable E fromElement,
+ BoundType fromBoundType,
+ @Nullable E toElement,
+ BoundType toBoundType) {
// These are checked elsewhere, but NullPointerTester wants them checked eagerly.
checkNotNull(fromBoundType);
checkNotNull(toBoundType);
@@ -122,7 +126,8 @@ abstract class AbstractSortedMultiset<E> extends AbstractMultiset<E> implements
}
SortedMultiset<E> createDescendingMultiset() {
- return new DescendingMultiset<E>() {
+ @WeakOuter
+ class DescendingMultisetImpl extends DescendingMultiset<E> {
@Override
SortedMultiset<E> forwardMultiset() {
return AbstractSortedMultiset.this;
@@ -137,6 +142,7 @@ abstract class AbstractSortedMultiset<E> extends AbstractMultiset<E> implements
public Iterator<E> iterator() {
return descendingIterator();
}
- };
+ }
+ return new DescendingMultisetImpl();
}
}
diff --git a/guava/src/com/google/common/collect/AbstractSortedSetMultimap.java b/guava/src/com/google/common/collect/AbstractSortedSetMultimap.java
index ac74155..9826c5f 100644
--- a/guava/src/com/google/common/collect/AbstractSortedSetMultimap.java
+++ b/guava/src/com/google/common/collect/AbstractSortedSetMultimap.java
@@ -35,8 +35,8 @@ import javax.annotation.Nullable;
* @author Jared Levy
*/
@GwtCompatible
-abstract class AbstractSortedSetMultimap<K, V>
- extends AbstractSetMultimap<K, V> implements SortedSetMultimap<K, V> {
+abstract class AbstractSortedSetMultimap<K, V> extends AbstractSetMultimap<K, V>
+ implements SortedSetMultimap<K, V> {
/**
* Creates a new multimap that uses the provided map.
*
@@ -74,7 +74,8 @@ abstract class AbstractSortedSetMultimap<K, V>
* key, this method returns a {@link SortedSet}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
- @Override public SortedSet<V> get(@Nullable K key) {
+ @Override
+ public SortedSet<V> get(@Nullable K key) {
return (SortedSet<V>) super.get(key);
}
@@ -86,7 +87,8 @@ abstract class AbstractSortedSetMultimap<K, V>
* key, this method returns a {@link SortedSet}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
- @Override public SortedSet<V> removeAll(@Nullable Object key) {
+ @Override
+ public SortedSet<V> removeAll(@Nullable Object key) {
return (SortedSet<V>) super.removeAll(key);
}
@@ -100,8 +102,8 @@ abstract class AbstractSortedSetMultimap<K, V>
*
* <p>Any duplicates in {@code values} will be stored in the multimap once.
*/
- @Override public SortedSet<V> replaceValues(
- @Nullable K key, Iterable<? extends V> values) {
+ @Override
+ public SortedSet<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
return (SortedSet<V>) super.replaceValues(key, values);
}
@@ -119,7 +121,8 @@ abstract class AbstractSortedSetMultimap<K, V>
* <p>Though the method signature doesn't say so explicitly, the returned map
* has {@link SortedSet} values.
*/
- @Override public Map<K, Collection<V>> asMap() {
+ @Override
+ public Map<K, Collection<V>> asMap() {
return super.asMap();
}
@@ -129,7 +132,8 @@ abstract class AbstractSortedSetMultimap<K, V>
* Consequently, the values do not follow their natural ordering or the
* ordering of the value comparator.
*/
- @Override public Collection<V> values() {
+ @Override
+ public Collection<V> values() {
return super.values();
}
diff --git a/guava/src/com/google/common/collect/AbstractTable.java b/guava/src/com/google/common/collect/AbstractTable.java
index fc979e9..6a68f4c 100644
--- a/guava/src/com/google/common/collect/AbstractTable.java
+++ b/guava/src/com/google/common/collect/AbstractTable.java
@@ -15,6 +15,7 @@
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.AbstractCollection;
import java.util.AbstractSet;
@@ -27,7 +28,7 @@ import javax.annotation.Nullable;
/**
* Skeletal, implementation-agnostic implementation of the {@link Table} interface.
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible
@@ -117,14 +118,16 @@ abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
abstract Iterator<Table.Cell<R, C, V>> cellIterator();
+ @WeakOuter
class CellSet extends AbstractSet<Cell<R, C, V>> {
@Override
public boolean contains(Object o) {
if (o instanceof Cell) {
Cell<?, ?, ?> cell = (Cell<?, ?, ?>) o;
Map<C, V> row = Maps.safeGet(rowMap(), cell.getRowKey());
- return row != null && Collections2.safeContains(
- row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
+ return row != null
+ && Collections2.safeContains(
+ row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
}
return false;
}
@@ -134,8 +137,9 @@ abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
if (o instanceof Cell) {
Cell<?, ?, ?> cell = (Cell<?, ?, ?>) o;
Map<C, V> row = Maps.safeGet(rowMap(), cell.getRowKey());
- return row != null && Collections2.safeRemove(
- row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
+ return row != null
+ && Collections2.safeRemove(
+ row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
}
return false;
}
@@ -163,11 +167,11 @@ abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
Collection<V> result = values;
return (result == null) ? values = createValues() : result;
}
-
+
Collection<V> createValues() {
return new Values();
}
-
+
Iterator<V> valuesIterator() {
return new TransformedIterator<Cell<R, C, V>, V>(cellSet().iterator()) {
@Override
@@ -177,6 +181,7 @@ abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
};
}
+ @WeakOuter
class Values extends AbstractCollection<V> {
@Override
public Iterator<V> iterator() {
@@ -199,18 +204,21 @@ abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
}
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
return Tables.equalsImpl(this, obj);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return cellSet().hashCode();
}
/**
* Returns the string representation {@code rowMap().toString()}.
*/
- @Override public String toString() {
+ @Override
+ public String toString() {
return rowMap().toString();
}
}
diff --git a/guava/src/com/google/common/collect/ArrayListMultimap.java b/guava/src/com/google/common/collect/ArrayListMultimap.java
index 1929ea7..33147ab 100644
--- a/guava/src/com/google/common/collect/ArrayListMultimap.java
+++ b/guava/src/com/google/common/collect/ArrayListMultimap.java
@@ -55,13 +55,13 @@ import java.util.Map;
* multimap. Concurrent read operations will work correctly. To allow concurrent
* update operations, wrap your multimap with a call to {@link
* Multimaps#synchronizedListMultimap}.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
* {@code Multimap}</a>.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
@@ -87,8 +87,7 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
* @throws IllegalArgumentException if {@code expectedKeys} or {@code
* expectedValuesPerKey} is negative
*/
- public static <K, V> ArrayListMultimap<K, V> create(
- int expectedKeys, int expectedValuesPerKey) {
+ public static <K, V> ArrayListMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
return new ArrayListMultimap<K, V>(expectedKeys, expectedValuesPerKey);
}
@@ -98,8 +97,7 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
*
* @param multimap the multimap whose contents are copied to this multimap
*/
- public static <K, V> ArrayListMultimap<K, V> create(
- Multimap<? extends K, ? extends V> multimap) {
+ public static <K, V> ArrayListMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
return new ArrayListMultimap<K, V>(multimap);
}
@@ -115,10 +113,11 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
}
private ArrayListMultimap(Multimap<? extends K, ? extends V> multimap) {
- this(multimap.keySet().size(),
- (multimap instanceof ArrayListMultimap) ?
- ((ArrayListMultimap<?, ?>) multimap).expectedValuesPerKey :
- DEFAULT_VALUES_PER_KEY);
+ this(
+ multimap.keySet().size(),
+ (multimap instanceof ArrayListMultimap)
+ ? ((ArrayListMultimap<?, ?>) multimap).expectedValuesPerKey
+ : DEFAULT_VALUES_PER_KEY);
putAll(multimap);
}
@@ -126,7 +125,8 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
* Creates a new, empty {@code ArrayList} to hold the collection of values for
* an arbitrary key.
*/
- @Override List<V> createCollection() {
+ @Override
+ List<V> createCollection() {
return new ArrayList<V>(expectedValuesPerKey);
}
@@ -148,17 +148,15 @@ public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
- stream.writeInt(expectedValuesPerKey);
Serialization.writeMultimap(this, stream);
}
@GwtIncompatible("java.io.ObjectOutputStream")
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
- expectedValuesPerKey = stream.readInt();
+ expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
int distinctKeys = Serialization.readCount(stream);
- Map<K, Collection<V>> map = Maps.newHashMapWithExpectedSize(distinctKeys);
+ Map<K, Collection<V>> map = Maps.newHashMap();
setMap(map);
Serialization.populateMultimap(this, stream, distinctKeys);
}
diff --git a/guava/src/com/google/common/collect/ArrayTable.java b/guava/src/com/google/common/collect/ArrayTable.java
index 48ff8e9..c1a9348 100644
--- a/guava/src/com/google/common/collect/ArrayTable.java
+++ b/guava/src/com/google/common/collect/ArrayTable.java
@@ -24,14 +24,16 @@ import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Objects;
+import com.google.common.collect.Maps.IteratorBasedAbstractMap;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
@@ -75,7 +77,7 @@ import javax.annotation.Nullable;
* to one cell and a thread that reads from another.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#table">
* {@code Table}</a>.
*
* @author Jared Levy
@@ -129,8 +131,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
*/
public static <R, C, V> ArrayTable<R, C, V> create(Table<R, C, V> table) {
return (table instanceof ArrayTable<?, ?, ?>)
- ? new ArrayTable<R, C, V>((ArrayTable<R, C, V>) table)
- : new ArrayTable<R, C, V>(table);
+ ? new ArrayTable<R, C, V>((ArrayTable<R, C, V>) table)
+ : new ArrayTable<R, C, V>(table);
}
private final ImmutableList<R> rowList;
@@ -141,8 +143,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
private final ImmutableMap<C, Integer> columnKeyToIndex;
private final V[][] array;
- private ArrayTable(Iterable<? extends R> rowKeys,
- Iterable<? extends C> columnKeys) {
+ private ArrayTable(Iterable<? extends R> rowKeys, Iterable<? extends C> columnKeys) {
this.rowList = ImmutableList.copyOf(rowKeys);
this.columnList = ImmutableList.copyOf(columnKeys);
checkArgument(!rowList.isEmpty());
@@ -153,25 +154,16 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
* columnKeys is empty but rowKeys isn't, the table is empty but
* containsRow() can return true and rowKeySet() isn't empty.
*/
- rowKeyToIndex = index(rowList);
- columnKeyToIndex = index(columnList);
+ rowKeyToIndex = Maps.indexMap(rowList);
+ columnKeyToIndex = Maps.indexMap(columnList);
@SuppressWarnings("unchecked")
- V[][] tmpArray
- = (V[][]) new Object[rowList.size()][columnList.size()];
+ V[][] tmpArray = (V[][]) new Object[rowList.size()][columnList.size()];
array = tmpArray;
// Necessary because in GWT the arrays are initialized with "undefined" instead of null.
eraseAll();
}
- private static <E> ImmutableMap<E, Integer> index(List<E> list) {
- ImmutableMap.Builder<E, Integer> columnBuilder = ImmutableMap.builder();
- for (int i = 0; i < list.size(); i++) {
- columnBuilder.put(list.get(i), i);
- }
- return columnBuilder.build();
- }
-
private ArrayTable(Table<R, C, V> table) {
this(table.rowKeySet(), table.columnKeySet());
putAll(table);
@@ -192,7 +184,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
}
}
- private abstract static class ArrayMap<K, V> extends Maps.ImprovedAbstractMap<K, V> {
+ private abstract static class ArrayMap<K, V> extends IteratorBasedAbstractMap<K, V> {
private final ImmutableMap<K, Integer> keyIndex;
private ArrayMap(ImmutableMap<K, Integer> keyIndex) {
@@ -210,9 +202,11 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
abstract String getKeyRole();
- @Nullable abstract V getValue(int index);
+ @Nullable
+ abstract V getValue(int index);
- @Nullable abstract V setValue(int index, V newValue);
+ @Nullable
+ abstract V setValue(int index, V newValue);
@Override
public int size() {
@@ -225,41 +219,31 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
}
@Override
- protected Set<Entry<K, V>> createEntrySet() {
- return new Maps.EntrySet<K, V>() {
+ Iterator<Entry<K, V>> entryIterator() {
+ return new AbstractIndexedListIterator<Entry<K, V>>(size()) {
@Override
- Map<K, V> map() {
- return ArrayMap.this;
- }
+ protected Entry<K, V> get(final int index) {
+ return new AbstractMapEntry<K, V>() {
+ @Override
+ public K getKey() {
+ return ArrayMap.this.getKey(index);
+ }
- @Override
- public Iterator<Entry<K, V>> iterator() {
- return new AbstractIndexedListIterator<Entry<K, V>>(size()) {
@Override
- protected Entry<K, V> get(final int index) {
- return new AbstractMapEntry<K, V>() {
- @Override
- public K getKey() {
- return ArrayMap.this.getKey(index);
- }
-
- @Override
- public V getValue() {
- return ArrayMap.this.getValue(index);
- }
-
- @Override
- public V setValue(V value) {
- return ArrayMap.this.setValue(index, value);
- }
- };
+ public V getValue() {
+ return ArrayMap.this.getValue(index);
+ }
+
+ @Override
+ public V setValue(V value) {
+ return ArrayMap.this.setValue(index, value);
}
};
}
};
}
- // TODO(user): consider an optimized values() implementation
+ // TODO(lowasser): consider an optimized values() implementation
@Override
public boolean containsKey(@Nullable Object key) {
@@ -372,8 +356,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
public V[][] toArray(Class<V> valueClass) {
// Can change to use varargs in JDK 1.6 if we want
@SuppressWarnings("unchecked") // TODO: safe?
- V[][] copy = (V[][]) Array.newInstance(
- valueClass, new int[] { rowList.size(), columnList.size() });
+ V[][] copy =
+ (V[][]) Array.newInstance(valueClass, new int[] {rowList.size(), columnList.size()});
for (int i = 0; i < rowList.size(); i++) {
System.arraycopy(array[i], 0, copy[i], 0, array[i].length);
}
@@ -387,7 +371,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
* @deprecated Use {@link #eraseAll}
*/
@Override
- @Deprecated public void clear() {
+ @Deprecated
+ public void clear() {
throw new UnsupportedOperationException();
}
@@ -444,8 +429,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
Integer rowIndex = rowKeyToIndex.get(rowKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
- return (rowIndex == null || columnIndex == null)
- ? null : at(rowIndex, columnIndex);
+ return (rowIndex == null || columnIndex == null) ? null : at(rowIndex, columnIndex);
}
/**
@@ -469,8 +453,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
Integer rowIndex = rowKeyToIndex.get(rowKey);
checkArgument(rowIndex != null, "Row %s not in %s", rowKey, rowList);
Integer columnIndex = columnKeyToIndex.get(columnKey);
- checkArgument(columnIndex != null,
- "Column %s not in %s", columnKey, columnList);
+ checkArgument(columnIndex != null, "Column %s not in %s", columnKey, columnList);
return set(rowIndex, columnIndex, value);
}
@@ -502,7 +485,8 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
* @deprecated Use {@link #erase}
*/
@Override
- @Deprecated public V remove(Object rowKey, Object columnKey) {
+ @Deprecated
+ public V remove(Object rowKey, Object columnKey) {
throw new UnsupportedOperationException();
}
@@ -556,18 +540,22 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
@Override
Iterator<Cell<R, C, V>> cellIterator() {
return new AbstractIndexedListIterator<Cell<R, C, V>>(size()) {
- @Override protected Cell<R, C, V> get(final int index) {
+ @Override
+ protected Cell<R, C, V> get(final int index) {
return new Tables.AbstractCell<R, C, V>() {
final int rowIndex = index / columnList.size();
final int columnIndex = index % columnList.size();
+
@Override
public R getRowKey() {
return rowList.get(rowIndex);
}
+
@Override
public C getColumnKey() {
return columnList.get(columnIndex);
}
+
@Override
public V getValue() {
return at(rowIndex, columnIndex);
@@ -593,8 +581,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
public Map<R, V> column(C columnKey) {
checkNotNull(columnKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
- return (columnIndex == null)
- ? ImmutableMap.<R, V>of() : new Column(columnIndex);
+ return (columnIndex == null) ? ImmutableMap.<R, V>of() : new Column(columnIndex);
}
private class Column extends ArrayMap<R, V> {
@@ -640,6 +627,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
return (map == null) ? columnMap = new ColumnMap() : map;
}
+ @WeakOuter
private class ColumnMap extends ArrayMap<C, Map<R, V>> {
private ColumnMap() {
super(columnKeyToIndex);
@@ -729,6 +717,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements
return (map == null) ? rowMap = new RowMap() : map;
}
+ @WeakOuter
private class RowMap extends ArrayMap<R, Map<C, V>> {
private RowMap() {
super(rowKeyToIndex);
diff --git a/guava/src/com/google/common/collect/BiMap.java b/guava/src/com/google/common/collect/BiMap.java
index a6203e0..e8ddf9d 100644
--- a/guava/src/com/google/common/collect/BiMap.java
+++ b/guava/src/com/google/common/collect/BiMap.java
@@ -28,13 +28,13 @@ import javax.annotation.Nullable;
* its values as well as that of its keys. This constraint enables bimaps to
* support an "inverse view", which is another bimap containing the same entries
* as this bimap but with reversed keys and values.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap">
* {@code BiMap}</a>.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public interface BiMap<K, V> extends Map<K, V> {
@@ -48,6 +48,7 @@ public interface BiMap<K, V> extends Map<K, V> {
* event. To avoid this exception, call {@link #forcePut} instead.
*/
@Override
+ @Nullable
V put(@Nullable K key, @Nullable V value);
/**
@@ -67,6 +68,7 @@ public interface BiMap<K, V> extends Map<K, V> {
* @return the value which was previously associated with the key, which may
* be {@code null}, or {@code null} if there was no previous entry
*/
+ @Nullable
V forcePut(@Nullable K key, @Nullable V value);
// Bulk Operations
diff --git a/guava/src/com/google/common/collect/BinaryTreeTraverser.java b/guava/src/com/google/common/collect/BinaryTreeTraverser.java
index d86d6a4..9eca1a8 100644
--- a/guava/src/com/google/common/collect/BinaryTreeTraverser.java
+++ b/guava/src/com/google/common/collect/BinaryTreeTraverser.java
@@ -37,7 +37,7 @@ import java.util.Iterator;
@Beta
@GwtCompatible(emulated = true)
public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> {
- // TODO(user): make this GWT-compatible when we've checked in ArrayDeque and BitSet emulation
+ // TODO(lowasser): make this GWT-compatible when we've checked in ArrayDeque and BitSet emulation
/**
* Returns the left child of the specified node, or {@link Optional#absent()} if the specified
@@ -164,7 +164,7 @@ public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> {
}
}
- // TODO(user): see if any significant optimizations are possible for breadthFirstIterator
+ // TODO(lowasser): see if any significant optimizations are possible for breadthFirstIterator
public final FluentIterable<T> inOrderTraversal(final T root) {
checkNotNull(root);
diff --git a/guava/src/com/google/common/collect/ByFunctionOrdering.java b/guava/src/com/google/common/collect/ByFunctionOrdering.java
index c148ba9..82d84e1 100644
--- a/guava/src/com/google/common/collect/ByFunctionOrdering.java
+++ b/guava/src/com/google/common/collect/ByFunctionOrdering.java
@@ -31,38 +31,39 @@ import javax.annotation.Nullable;
* function on those elements.
*/
@GwtCompatible(serializable = true)
-final class ByFunctionOrdering<F, T>
- extends Ordering<F> implements Serializable {
+final class ByFunctionOrdering<F, T> extends Ordering<F> implements Serializable {
final Function<F, ? extends T> function;
final Ordering<T> ordering;
- ByFunctionOrdering(
- Function<F, ? extends T> function, Ordering<T> ordering) {
+ ByFunctionOrdering(Function<F, ? extends T> function, Ordering<T> ordering) {
this.function = checkNotNull(function);
this.ordering = checkNotNull(ordering);
}
- @Override public int compare(F left, F right) {
+ @Override
+ public int compare(F left, F right) {
return ordering.compare(function.apply(left), function.apply(right));
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
if (object instanceof ByFunctionOrdering) {
ByFunctionOrdering<?, ?> that = (ByFunctionOrdering<?, ?>) object;
- return this.function.equals(that.function)
- && this.ordering.equals(that.ordering);
+ return this.function.equals(that.function) && this.ordering.equals(that.ordering);
}
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Objects.hashCode(function, ordering);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return ordering + ".onResultOf(" + function + ")";
}
diff --git a/guava/src/com/google/common/collect/CartesianList.java b/guava/src/com/google/common/collect/CartesianList.java
index 0e50740..e27de14 100644
--- a/guava/src/com/google/common/collect/CartesianList.java
+++ b/guava/src/com/google/common/collect/CartesianList.java
@@ -28,7 +28,7 @@ import javax.annotation.Nullable;
/**
* Implementation of {@link Lists#cartesianProduct(List)}.
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible
@@ -36,10 +36,9 @@ final class CartesianList<E> extends AbstractList<List<E>> implements RandomAcce
private transient final ImmutableList<List<E>> axes;
private transient final int[] axesSizeProduct;
-
+
static <E> List<List<E>> create(List<? extends List<? extends E>> lists) {
- ImmutableList.Builder<List<E>> axesBuilder =
- new ImmutableList.Builder<List<E>>(lists.size());
+ ImmutableList.Builder<List<E>> axesBuilder = new ImmutableList.Builder<List<E>>(lists.size());
for (List<? extends E> list : lists) {
List<E> copy = ImmutableList.copyOf(list);
if (copy.isEmpty()) {
@@ -56,8 +55,7 @@ final class CartesianList<E> extends AbstractList<List<E>> implements RandomAcce
axesSizeProduct[axes.size()] = 1;
try {
for (int i = axes.size() - 1; i >= 0; i--) {
- axesSizeProduct[i] =
- IntMath.checkedMultiply(axesSizeProduct[i + 1], axes.get(i).size());
+ axesSizeProduct[i] = IntMath.checkedMultiply(axesSizeProduct[i + 1], axes.get(i).size());
}
} catch (ArithmeticException e) {
throw new IllegalArgumentException(
diff --git a/guava/src/com/google/common/collect/ClassToInstanceMap.java b/guava/src/com/google/common/collect/ClassToInstanceMap.java
index b3f535c..8c39210 100644
--- a/guava/src/com/google/common/collect/ClassToInstanceMap.java
+++ b/guava/src/com/google/common/collect/ClassToInstanceMap.java
@@ -31,9 +31,9 @@ import javax.annotation.Nullable;
* <p>Like any other {@code Map<Class, Object>}, this map may contain entries
* for primitive types, and a primitive type and its corresponding wrapper type
* may map to different values.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#ClassToInstanceMap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#classtoinstancemap">
* {@code ClassToInstanceMap}</a>.
*
* <p>To map a generic type to an instance of that type, use {@link
@@ -43,7 +43,7 @@ import javax.annotation.Nullable;
* simply {@link Object}
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public interface ClassToInstanceMap<B> extends Map<Class<? extends B>, B> {
diff --git a/guava/src/com/google/common/collect/CollectPreconditions.java b/guava/src/com/google/common/collect/CollectPreconditions.java
index e3e1cbe..f19f475 100644
--- a/guava/src/com/google/common/collect/CollectPreconditions.java
+++ b/guava/src/com/google/common/collect/CollectPreconditions.java
@@ -41,6 +41,12 @@ final class CollectPreconditions {
return value;
}
+ static void checkPositive(int value, String name) {
+ if (value <= 0) {
+ throw new IllegalArgumentException(name + " must be positive but was: " + value);
+ }
+ }
+
/**
* Precondition tester for {@code Iterator.remove()} that throws an exception with a consistent
* error message.
diff --git a/guava/src/com/google/common/collect/Collections2.java b/guava/src/com/google/common/collect/Collections2.java
index a0c46b1..ae8ae77 100644
--- a/guava/src/com/google/common/collect/Collections2.java
+++ b/guava/src/com/google/common/collect/Collections2.java
@@ -42,6 +42,7 @@ import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -50,8 +51,9 @@ import javax.annotation.Nullable;
* @author Chris Povirk
* @author Mike Bostock
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
+ at CheckReturnValue
@GwtCompatible
public final class Collections2 {
private Collections2() {}
@@ -86,16 +88,15 @@ public final class Collections2 {
*/
// TODO(kevinb): how can we omit that Iterables link when building gwt
// javadoc?
- public static <E> Collection<E> filter(
- Collection<E> unfiltered, Predicate<? super E> predicate) {
+ @CheckReturnValue
+ public static <E> Collection<E> filter(Collection<E> unfiltered, Predicate<? super E> predicate) {
if (unfiltered instanceof FilteredCollection) {
// Support clear(), removeAll(), and retainAll() when filtering a filtered
// collection.
return ((FilteredCollection<E>) unfiltered).createCombined(predicate);
}
- return new FilteredCollection<E>(
- checkNotNull(unfiltered), checkNotNull(predicate));
+ return new FilteredCollection<E>(checkNotNull(unfiltered), checkNotNull(predicate));
}
/**
@@ -103,8 +104,7 @@ public final class Collections2 {
* {@code contains} method throws a {@code ClassCastException} or
* {@code NullPointerException}.
*/
- static boolean safeContains(
- Collection<?> collection, @Nullable Object object) {
+ static boolean safeContains(Collection<?> collection, @Nullable Object object) {
checkNotNull(collection);
try {
return collection.contains(object);
@@ -135,15 +135,13 @@ public final class Collections2 {
final Collection<E> unfiltered;
final Predicate<? super E> predicate;
- FilteredCollection(Collection<E> unfiltered,
- Predicate<? super E> predicate) {
+ FilteredCollection(Collection<E> unfiltered, Predicate<? super E> predicate) {
this.unfiltered = unfiltered;
this.predicate = predicate;
}
FilteredCollection<E> createCombined(Predicate<? super E> newPredicate) {
- return new FilteredCollection<E>(unfiltered,
- Predicates.<E>and(predicate, newPredicate));
+ return new FilteredCollection<E>(unfiltered, Predicates.<E>and(predicate, newPredicate));
// .<E> above needed to compile in JDK 5
}
@@ -198,12 +196,12 @@ public final class Collections2 {
@Override
public boolean removeAll(final Collection<?> collection) {
- return Iterables.removeIf(unfiltered, and(predicate, in(collection)));
+ return Iterables.removeIf(unfiltered, and(predicate, Predicates.<Object>in(collection)));
}
@Override
public boolean retainAll(final Collection<?> collection) {
- return Iterables.removeIf(unfiltered, and(predicate, not(in(collection))));
+ return Iterables.removeIf(unfiltered, and(predicate, not(Predicates.<Object>in(collection))));
}
@Override
@@ -242,8 +240,8 @@ public final class Collections2 {
* {@link Lists#transform}. If only an {@code Iterable} is available, use
* {@link Iterables#transform}.
*/
- public static <F, T> Collection<T> transform(Collection<F> fromCollection,
- Function<? super F, T> function) {
+ public static <F, T> Collection<T> transform(
+ Collection<F> fromCollection, Function<? super F, T> function) {
return new TransformedCollection<F, T>(fromCollection, function);
}
@@ -251,25 +249,28 @@ public final class Collections2 {
final Collection<F> fromCollection;
final Function<? super F, ? extends T> function;
- TransformedCollection(Collection<F> fromCollection,
- Function<? super F, ? extends T> function) {
+ TransformedCollection(Collection<F> fromCollection, Function<? super F, ? extends T> function) {
this.fromCollection = checkNotNull(fromCollection);
this.function = checkNotNull(function);
}
- @Override public void clear() {
+ @Override
+ public void clear() {
fromCollection.clear();
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return fromCollection.isEmpty();
}
- @Override public Iterator<T> iterator() {
+ @Override
+ public Iterator<T> iterator() {
return Iterators.transform(fromCollection.iterator(), function);
}
- @Override public int size() {
+ @Override
+ public int size() {
return fromCollection.size();
}
}
@@ -294,14 +295,17 @@ public final class Collections2 {
* An implementation of {@link Collection#toString()}.
*/
static String toStringImpl(final Collection<?> collection) {
- StringBuilder sb
- = newStringBuilderForCollection(collection.size()).append('[');
+ StringBuilder sb = newStringBuilderForCollection(collection.size()).append('[');
STANDARD_JOINER.appendTo(
- sb, Iterables.transform(collection, new Function<Object, Object>() {
- @Override public Object apply(Object input) {
- return input == collection ? "(this Collection)" : input;
- }
- }));
+ sb,
+ Iterables.transform(
+ collection,
+ new Function<Object, Object>() {
+ @Override
+ public Object apply(Object input) {
+ return input == collection ? "(this Collection)" : input;
+ }
+ }));
return sb.append(']').toString();
}
@@ -349,8 +353,9 @@ public final class Collections2 {
* null elements.
* @since 12.0
*/
- @Beta public static <E extends Comparable<? super E>>
- Collection<List<E>> orderedPermutations(Iterable<E> elements) {
+ @Beta
+ public static <E extends Comparable<? super E>> Collection<List<E>> orderedPermutations(
+ Iterable<E> elements) {
return orderedPermutations(elements, Ordering.natural());
}
@@ -401,19 +406,18 @@ public final class Collections2 {
* null elements, or if the specified comparator is null.
* @since 12.0
*/
- @Beta public static <E> Collection<List<E>> orderedPermutations(
+ @Beta
+ public static <E> Collection<List<E>> orderedPermutations(
Iterable<E> elements, Comparator<? super E> comparator) {
return new OrderedPermutationCollection<E>(elements, comparator);
}
- private static final class OrderedPermutationCollection<E>
- extends AbstractCollection<List<E>> {
+ private static final class OrderedPermutationCollection<E> extends AbstractCollection<List<E>> {
final ImmutableList<E> inputList;
final Comparator<? super E> comparator;
final int size;
- OrderedPermutationCollection(Iterable<E> input,
- Comparator<? super E> comparator) {
+ OrderedPermutationCollection(Iterable<E> input, Comparator<? super E> comparator) {
this.inputList = Ordering.from(comparator).immutableSortedCopy(input);
this.comparator = comparator;
this.size = calculateSize(inputList, comparator);
@@ -434,8 +438,7 @@ public final class Collections2 {
int n = 1;
int r = 1;
while (n < sortedInputList.size()) {
- int comparison = comparator.compare(
- sortedInputList.get(n - 1), sortedInputList.get(n));
+ int comparison = comparator.compare(sortedInputList.get(n - 1), sortedInputList.get(n));
if (comparison < 0) {
// We move to the next non-repeated element.
permutations *= binomial(n, r);
@@ -454,19 +457,23 @@ public final class Collections2 {
return (int) permutations;
}
- @Override public int size() {
+ @Override
+ public int size() {
return size;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Iterator<List<E>> iterator() {
+ @Override
+ public Iterator<List<E>> iterator() {
return new OrderedPermutationIterator<E>(inputList, comparator);
}
- @Override public boolean contains(@Nullable Object obj) {
+ @Override
+ public boolean contains(@Nullable Object obj) {
if (obj instanceof List) {
List<?> list = (List<?>) obj;
return isPermutation(inputList, list);
@@ -474,24 +481,24 @@ public final class Collections2 {
return false;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "orderedPermutationCollection(" + inputList + ")";
}
}
- private static final class OrderedPermutationIterator<E>
- extends AbstractIterator<List<E>> {
+ private static final class OrderedPermutationIterator<E> extends AbstractIterator<List<E>> {
List<E> nextPermutation;
final Comparator<? super E> comparator;
- OrderedPermutationIterator(List<E> list,
- Comparator<? super E> comparator) {
+ OrderedPermutationIterator(List<E> list, Comparator<? super E> comparator) {
this.nextPermutation = Lists.newArrayList(list);
this.comparator = comparator;
}
- @Override protected List<E> computeNext() {
+ @Override
+ protected List<E> computeNext() {
if (nextPermutation == null) {
return endOfData();
}
@@ -515,8 +522,7 @@ public final class Collections2 {
int findNextJ() {
for (int k = nextPermutation.size() - 2; k >= 0; k--) {
- if (comparator.compare(nextPermutation.get(k),
- nextPermutation.get(k + 1)) < 0) {
+ if (comparator.compare(nextPermutation.get(k), nextPermutation.get(k + 1)) < 0) {
return k;
}
}
@@ -554,32 +560,35 @@ public final class Collections2 {
* null elements.
* @since 12.0
*/
- @Beta public static <E> Collection<List<E>> permutations(
- Collection<E> elements) {
+ @Beta
+ public static <E> Collection<List<E>> permutations(Collection<E> elements) {
return new PermutationCollection<E>(ImmutableList.copyOf(elements));
}
- private static final class PermutationCollection<E>
- extends AbstractCollection<List<E>> {
+ private static final class PermutationCollection<E> extends AbstractCollection<List<E>> {
final ImmutableList<E> inputList;
PermutationCollection(ImmutableList<E> input) {
this.inputList = input;
}
- @Override public int size() {
+ @Override
+ public int size() {
return IntMath.factorial(inputList.size());
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Iterator<List<E>> iterator() {
+ @Override
+ public Iterator<List<E>> iterator() {
return new PermutationIterator<E>(inputList);
}
- @Override public boolean contains(@Nullable Object obj) {
+ @Override
+ public boolean contains(@Nullable Object obj) {
if (obj instanceof List) {
List<?> list = (List<?>) obj;
return isPermutation(inputList, list);
@@ -587,13 +596,13 @@ public final class Collections2 {
return false;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "permutations(" + inputList + ")";
}
}
- private static class PermutationIterator<E>
- extends AbstractIterator<List<E>> {
+ private static class PermutationIterator<E> extends AbstractIterator<List<E>> {
final List<E> list;
final int[] c;
final int[] o;
@@ -609,7 +618,8 @@ public final class Collections2 {
j = Integer.MAX_VALUE;
}
- @Override protected List<E> computeNext() {
+ @Override
+ protected List<E> computeNext() {
if (j <= 0) {
return endOfData();
}
@@ -658,8 +668,7 @@ public final class Collections2 {
/**
* Returns {@code true} if the second list is a permutation of the first.
*/
- private static boolean isPermutation(List<?> first,
- List<?> second) {
+ private static boolean isPermutation(List<?> first, List<?> second) {
if (first.size() != second.size()) {
return false;
}
diff --git a/guava/src/com/google/common/collect/ComparatorOrdering.java b/guava/src/com/google/common/collect/ComparatorOrdering.java
index 5b518af..eec5246 100644
--- a/guava/src/com/google/common/collect/ComparatorOrdering.java
+++ b/guava/src/com/google/common/collect/ComparatorOrdering.java
@@ -34,11 +34,13 @@ final class ComparatorOrdering<T> extends Ordering<T> implements Serializable {
this.comparator = checkNotNull(comparator);
}
- @Override public int compare(T a, T b) {
+ @Override
+ public int compare(T a, T b) {
return comparator.compare(a, b);
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -49,11 +51,13 @@ final class ComparatorOrdering<T> extends Ordering<T> implements Serializable {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return comparator.hashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return comparator.toString();
}
diff --git a/guava/src/com/google/common/collect/ComparisonChain.java b/guava/src/com/google/common/collect/ComparisonChain.java
index c228c8a..43bbc9e 100644
--- a/guava/src/com/google/common/collect/ComparisonChain.java
+++ b/guava/src/com/google/common/collect/ComparisonChain.java
@@ -23,6 +23,7 @@ import com.google.common.primitives.Longs;
import java.util.Comparator;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -41,6 +42,9 @@ import javax.annotation.Nullable;
* nonzero</i> comparison result in the chain, or will be zero if every
* comparison result was zero.
*
+ * <p><b>Note:</b> {@code ComparisonChain} instances are <b>immutable</b>. For
+ * this utility to work correctly, calls must be chained as illustrated above.
+ *
* <p>Performance note: Even though the {@code ComparisonChain} caller always
* invokes its {@code compare} methods unconditionally, the {@code
* ComparisonChain} implementation stops calling its inputs' {@link
@@ -50,13 +54,14 @@ import javax.annotation.Nullable;
* {@code compare} implementations.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained#compare/compareTo">
+ * "https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained#comparecompareto">
* {@code ComparisonChain}</a>.
*
* @author Mark Davis
* @author Kevin Bourrillion
* @since 2.0
*/
+ at CheckReturnValue
@GwtCompatible
public abstract class ComparisonChain {
private ComparisonChain() {}
@@ -69,41 +74,59 @@ public abstract class ComparisonChain {
return ACTIVE;
}
- private static final ComparisonChain ACTIVE = new ComparisonChain() {
- @SuppressWarnings("unchecked")
- @Override public ComparisonChain compare(
- Comparable left, Comparable right) {
- return classify(left.compareTo(right));
- }
- @Override public <T> ComparisonChain compare(
- @Nullable T left, @Nullable T right, Comparator<T> comparator) {
- return classify(comparator.compare(left, right));
- }
- @Override public ComparisonChain compare(int left, int right) {
- return classify(Ints.compare(left, right));
- }
- @Override public ComparisonChain compare(long left, long right) {
- return classify(Longs.compare(left, right));
- }
- @Override public ComparisonChain compare(float left, float right) {
- return classify(Float.compare(left, right));
- }
- @Override public ComparisonChain compare(double left, double right) {
- return classify(Double.compare(left, right));
- }
- @Override public ComparisonChain compareTrueFirst(boolean left, boolean right) {
- return classify(Booleans.compare(right, left)); // reversed
- }
- @Override public ComparisonChain compareFalseFirst(boolean left, boolean right) {
- return classify(Booleans.compare(left, right));
- }
- ComparisonChain classify(int result) {
- return (result < 0) ? LESS : (result > 0) ? GREATER : ACTIVE;
- }
- @Override public int result() {
- return 0;
- }
- };
+ private static final ComparisonChain ACTIVE =
+ new ComparisonChain() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public ComparisonChain compare(Comparable left, Comparable right) {
+ return classify(left.compareTo(right));
+ }
+
+ @Override
+ public <T> ComparisonChain compare(
+ @Nullable T left, @Nullable T right, Comparator<T> comparator) {
+ return classify(comparator.compare(left, right));
+ }
+
+ @Override
+ public ComparisonChain compare(int left, int right) {
+ return classify(Ints.compare(left, right));
+ }
+
+ @Override
+ public ComparisonChain compare(long left, long right) {
+ return classify(Longs.compare(left, right));
+ }
+
+ @Override
+ public ComparisonChain compare(float left, float right) {
+ return classify(Float.compare(left, right));
+ }
+
+ @Override
+ public ComparisonChain compare(double left, double right) {
+ return classify(Double.compare(left, right));
+ }
+
+ @Override
+ public ComparisonChain compareTrueFirst(boolean left, boolean right) {
+ return classify(Booleans.compare(right, left)); // reversed
+ }
+
+ @Override
+ public ComparisonChain compareFalseFirst(boolean left, boolean right) {
+ return classify(Booleans.compare(left, right));
+ }
+
+ ComparisonChain classify(int result) {
+ return (result < 0) ? LESS : (result > 0) ? GREATER : ACTIVE;
+ }
+
+ @Override
+ public int result() {
+ return 0;
+ }
+ };
private static final ComparisonChain LESS = new InactiveComparisonChain(-1);
@@ -115,33 +138,50 @@ public abstract class ComparisonChain {
InactiveComparisonChain(int result) {
this.result = result;
}
- @Override public ComparisonChain compare(
- @Nullable Comparable left, @Nullable Comparable right) {
+
+ @Override
+ public ComparisonChain compare(@Nullable Comparable left, @Nullable Comparable right) {
return this;
}
- @Override public <T> ComparisonChain compare(@Nullable T left,
- @Nullable T right, @Nullable Comparator<T> comparator) {
+
+ @Override
+ public <T> ComparisonChain compare(
+ @Nullable T left, @Nullable T right, @Nullable Comparator<T> comparator) {
return this;
}
- @Override public ComparisonChain compare(int left, int right) {
+
+ @Override
+ public ComparisonChain compare(int left, int right) {
return this;
}
- @Override public ComparisonChain compare(long left, long right) {
+
+ @Override
+ public ComparisonChain compare(long left, long right) {
return this;
}
- @Override public ComparisonChain compare(float left, float right) {
+
+ @Override
+ public ComparisonChain compare(float left, float right) {
return this;
}
- @Override public ComparisonChain compare(double left, double right) {
+
+ @Override
+ public ComparisonChain compare(double left, double right) {
return this;
}
- @Override public ComparisonChain compareTrueFirst(boolean left, boolean right) {
+
+ @Override
+ public ComparisonChain compareTrueFirst(boolean left, boolean right) {
return this;
}
- @Override public ComparisonChain compareFalseFirst(boolean left, boolean right) {
+
+ @Override
+ public ComparisonChain compareFalseFirst(boolean left, boolean right) {
return this;
}
- @Override public int result() {
+
+ @Override
+ public int result() {
return result;
}
}
@@ -151,8 +191,7 @@ public abstract class ComparisonChain {
* Comparable#compareTo}, <i>if</i> the result of this comparison chain
* has not already been determined.
*/
- public abstract ComparisonChain compare(
- Comparable<?> left, Comparable<?> right);
+ public abstract ComparisonChain compare(Comparable<?> left, Comparable<?> right);
/**
* Compares two objects using a comparator, <i>if</i> the result of this
@@ -190,6 +229,19 @@ public abstract class ComparisonChain {
public abstract ComparisonChain compare(double left, double right);
/**
+ * Discouraged synonym for {@link #compareFalseFirst}.
+ *
+ * @deprecated Use {@link #compareFalseFirst}; or, if the parameters passed
+ * are being either negated or reversed, undo the negation or reversal and
+ * use {@link #compareTrueFirst}.
+ * @since 19.0
+ */
+ @Deprecated
+ public final ComparisonChain compare(Boolean left, Boolean right) {
+ return compareFalseFirst(left, right);
+ }
+
+ /**
* Compares two {@code boolean} values, considering {@code true} to be less
* than {@code false}, <i>if</i> the result of this comparison chain has not
* already been determined.
diff --git a/guava/src/com/google/common/collect/CompoundOrdering.java b/guava/src/com/google/common/collect/CompoundOrdering.java
index 26ebf54..385d0a9 100644
--- a/guava/src/com/google/common/collect/CompoundOrdering.java
+++ b/guava/src/com/google/common/collect/CompoundOrdering.java
@@ -26,17 +26,16 @@ import java.util.Comparator;
final class CompoundOrdering<T> extends Ordering<T> implements Serializable {
final ImmutableList<Comparator<? super T>> comparators;
- CompoundOrdering(Comparator<? super T> primary,
- Comparator<? super T> secondary) {
- this.comparators
- = ImmutableList.<Comparator<? super T>>of(primary, secondary);
+ CompoundOrdering(Comparator<? super T> primary, Comparator<? super T> secondary) {
+ this.comparators = ImmutableList.<Comparator<? super T>>of(primary, secondary);
}
CompoundOrdering(Iterable<? extends Comparator<? super T>> comparators) {
this.comparators = ImmutableList.copyOf(comparators);
}
- @Override public int compare(T left, T right) {
+ @Override
+ public int compare(T left, T right) {
// Avoid using the Iterator to avoid generating garbage (issue 979).
int size = comparators.size();
for (int i = 0; i < size; i++) {
@@ -48,7 +47,8 @@ final class CompoundOrdering<T> extends Ordering<T> implements Serializable {
return 0;
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(Object object) {
if (object == this) {
return true;
}
@@ -59,11 +59,13 @@ final class CompoundOrdering<T> extends Ordering<T> implements Serializable {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return comparators.hashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Ordering.compound(" + comparators + ")";
}
diff --git a/guava/src/com/google/common/collect/ComputationException.java b/guava/src/com/google/common/collect/ComputationException.java
index ac80d6a..80b2f5d 100644
--- a/guava/src/com/google/common/collect/ComputationException.java
+++ b/guava/src/com/google/common/collect/ComputationException.java
@@ -24,7 +24,7 @@ import javax.annotation.Nullable;
* Wraps an exception that occurred during a computation.
*
* @author Bob Lee
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public class ComputationException extends RuntimeException {
@@ -34,5 +34,6 @@ public class ComputationException extends RuntimeException {
public ComputationException(@Nullable Throwable cause) {
super(cause);
}
+
private static final long serialVersionUID = 0;
}
diff --git a/guava/src/com/google/common/collect/ComputingConcurrentHashMap.java b/guava/src/com/google/common/collect/ComputingConcurrentHashMap.java
index eb7363a..87d75bb 100644
--- a/guava/src/com/google/common/collect/ComputingConcurrentHashMap.java
+++ b/guava/src/com/google/common/collect/ComputingConcurrentHashMap.java
@@ -46,8 +46,7 @@ class ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
* Creates a new, empty map with the specified strategy, initial capacity, load factor and
* concurrency level.
*/
- ComputingConcurrentHashMap(MapMaker builder,
- Function<? super K, ? extends V> computingFunction) {
+ ComputingConcurrentHashMap(MapMaker builder, Function<? super K, ? extends V> computingFunction) {
super(builder);
this.computingFunction = checkNotNull(computingFunction);
}
@@ -76,7 +75,8 @@ class ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
V getOrCompute(K key, int hash, Function<? super K, ? extends V> computingFunction)
throws ExecutionException {
try {
- outer: while (true) {
+ outer:
+ while (true) {
// don't call getLiveEntry, which would ignore computing values
ReferenceEntry<K, V> e = getEntry(key, hash);
if (e != null) {
@@ -103,7 +103,8 @@ class ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
for (e = first; e != null; e = e.getNext()) {
K entryKey = e.getKey();
- if (e.getHash() == hash && entryKey != null
+ if (e.getHash() == hash
+ && entryKey != null
&& map.keyEquivalence.equivalent(key, entryKey)) {
ValueReference<K, V> valueReference = e.getValueReference();
if (valueReference.isComputingReference()) {
@@ -168,9 +169,11 @@ class ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
}
}
- V compute(K key, int hash, ReferenceEntry<K, V> e,
- ComputingValueReference<K, V> computingValueReference)
- throws ExecutionException {
+ V compute(
+ K key,
+ int hash,
+ ReferenceEntry<K, V> e,
+ ComputingValueReference<K, V> computingValueReference) throws ExecutionException {
V value = null;
long start = System.nanoTime();
long end = 0;
@@ -285,7 +288,7 @@ class ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
private static final class ComputingValueReference<K, V> implements ValueReference<K, V> {
final Function<? super K, ? extends V> computingFunction;
- @GuardedBy("ComputingValueReference.this") // writes
+ @GuardedBy("this") // writes
volatile ValueReference<K, V> computedReference = unset();
public ComputingValueReference(Function<? super K, ? extends V> computingFunction) {
@@ -379,22 +382,47 @@ class ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
@Override
Object writeReplace() {
- return new ComputingSerializationProxy<K, V>(keyStrength, valueStrength, keyEquivalence,
- valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maximumSize,
- concurrencyLevel, removalListener, this, computingFunction);
+ return new ComputingSerializationProxy<K, V>(
+ keyStrength,
+ valueStrength,
+ keyEquivalence,
+ valueEquivalence,
+ expireAfterWriteNanos,
+ expireAfterAccessNanos,
+ maximumSize,
+ concurrencyLevel,
+ removalListener,
+ this,
+ computingFunction);
}
static final class ComputingSerializationProxy<K, V> extends AbstractSerializationProxy<K, V> {
final Function<? super K, ? extends V> computingFunction;
- ComputingSerializationProxy(Strength keyStrength, Strength valueStrength,
- Equivalence<Object> keyEquivalence, Equivalence<Object> valueEquivalence,
- long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize,
- int concurrencyLevel, RemovalListener<? super K, ? super V> removalListener,
- ConcurrentMap<K, V> delegate, Function<? super K, ? extends V> computingFunction) {
- super(keyStrength, valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos,
- expireAfterAccessNanos, maximumSize, concurrencyLevel, removalListener, delegate);
+ ComputingSerializationProxy(
+ Strength keyStrength,
+ Strength valueStrength,
+ Equivalence<Object> keyEquivalence,
+ Equivalence<Object> valueEquivalence,
+ long expireAfterWriteNanos,
+ long expireAfterAccessNanos,
+ int maximumSize,
+ int concurrencyLevel,
+ RemovalListener<? super K, ? super V> removalListener,
+ ConcurrentMap<K, V> delegate,
+ Function<? super K, ? extends V> computingFunction) {
+ super(
+ keyStrength,
+ valueStrength,
+ keyEquivalence,
+ valueEquivalence,
+ expireAfterWriteNanos,
+ expireAfterAccessNanos,
+ maximumSize,
+ concurrencyLevel,
+ removalListener,
+ delegate);
this.computingFunction = computingFunction;
}
diff --git a/guava/src/com/google/common/collect/ConcurrentHashMultiset.java b/guava/src/com/google/common/collect/ConcurrentHashMultiset.java
index 89afa4e..e3cb982 100644
--- a/guava/src/com/google/common/collect/ConcurrentHashMultiset.java
+++ b/guava/src/com/google/common/collect/ConcurrentHashMultiset.java
@@ -26,6 +26,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Serialization.FieldSetter;
import com.google.common.math.IntMath;
import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -47,12 +48,12 @@ import javax.annotation.Nullable;
* {@code Multiset} operations (exceptions where noted). Null elements are not supported.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
* {@code Multiset}</a>.
*
* @author Cliff L. Biffle
* @author mike nonemacher
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> implements Serializable {
@@ -137,7 +138,8 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* their counts. It must be empty.
* @throws IllegalArgumentException if {@code countMap} is not empty
*/
- @VisibleForTesting ConcurrentHashMultiset(ConcurrentMap<E, AtomicInteger> countMap) {
+ @VisibleForTesting
+ ConcurrentHashMultiset(ConcurrentMap<E, AtomicInteger> countMap) {
checkArgument(countMap.isEmpty());
this.countMap = countMap;
}
@@ -150,7 +152,8 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* @param element the element to look for
* @return the nonnegative number of occurrences of the element
*/
- @Override public int count(@Nullable Object element) {
+ @Override
+ public int count(@Nullable Object element) {
AtomicInteger existingCounter = Maps.safeGet(countMap, element);
return (existingCounter == null) ? 0 : existingCounter.get();
}
@@ -161,7 +164,8 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* <p>If the data in the multiset is modified by any other threads during this method,
* it is undefined which (if any) of these modifications will be reflected in the result.
*/
- @Override public int size() {
+ @Override
+ public int size() {
long sum = 0L;
for (AtomicInteger value : countMap.values()) {
sum += value.get();
@@ -174,11 +178,13 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* answer, which ours does not.
*/
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
return snapshot().toArray();
}
- @Override public <T> T[] toArray(T[] array) {
+ @Override
+ public <T> T[] toArray(T[] array) {
return snapshot().toArray(array);
}
@@ -208,12 +214,13 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* @throws IllegalArgumentException if {@code occurrences} is negative, or if
* the resulting amount would exceed {@link Integer#MAX_VALUE}
*/
- @Override public int add(E element, int occurrences) {
+ @Override
+ public int add(E element, int occurrences) {
checkNotNull(element);
if (occurrences == 0) {
return count(element);
}
- checkArgument(occurrences > 0, "Invalid occurrences: %s", occurrences);
+ CollectPreconditions.checkPositive(occurrences, "occurences");
while (true) {
AtomicInteger existingCounter = Maps.safeGet(countMap, element);
@@ -235,8 +242,8 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
return oldValue;
}
} catch (ArithmeticException overflow) {
- throw new IllegalArgumentException("Overflow adding " + occurrences
- + " occurrences to a count of " + oldValue);
+ throw new IllegalArgumentException(
+ "Overflow adding " + occurrences + " occurrences to a count of " + oldValue);
}
} else {
// In the case of a concurrent remove, we might observe a zero value, which means another
@@ -273,11 +280,12 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* we'll want to remove @Nullable, add an eager checkNotNull, and loosen up
* testRemove_nullAllowed.
*/
- @Override public int remove(@Nullable Object element, int occurrences) {
+ @Override
+ public int remove(@Nullable Object element, int occurrences) {
if (occurrences == 0) {
return count(element);
}
- checkArgument(occurrences > 0, "Invalid occurrences: %s", occurrences);
+ CollectPreconditions.checkPositive(occurrences, "occurences");
AtomicInteger existingCounter = Maps.safeGet(countMap, element);
if (existingCounter == null) {
@@ -311,12 +319,13 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* @param element the element to remove
* @param occurrences the number of occurrences of {@code element} to remove
* @return {@code true} if the removal was possible (including if {@code occurrences} is zero)
+ * @throws IllegalArgumentException if {@code occurrences} is negative
*/
public boolean removeExactly(@Nullable Object element, int occurrences) {
if (occurrences == 0) {
return true;
}
- checkArgument(occurrences > 0, "Invalid occurrences: %s", occurrences);
+ CollectPreconditions.checkPositive(occurrences, "occurences");
AtomicInteger existingCounter = Maps.safeGet(countMap, element);
if (existingCounter == null) {
@@ -346,7 +355,8 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* @return the count of {@code element} in the multiset before this call
* @throws IllegalArgumentException if {@code count} is negative
*/
- @Override public int setCount(E element, int count) {
+ @Override
+ public int setCount(E element, int count) {
checkNotNull(element);
checkNonnegative(count, "count");
while (true) {
@@ -401,7 +411,8 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* the condition was met.
* @throws IllegalArgumentException if {@code expectedOldCount} or {@code newCount} is negative
*/
- @Override public boolean setCount(E element, int expectedOldCount, int newCount) {
+ @Override
+ public boolean setCount(E element, int expectedOldCount, int newCount) {
checkNotNull(element);
checkNonnegative(expectedOldCount, "oldCount");
checkNonnegative(newCount, "newCount");
@@ -445,10 +456,12 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
// Views
- @Override Set<E> createElementSet() {
+ @Override
+ Set<E> createElementSet() {
final Set<E> delegate = countMap.keySet();
return new ForwardingSet<E>() {
- @Override protected Set<E> delegate() {
+ @Override
+ protected Set<E> delegate() {
return delegate;
}
@@ -462,36 +475,43 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
return standardContainsAll(collection);
}
- @Override public boolean remove(Object object) {
+ @Override
+ public boolean remove(Object object) {
return object != null && Collections2.safeRemove(delegate, object);
}
- @Override public boolean removeAll(Collection<?> c) {
+ @Override
+ public boolean removeAll(Collection<?> c) {
return standardRemoveAll(c);
}
};
}
- @Override public Set<Multiset.Entry<E>> createEntrySet() {
+ @Override
+ public Set<Multiset.Entry<E>> createEntrySet() {
return new EntrySet();
}
- @Override int distinctElements() {
+ @Override
+ int distinctElements() {
return countMap.size();
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return countMap.isEmpty();
}
- @Override Iterator<Entry<E>> entryIterator() {
+ @Override
+ Iterator<Entry<E>> entryIterator() {
// AbstractIterator makes this fairly clean, but it doesn't support remove(). To support
// remove(), we create an AbstractIterator, and then use ForwardingIterator to delegate to it.
final Iterator<Entry<E>> readOnlyIterator =
new AbstractIterator<Entry<E>>() {
private Iterator<Map.Entry<E, AtomicInteger>> mapEntries = countMap.entrySet().iterator();
- @Override protected Entry<E> computeNext() {
+ @Override
+ protected Entry<E> computeNext() {
while (true) {
if (!mapEntries.hasNext()) {
return endOfData();
@@ -508,16 +528,19 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
return new ForwardingIterator<Entry<E>>() {
private Entry<E> last;
- @Override protected Iterator<Entry<E>> delegate() {
+ @Override
+ protected Iterator<Entry<E>> delegate() {
return readOnlyIterator;
}
- @Override public Entry<E> next() {
+ @Override
+ public Entry<E> next() {
last = super.next();
return last;
}
- @Override public void remove() {
+ @Override
+ public void remove() {
checkRemove(last != null);
ConcurrentHashMultiset.this.setCount(last.getElement(), 0);
last = null;
@@ -525,12 +548,15 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
};
}
- @Override public void clear() {
+ @Override
+ public void clear() {
countMap.clear();
}
+ @WeakOuter
private class EntrySet extends AbstractMultiset<E>.EntrySet {
- @Override ConcurrentHashMultiset<E> multiset() {
+ @Override
+ ConcurrentHashMultiset<E> multiset() {
return ConcurrentHashMultiset.this;
}
@@ -539,11 +565,13 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* answer, which ours does not.
*/
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
return snapshot().toArray();
}
- @Override public <T> T[] toArray(T[] array) {
+ @Override
+ public <T> T[] toArray(T[] array) {
return snapshot().toArray(array);
}
diff --git a/guava/src/com/google/common/collect/Constraints.java b/guava/src/com/google/common/collect/Constraints.java
index 2b5da00..505f31e 100644
--- a/guava/src/com/google/common/collect/Constraints.java
+++ b/guava/src/com/google/common/collect/Constraints.java
@@ -59,19 +59,24 @@ final class Constraints {
private final Collection<E> delegate;
private final Constraint<? super E> constraint;
- public ConstrainedCollection(
- Collection<E> delegate, Constraint<? super E> constraint) {
+ public ConstrainedCollection(Collection<E> delegate, Constraint<? super E> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
- @Override protected Collection<E> delegate() {
+
+ @Override
+ protected Collection<E> delegate() {
return delegate;
}
- @Override public boolean add(E element) {
+
+ @Override
+ public boolean add(E element) {
constraint.checkElement(element);
return delegate.add(element);
}
- @Override public boolean addAll(Collection<? extends E> elements) {
+
+ @Override
+ public boolean addAll(Collection<? extends E> elements) {
return delegate.addAll(checkElements(elements, constraint));
}
}
@@ -88,8 +93,7 @@ final class Constraints {
* @param constraint the constraint that validates added elements
* @return a constrained view of the set
*/
- public static <E> Set<E> constrainedSet(
- Set<E> set, Constraint<? super E> constraint) {
+ public static <E> Set<E> constrainedSet(Set<E> set, Constraint<? super E> constraint) {
return new ConstrainedSet<E>(set, constraint);
}
@@ -102,14 +106,20 @@ final class Constraints {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
- @Override protected Set<E> delegate() {
+
+ @Override
+ protected Set<E> delegate() {
return delegate;
}
- @Override public boolean add(E element) {
+
+ @Override
+ public boolean add(E element) {
constraint.checkElement(element);
return delegate.add(element);
}
- @Override public boolean addAll(Collection<? extends E> elements) {
+
+ @Override
+ public boolean addAll(Collection<? extends E> elements) {
return delegate.addAll(checkElements(elements, constraint));
}
}
@@ -136,29 +146,39 @@ final class Constraints {
final SortedSet<E> delegate;
final Constraint<? super E> constraint;
- ConstrainedSortedSet(
- SortedSet<E> delegate, Constraint<? super E> constraint) {
+ ConstrainedSortedSet(SortedSet<E> delegate, Constraint<? super E> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
- @Override protected SortedSet<E> delegate() {
+
+ @Override
+ protected SortedSet<E> delegate() {
return delegate;
}
- @Override public SortedSet<E> headSet(E toElement) {
+
+ @Override
+ public SortedSet<E> headSet(E toElement) {
return constrainedSortedSet(delegate.headSet(toElement), constraint);
}
- @Override public SortedSet<E> subSet(E fromElement, E toElement) {
- return constrainedSortedSet(
- delegate.subSet(fromElement, toElement), constraint);
+
+ @Override
+ public SortedSet<E> subSet(E fromElement, E toElement) {
+ return constrainedSortedSet(delegate.subSet(fromElement, toElement), constraint);
}
- @Override public SortedSet<E> tailSet(E fromElement) {
+
+ @Override
+ public SortedSet<E> tailSet(E fromElement) {
return constrainedSortedSet(delegate.tailSet(fromElement), constraint);
}
- @Override public boolean add(E element) {
+
+ @Override
+ public boolean add(E element) {
constraint.checkElement(element);
return delegate.add(element);
}
- @Override public boolean addAll(Collection<? extends E> elements) {
+
+ @Override
+ public boolean addAll(Collection<? extends E> elements) {
return delegate.addAll(checkElements(elements, constraint));
}
}
@@ -176,8 +196,7 @@ final class Constraints {
* @param constraint the constraint that validates added elements
* @return a constrained view of the list
*/
- public static <E> List<E> constrainedList(
- List<E> list, Constraint<? super E> constraint) {
+ public static <E> List<E> constrainedList(List<E> list, Constraint<? super E> constraint) {
return (list instanceof RandomAccess)
? new ConstrainedRandomAccessList<E>(list, constraint)
: new ConstrainedList<E>(list, constraint);
@@ -193,46 +212,59 @@ final class Constraints {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
- @Override protected List<E> delegate() {
+
+ @Override
+ protected List<E> delegate() {
return delegate;
}
- @Override public boolean add(E element) {
+ @Override
+ public boolean add(E element) {
constraint.checkElement(element);
return delegate.add(element);
}
- @Override public void add(int index, E element) {
+
+ @Override
+ public void add(int index, E element) {
constraint.checkElement(element);
delegate.add(index, element);
}
- @Override public boolean addAll(Collection<? extends E> elements) {
+
+ @Override
+ public boolean addAll(Collection<? extends E> elements) {
return delegate.addAll(checkElements(elements, constraint));
}
- @Override public boolean addAll(int index, Collection<? extends E> elements)
- {
+
+ @Override
+ public boolean addAll(int index, Collection<? extends E> elements) {
return delegate.addAll(index, checkElements(elements, constraint));
}
- @Override public ListIterator<E> listIterator() {
+
+ @Override
+ public ListIterator<E> listIterator() {
return constrainedListIterator(delegate.listIterator(), constraint);
}
- @Override public ListIterator<E> listIterator(int index) {
+
+ @Override
+ public ListIterator<E> listIterator(int index) {
return constrainedListIterator(delegate.listIterator(index), constraint);
}
- @Override public E set(int index, E element) {
+
+ @Override
+ public E set(int index, E element) {
constraint.checkElement(element);
return delegate.set(index, element);
}
- @Override public List<E> subList(int fromIndex, int toIndex) {
- return constrainedList(
- delegate.subList(fromIndex, toIndex), constraint);
+
+ @Override
+ public List<E> subList(int fromIndex, int toIndex) {
+ return constrainedList(delegate.subList(fromIndex, toIndex), constraint);
}
}
/** @see Constraints#constrainedList */
- static class ConstrainedRandomAccessList<E> extends ConstrainedList<E>
- implements RandomAccess {
- ConstrainedRandomAccessList(
- List<E> delegate, Constraint<? super E> constraint) {
+ static class ConstrainedRandomAccessList<E> extends ConstrainedList<E> implements RandomAccess {
+ ConstrainedRandomAccessList(List<E> delegate, Constraint<? super E> constraint) {
super(delegate, constraint);
}
}
@@ -256,20 +288,24 @@ final class Constraints {
private final ListIterator<E> delegate;
private final Constraint<? super E> constraint;
- public ConstrainedListIterator(
- ListIterator<E> delegate, Constraint<? super E> constraint) {
+ public ConstrainedListIterator(ListIterator<E> delegate, Constraint<? super E> constraint) {
this.delegate = delegate;
this.constraint = constraint;
}
- @Override protected ListIterator<E> delegate() {
+
+ @Override
+ protected ListIterator<E> delegate() {
return delegate;
}
- @Override public void add(E element) {
+ @Override
+ public void add(E element) {
constraint.checkElement(element);
delegate.add(element);
}
- @Override public void set(E element) {
+
+ @Override
+ public void set(E element) {
constraint.checkElement(element);
delegate.set(element);
}
diff --git a/guava/src/com/google/common/collect/ConsumingQueueIterator.java b/guava/src/com/google/common/collect/ConsumingQueueIterator.java
new file mode 100644
index 0000000..bf48a7d
--- /dev/null
+++ b/guava/src/com/google/common/collect/ConsumingQueueIterator.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.common.collect;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.util.Collections;
+import java.util.Queue;
+
+/**
+ * An Iterator implementation which draws elements from a queue, removing them from the queue as it
+ * iterates.
+ */
+ at GwtCompatible
+class ConsumingQueueIterator<T> extends AbstractIterator<T> {
+ private final Queue<T> queue;
+
+ ConsumingQueueIterator(T... elements) {
+ // Uses LinkedList because ArrayDeque isn't GWT-compatible for now =(
+ this.queue = Lists.newLinkedList();
+ Collections.addAll(queue, elements);
+ }
+
+ ConsumingQueueIterator(Queue<T> queue) {
+ this.queue = checkNotNull(queue);
+ }
+
+ @Override
+ public T computeNext() {
+ return queue.isEmpty() ? endOfData() : queue.remove();
+ }
+}
diff --git a/guava/src/com/google/common/collect/ContiguousSet.java b/guava/src/com/google/common/collect/ContiguousSet.java
index 16f19fa..1bd2856 100644
--- a/guava/src/com/google/common/collect/ContiguousSet.java
+++ b/guava/src/com/google/common/collect/ContiguousSet.java
@@ -66,10 +66,12 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
}
// Per class spec, we are allowed to throw CCE if necessary
- boolean empty = effectiveRange.isEmpty()
- || Range.compareOrThrow(
- range.lowerBound.leastValueAbove(domain),
- range.upperBound.greatestValueBelow(domain)) > 0;
+ boolean empty =
+ effectiveRange.isEmpty()
+ || Range.compareOrThrow(
+ range.lowerBound.leastValueAbove(domain),
+ range.upperBound.greatestValueBelow(domain))
+ > 0;
return empty
? new EmptyContiguousSet<C>(domain)
@@ -83,7 +85,8 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
this.domain = domain;
}
- @Override public ContiguousSet<C> headSet(C toElement) {
+ @Override
+ public ContiguousSet<C> headSet(C toElement) {
return headSetImpl(checkNotNull(toElement), false);
}
@@ -91,11 +94,13 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
* @since 12.0
*/
@GwtIncompatible("NavigableSet")
- @Override public ContiguousSet<C> headSet(C toElement, boolean inclusive) {
+ @Override
+ public ContiguousSet<C> headSet(C toElement, boolean inclusive) {
return headSetImpl(checkNotNull(toElement), inclusive);
}
- @Override public ContiguousSet<C> subSet(C fromElement, C toElement) {
+ @Override
+ public ContiguousSet<C> subSet(C fromElement, C toElement) {
checkNotNull(fromElement);
checkNotNull(toElement);
checkArgument(comparator().compare(fromElement, toElement) <= 0);
@@ -106,15 +111,17 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
* @since 12.0
*/
@GwtIncompatible("NavigableSet")
- @Override public ContiguousSet<C> subSet(C fromElement, boolean fromInclusive, C toElement,
- boolean toInclusive) {
+ @Override
+ public ContiguousSet<C> subSet(
+ C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
checkNotNull(fromElement);
checkNotNull(toElement);
checkArgument(comparator().compare(fromElement, toElement) <= 0);
return subSetImpl(fromElement, fromInclusive, toElement, toInclusive);
}
- @Override public ContiguousSet<C> tailSet(C fromElement) {
+ @Override
+ public ContiguousSet<C> tailSet(C fromElement) {
return tailSetImpl(checkNotNull(fromElement), true);
}
@@ -122,19 +129,24 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
* @since 12.0
*/
@GwtIncompatible("NavigableSet")
- @Override public ContiguousSet<C> tailSet(C fromElement, boolean inclusive) {
+ @Override
+ public ContiguousSet<C> tailSet(C fromElement, boolean inclusive) {
return tailSetImpl(checkNotNull(fromElement), inclusive);
}
/*
* These methods perform most headSet, subSet, and tailSet logic, besides parameter validation.
*/
- /*@Override*/ abstract ContiguousSet<C> headSetImpl(C toElement, boolean inclusive);
+ // TODO(kevinb): we can probably make these real @Overrides now
+ /*@Override*/
+ abstract ContiguousSet<C> headSetImpl(C toElement, boolean inclusive);
- /*@Override*/ abstract ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive,
- C toElement, boolean toInclusive);
+ /*@Override*/
+ abstract ContiguousSet<C> subSetImpl(
+ C fromElement, boolean fromInclusive, C toElement, boolean toInclusive);
- /*@Override*/ abstract ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive);
+ /*@Override*/
+ abstract ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive);
/**
* Returns the set of values that are contained in both this set and the other.
@@ -166,7 +178,8 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
public abstract Range<C> range(BoundType lowerBoundType, BoundType upperBoundType);
/** Returns a short-hand representation of the contents such as {@code "[1..100]"}. */
- @Override public String toString() {
+ @Override
+ public String toString() {
return range().toString();
}
@@ -178,7 +191,8 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
* @throws UnsupportedOperationException always
* @deprecated Use {@link #create}.
*/
- @Deprecated public static <E> ImmutableSortedSet.Builder<E> builder() {
+ @Deprecated
+ public static <E> ImmutableSortedSet.Builder<E> builder() {
throw new UnsupportedOperationException();
}
}
diff --git a/guava/src/com/google/common/collect/Cut.java b/guava/src/com/google/common/collect/Cut.java
index 44e3450..087b234 100644
--- a/guava/src/com/google/common/collect/Cut.java
+++ b/guava/src/com/google/common/collect/Cut.java
@@ -44,15 +44,19 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
abstract boolean isLessThan(C value);
abstract BoundType typeAsLowerBound();
+
abstract BoundType typeAsUpperBound();
abstract Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain);
+
abstract Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain);
abstract void describeAsLowerBound(StringBuilder sb);
+
abstract void describeAsUpperBound(StringBuilder sb);
abstract C leastValueAbove(DiscreteDomain<C> domain);
+
abstract C greatestValueBelow(DiscreteDomain<C> domain);
/*
@@ -77,8 +81,7 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
return result;
}
// same value. below comes before above
- return Booleans.compare(
- this instanceof AboveValue, that instanceof AboveValue);
+ return Booleans.compare(this instanceof AboveValue, that instanceof AboveValue);
}
C endpoint() {
@@ -86,7 +89,8 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
}
@SuppressWarnings("unchecked") // catching CCE
- @Override public boolean equals(Object obj) {
+ @Override
+ public boolean equals(Object obj) {
if (obj instanceof Cut) {
// It might not really be a Cut<C>, but we'll catch a CCE if it's not
Cut<C> that = (Cut<C>) obj;
@@ -116,57 +120,82 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
private BelowAll() {
super(null);
}
- @Override Comparable<?> endpoint() {
+
+ @Override
+ Comparable<?> endpoint() {
throw new IllegalStateException("range unbounded on this side");
}
- @Override boolean isLessThan(Comparable<?> value) {
+
+ @Override
+ boolean isLessThan(Comparable<?> value) {
return true;
}
- @Override BoundType typeAsLowerBound() {
+
+ @Override
+ BoundType typeAsLowerBound() {
throw new IllegalStateException();
}
- @Override BoundType typeAsUpperBound() {
+
+ @Override
+ BoundType typeAsUpperBound() {
throw new AssertionError("this statement should be unreachable");
}
- @Override Cut<Comparable<?>> withLowerBoundType(BoundType boundType,
- DiscreteDomain<Comparable<?>> domain) {
+
+ @Override
+ Cut<Comparable<?>> withLowerBoundType(
+ BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
throw new IllegalStateException();
}
- @Override Cut<Comparable<?>> withUpperBoundType(BoundType boundType,
- DiscreteDomain<Comparable<?>> domain) {
+
+ @Override
+ Cut<Comparable<?>> withUpperBoundType(
+ BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
throw new AssertionError("this statement should be unreachable");
}
- @Override void describeAsLowerBound(StringBuilder sb) {
+
+ @Override
+ void describeAsLowerBound(StringBuilder sb) {
sb.append("(-\u221e");
}
- @Override void describeAsUpperBound(StringBuilder sb) {
+
+ @Override
+ void describeAsUpperBound(StringBuilder sb) {
throw new AssertionError();
}
- @Override Comparable<?> leastValueAbove(
- DiscreteDomain<Comparable<?>> domain) {
+
+ @Override
+ Comparable<?> leastValueAbove(DiscreteDomain<Comparable<?>> domain) {
return domain.minValue();
}
- @Override Comparable<?> greatestValueBelow(
- DiscreteDomain<Comparable<?>> domain) {
+
+ @Override
+ Comparable<?> greatestValueBelow(DiscreteDomain<Comparable<?>> domain) {
throw new AssertionError();
}
- @Override Cut<Comparable<?>> canonical(
- DiscreteDomain<Comparable<?>> domain) {
+
+ @Override
+ Cut<Comparable<?>> canonical(DiscreteDomain<Comparable<?>> domain) {
try {
return Cut.<Comparable<?>>belowValue(domain.minValue());
} catch (NoSuchElementException e) {
return this;
}
}
- @Override public int compareTo(Cut<Comparable<?>> o) {
+
+ @Override
+ public int compareTo(Cut<Comparable<?>> o) {
return (o == this) ? 0 : -1;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "-\u221e";
}
+
private Object readResolve() {
return INSTANCE;
}
+
private static final long serialVersionUID = 0;
}
@@ -185,49 +214,73 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
private AboveAll() {
super(null);
}
- @Override Comparable<?> endpoint() {
+
+ @Override
+ Comparable<?> endpoint() {
throw new IllegalStateException("range unbounded on this side");
}
- @Override boolean isLessThan(Comparable<?> value) {
+
+ @Override
+ boolean isLessThan(Comparable<?> value) {
return false;
}
- @Override BoundType typeAsLowerBound() {
+
+ @Override
+ BoundType typeAsLowerBound() {
throw new AssertionError("this statement should be unreachable");
}
- @Override BoundType typeAsUpperBound() {
+
+ @Override
+ BoundType typeAsUpperBound() {
throw new IllegalStateException();
}
- @Override Cut<Comparable<?>> withLowerBoundType(BoundType boundType,
- DiscreteDomain<Comparable<?>> domain) {
+
+ @Override
+ Cut<Comparable<?>> withLowerBoundType(
+ BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
throw new AssertionError("this statement should be unreachable");
}
- @Override Cut<Comparable<?>> withUpperBoundType(BoundType boundType,
- DiscreteDomain<Comparable<?>> domain) {
+
+ @Override
+ Cut<Comparable<?>> withUpperBoundType(
+ BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
throw new IllegalStateException();
}
- @Override void describeAsLowerBound(StringBuilder sb) {
+
+ @Override
+ void describeAsLowerBound(StringBuilder sb) {
throw new AssertionError();
}
- @Override void describeAsUpperBound(StringBuilder sb) {
+
+ @Override
+ void describeAsUpperBound(StringBuilder sb) {
sb.append("+\u221e)");
}
- @Override Comparable<?> leastValueAbove(
- DiscreteDomain<Comparable<?>> domain) {
+
+ @Override
+ Comparable<?> leastValueAbove(DiscreteDomain<Comparable<?>> domain) {
throw new AssertionError();
}
- @Override Comparable<?> greatestValueBelow(
- DiscreteDomain<Comparable<?>> domain) {
+
+ @Override
+ Comparable<?> greatestValueBelow(DiscreteDomain<Comparable<?>> domain) {
return domain.maxValue();
}
- @Override public int compareTo(Cut<Comparable<?>> o) {
+
+ @Override
+ public int compareTo(Cut<Comparable<?>> o) {
return (o == this) ? 0 : 1;
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "+\u221e";
}
+
private Object readResolve() {
return INSTANCE;
}
+
private static final long serialVersionUID = 0;
}
@@ -240,16 +293,23 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
super(checkNotNull(endpoint));
}
- @Override boolean isLessThan(C value) {
+ @Override
+ boolean isLessThan(C value) {
return Range.compareOrThrow(endpoint, value) <= 0;
}
- @Override BoundType typeAsLowerBound() {
+
+ @Override
+ BoundType typeAsLowerBound() {
return BoundType.CLOSED;
}
- @Override BoundType typeAsUpperBound() {
+
+ @Override
+ BoundType typeAsUpperBound() {
return BoundType.OPEN;
}
- @Override Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
+
+ @Override
+ Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
switch (boundType) {
case CLOSED:
return this;
@@ -260,7 +320,9 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
throw new AssertionError();
}
}
- @Override Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
+
+ @Override
+ Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
switch (boundType) {
case CLOSED:
@Nullable C previous = domain.previous(endpoint);
@@ -271,24 +333,37 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
throw new AssertionError();
}
}
- @Override void describeAsLowerBound(StringBuilder sb) {
+
+ @Override
+ void describeAsLowerBound(StringBuilder sb) {
sb.append('[').append(endpoint);
}
- @Override void describeAsUpperBound(StringBuilder sb) {
+
+ @Override
+ void describeAsUpperBound(StringBuilder sb) {
sb.append(endpoint).append(')');
}
- @Override C leastValueAbove(DiscreteDomain<C> domain) {
+
+ @Override
+ C leastValueAbove(DiscreteDomain<C> domain) {
return endpoint;
}
- @Override C greatestValueBelow(DiscreteDomain<C> domain) {
+
+ @Override
+ C greatestValueBelow(DiscreteDomain<C> domain) {
return domain.previous(endpoint);
}
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
return endpoint.hashCode();
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "\\" + endpoint + "/";
}
+
private static final long serialVersionUID = 0;
}
@@ -301,16 +376,23 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
super(checkNotNull(endpoint));
}
- @Override boolean isLessThan(C value) {
+ @Override
+ boolean isLessThan(C value) {
return Range.compareOrThrow(endpoint, value) < 0;
}
- @Override BoundType typeAsLowerBound() {
+
+ @Override
+ BoundType typeAsLowerBound() {
return BoundType.OPEN;
}
- @Override BoundType typeAsUpperBound() {
+
+ @Override
+ BoundType typeAsUpperBound() {
return BoundType.CLOSED;
}
- @Override Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
+
+ @Override
+ Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
switch (boundType) {
case OPEN:
return this;
@@ -321,7 +403,9 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
throw new AssertionError();
}
}
- @Override Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
+
+ @Override
+ Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
switch (boundType) {
case OPEN:
@Nullable C next = domain.next(endpoint);
@@ -332,28 +416,43 @@ abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializ
throw new AssertionError();
}
}
- @Override void describeAsLowerBound(StringBuilder sb) {
+
+ @Override
+ void describeAsLowerBound(StringBuilder sb) {
sb.append('(').append(endpoint);
}
- @Override void describeAsUpperBound(StringBuilder sb) {
+
+ @Override
+ void describeAsUpperBound(StringBuilder sb) {
sb.append(endpoint).append(']');
}
- @Override C leastValueAbove(DiscreteDomain<C> domain) {
+
+ @Override
+ C leastValueAbove(DiscreteDomain<C> domain) {
return domain.next(endpoint);
}
- @Override C greatestValueBelow(DiscreteDomain<C> domain) {
+
+ @Override
+ C greatestValueBelow(DiscreteDomain<C> domain) {
return endpoint;
}
- @Override Cut<C> canonical(DiscreteDomain<C> domain) {
+
+ @Override
+ Cut<C> canonical(DiscreteDomain<C> domain) {
C next = leastValueAbove(domain);
return (next != null) ? belowValue(next) : Cut.<C>aboveAll();
}
- @Override public int hashCode() {
+
+ @Override
+ public int hashCode() {
return ~endpoint.hashCode();
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "/" + endpoint + "\\";
}
+
private static final long serialVersionUID = 0;
}
}
diff --git a/guava/src/com/google/common/collect/DenseImmutableTable.java b/guava/src/com/google/common/collect/DenseImmutableTable.java
index 60f93a8..81f26ad 100644
--- a/guava/src/com/google/common/collect/DenseImmutableTable.java
+++ b/guava/src/com/google/common/collect/DenseImmutableTable.java
@@ -17,8 +17,11 @@ package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.ImmutableMap.IteratorBasedImmutableMap;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.Map;
+import java.util.Map.Entry;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@@ -28,8 +31,7 @@ import javax.annotation.concurrent.Immutable;
*/
@GwtCompatible
@Immutable
-final class DenseImmutableTable<R, C, V>
- extends RegularImmutableTable<R, C, V> {
+final class DenseImmutableTable<R, C, V> extends RegularImmutableTable<R, C, V> {
private final ImmutableMap<R, Integer> rowKeyToIndex;
private final ImmutableMap<C, Integer> columnKeyToIndex;
private final ImmutableMap<R, Map<C, V>> rowMap;
@@ -40,23 +42,15 @@ final class DenseImmutableTable<R, C, V>
private final int[] iterationOrderRow;
private final int[] iterationOrderColumn;
- private static <E> ImmutableMap<E, Integer> makeIndex(ImmutableSet<E> set) {
- ImmutableMap.Builder<E, Integer> indexBuilder = ImmutableMap.builder();
- int i = 0;
- for (E key : set) {
- indexBuilder.put(key, i);
- i++;
- }
- return indexBuilder.build();
- }
-
- DenseImmutableTable(ImmutableList<Cell<R, C, V>> cellList,
- ImmutableSet<R> rowSpace, ImmutableSet<C> columnSpace) {
+ DenseImmutableTable(
+ ImmutableList<Cell<R, C, V>> cellList,
+ ImmutableSet<R> rowSpace,
+ ImmutableSet<C> columnSpace) {
@SuppressWarnings("unchecked")
V[][] array = (V[][]) new Object[rowSpace.size()][columnSpace.size()];
this.values = array;
- this.rowKeyToIndex = makeIndex(rowSpace);
- this.columnKeyToIndex = makeIndex(columnSpace);
+ this.rowKeyToIndex = Maps.indexMap(rowSpace);
+ this.columnKeyToIndex = Maps.indexMap(columnSpace);
rowCounts = new int[rowKeyToIndex.size()];
columnCounts = new int[columnKeyToIndex.size()];
int[] iterationOrderRow = new int[cellList.size()];
@@ -84,66 +78,58 @@ final class DenseImmutableTable<R, C, V>
/**
* An immutable map implementation backed by an indexed nullable array.
*/
- private abstract static class ImmutableArrayMap<K, V> extends ImmutableMap<K, V> {
+ private abstract static class ImmutableArrayMap<K, V> extends IteratorBasedImmutableMap<K, V> {
private final int size;
-
+
ImmutableArrayMap(int size) {
this.size = size;
}
-
+
abstract ImmutableMap<K, Integer> keyToIndex();
-
+
// True if getValue never returns null.
private boolean isFull() {
return size == keyToIndex().size();
}
-
+
K getKey(int index) {
return keyToIndex().keySet().asList().get(index);
}
-
- @Nullable abstract V getValue(int keyIndex);
-
+
+ @Nullable
+ abstract V getValue(int keyIndex);
+
@Override
ImmutableSet<K> createKeySet() {
return isFull() ? keyToIndex().keySet() : super.createKeySet();
}
-
+
@Override
public int size() {
return size;
}
-
+
@Override
public V get(@Nullable Object key) {
Integer keyIndex = keyToIndex().get(key);
return (keyIndex == null) ? null : getValue(keyIndex);
}
-
+
@Override
- ImmutableSet<Entry<K, V>> createEntrySet() {
- return new ImmutableMapEntrySet<K, V>() {
- @Override ImmutableMap<K, V> map() {
- return ImmutableArrayMap.this;
- }
+ UnmodifiableIterator<Entry<K, V>> entryIterator() {
+ return new AbstractIterator<Entry<K, V>>() {
+ private int index = -1;
+ private final int maxIndex = keyToIndex().size();
@Override
- public UnmodifiableIterator<Entry<K, V>> iterator() {
- return new AbstractIterator<Entry<K, V>>() {
- private int index = -1;
- private final int maxIndex = keyToIndex().size();
-
- @Override
- protected Entry<K, V> computeNext() {
- for (index++; index < maxIndex; index++) {
- V value = getValue(index);
- if (value != null) {
- return Maps.immutableEntry(getKey(index), value);
- }
- }
- return endOfData();
+ protected Entry<K, V> computeNext() {
+ for (index++; index < maxIndex; index++) {
+ V value = getValue(index);
+ if (value != null) {
+ return Maps.immutableEntry(getKey(index), value);
}
- };
+ }
+ return endOfData();
}
};
}
@@ -197,6 +183,7 @@ final class DenseImmutableTable<R, C, V>
}
}
+ @WeakOuter
private final class RowMap extends ImmutableArrayMap<R, Map<C, V>> {
private RowMap() {
super(rowCounts.length);
@@ -218,6 +205,7 @@ final class DenseImmutableTable<R, C, V>
}
}
+ @WeakOuter
private final class ColumnMap extends ImmutableArrayMap<C, Map<R, V>> {
private ColumnMap() {
super(columnCounts.length);
@@ -239,7 +227,8 @@ final class DenseImmutableTable<R, C, V>
}
}
- @Override public ImmutableMap<C, Map<R, V>> columnMap() {
+ @Override
+ public ImmutableMap<C, Map<R, V>> columnMap() {
return columnMap;
}
@@ -248,12 +237,11 @@ final class DenseImmutableTable<R, C, V>
return rowMap;
}
- @Override public V get(@Nullable Object rowKey,
- @Nullable Object columnKey) {
+ @Override
+ public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
Integer rowIndex = rowKeyToIndex.get(rowKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
- return ((rowIndex == null) || (columnIndex == null)) ? null
- : values[rowIndex][columnIndex];
+ return ((rowIndex == null) || (columnIndex == null)) ? null : values[rowIndex][columnIndex];
}
@Override
diff --git a/guava/src/com/google/common/collect/DescendingImmutableSortedMultiset.java b/guava/src/com/google/common/collect/DescendingImmutableSortedMultiset.java
index 4408662..0246b40 100644
--- a/guava/src/com/google/common/collect/DescendingImmutableSortedMultiset.java
+++ b/guava/src/com/google/common/collect/DescendingImmutableSortedMultiset.java
@@ -56,7 +56,11 @@ final class DescendingImmutableSortedMultiset<E> extends ImmutableSortedMultiset
@Override
Entry<E> getEntry(int index) {
- return forward.entrySet().asList().reverse().get(index);
+ return forward
+ .entrySet()
+ .asList()
+ .reverse()
+ .get(index);
}
@Override
diff --git a/guava/src/com/google/common/collect/DescendingImmutableSortedSet.java b/guava/src/com/google/common/collect/DescendingImmutableSortedSet.java
index 340d8b9..d30b0fd 100644
--- a/guava/src/com/google/common/collect/DescendingImmutableSortedSet.java
+++ b/guava/src/com/google/common/collect/DescendingImmutableSortedSet.java
@@ -34,6 +34,11 @@ class DescendingImmutableSortedSet<E> extends ImmutableSortedSet<E> {
}
@Override
+ public boolean contains(@Nullable Object object) {
+ return forward.contains(object);
+ }
+
+ @Override
public int size() {
return forward.size();
}
diff --git a/guava/src/com/google/common/collect/DescendingMultiset.java b/guava/src/com/google/common/collect/DescendingMultiset.java
index d83f782..0be951b 100644
--- a/guava/src/com/google/common/collect/DescendingMultiset.java
+++ b/guava/src/com/google/common/collect/DescendingMultiset.java
@@ -17,6 +17,7 @@
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.Comparator;
import java.util.Iterator;
@@ -26,28 +27,28 @@ import java.util.Set;
/**
* A skeleton implementation of a descending multiset. Only needs
* {@code forwardMultiset()} and {@code entryIterator()}.
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible(emulated = true)
-abstract class DescendingMultiset<E> extends ForwardingMultiset<E>
- implements SortedMultiset<E> {
+abstract class DescendingMultiset<E> extends ForwardingMultiset<E> implements SortedMultiset<E> {
abstract SortedMultiset<E> forwardMultiset();
private transient Comparator<? super E> comparator;
- @Override public Comparator<? super E> comparator() {
+ @Override
+ public Comparator<? super E> comparator() {
Comparator<? super E> result = comparator;
if (result == null) {
- return comparator =
- Ordering.from(forwardMultiset().comparator()).<E>reverse();
+ return comparator = Ordering.from(forwardMultiset().comparator()).<E>reverse();
}
return result;
}
private transient NavigableSet<E> elementSet;
- @Override public NavigableSet<E> elementSet() {
+ @Override
+ public NavigableSet<E> elementSet() {
NavigableSet<E> result = elementSet;
if (result == null) {
return elementSet = new SortedMultisets.NavigableElementSet<E>(this);
@@ -55,45 +56,51 @@ abstract class DescendingMultiset<E> extends ForwardingMultiset<E>
return result;
}
- @Override public Entry<E> pollFirstEntry() {
+ @Override
+ public Entry<E> pollFirstEntry() {
return forwardMultiset().pollLastEntry();
}
- @Override public Entry<E> pollLastEntry() {
+ @Override
+ public Entry<E> pollLastEntry() {
return forwardMultiset().pollFirstEntry();
}
- @Override public SortedMultiset<E> headMultiset(E toElement,
- BoundType boundType) {
- return forwardMultiset().tailMultiset(toElement, boundType)
- .descendingMultiset();
+ @Override
+ public SortedMultiset<E> headMultiset(E toElement, BoundType boundType) {
+ return forwardMultiset().tailMultiset(toElement, boundType).descendingMultiset();
}
- @Override public SortedMultiset<E> subMultiset(E fromElement,
- BoundType fromBoundType, E toElement, BoundType toBoundType) {
- return forwardMultiset().subMultiset(toElement, toBoundType, fromElement,
- fromBoundType).descendingMultiset();
+ @Override
+ public SortedMultiset<E> subMultiset(
+ E fromElement, BoundType fromBoundType, E toElement, BoundType toBoundType) {
+ return forwardMultiset()
+ .subMultiset(toElement, toBoundType, fromElement, fromBoundType)
+ .descendingMultiset();
}
- @Override public SortedMultiset<E> tailMultiset(E fromElement,
- BoundType boundType) {
- return forwardMultiset().headMultiset(fromElement, boundType)
- .descendingMultiset();
+ @Override
+ public SortedMultiset<E> tailMultiset(E fromElement, BoundType boundType) {
+ return forwardMultiset().headMultiset(fromElement, boundType).descendingMultiset();
}
- @Override protected Multiset<E> delegate() {
+ @Override
+ protected Multiset<E> delegate() {
return forwardMultiset();
}
- @Override public SortedMultiset<E> descendingMultiset() {
+ @Override
+ public SortedMultiset<E> descendingMultiset() {
return forwardMultiset();
}
- @Override public Entry<E> firstEntry() {
+ @Override
+ public Entry<E> firstEntry() {
return forwardMultiset().lastEntry();
}
- @Override public Entry<E> lastEntry() {
+ @Override
+ public Entry<E> lastEntry() {
return forwardMultiset().firstEntry();
}
@@ -101,40 +108,50 @@ abstract class DescendingMultiset<E> extends ForwardingMultiset<E>
private transient Set<Entry<E>> entrySet;
- @Override public Set<Entry<E>> entrySet() {
+ @Override
+ public Set<Entry<E>> entrySet() {
Set<Entry<E>> result = entrySet;
return (result == null) ? entrySet = createEntrySet() : result;
}
Set<Entry<E>> createEntrySet() {
- return new Multisets.EntrySet<E>() {
- @Override Multiset<E> multiset() {
+ @WeakOuter
+ class EntrySetImpl extends Multisets.EntrySet<E> {
+ @Override
+ Multiset<E> multiset() {
return DescendingMultiset.this;
}
- @Override public Iterator<Entry<E>> iterator() {
+ @Override
+ public Iterator<Entry<E>> iterator() {
return entryIterator();
}
- @Override public int size() {
+ @Override
+ public int size() {
return forwardMultiset().entrySet().size();
}
- };
+ }
+ return new EntrySetImpl();
}
- @Override public Iterator<E> iterator() {
+ @Override
+ public Iterator<E> iterator() {
return Multisets.iteratorImpl(this);
}
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
return standardToArray();
}
- @Override public <T> T[] toArray(T[] array) {
+ @Override
+ public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return entrySet().toString();
}
-}
\ No newline at end of file
+}
diff --git a/guava/src/com/google/common/collect/DiscreteDomain.java b/guava/src/com/google/common/collect/DiscreteDomain.java
index 1afdc3a..1f11dcb 100644
--- a/guava/src/com/google/common/collect/DiscreteDomain.java
+++ b/guava/src/com/google/common/collect/DiscreteDomain.java
@@ -35,7 +35,7 @@ import java.util.NoSuchElementException;
* "strings of length 5."
*
* <p>See the Guava User Guide section on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/RangesExplained#Discrete_Domains">
+ * "https://github.com/google/guava/wiki/RangesExplained#discrete-domains">
* {@code DiscreteDomain}</a>.
*
* @author Kevin Bourrillion
@@ -47,36 +47,40 @@ public abstract class DiscreteDomain<C extends Comparable> {
/**
* Returns the discrete domain for values of type {@code Integer}.
- *
+ *
* @since 14.0 (since 10.0 as {@code DiscreteDomains.integers()})
*/
public static DiscreteDomain<Integer> integers() {
return IntegerDomain.INSTANCE;
}
- private static final class IntegerDomain extends DiscreteDomain<Integer>
- implements Serializable {
+ private static final class IntegerDomain extends DiscreteDomain<Integer> implements Serializable {
private static final IntegerDomain INSTANCE = new IntegerDomain();
- @Override public Integer next(Integer value) {
+ @Override
+ public Integer next(Integer value) {
int i = value;
return (i == Integer.MAX_VALUE) ? null : i + 1;
}
- @Override public Integer previous(Integer value) {
+ @Override
+ public Integer previous(Integer value) {
int i = value;
return (i == Integer.MIN_VALUE) ? null : i - 1;
}
- @Override public long distance(Integer start, Integer end) {
+ @Override
+ public long distance(Integer start, Integer end) {
return (long) end - start;
}
- @Override public Integer minValue() {
+ @Override
+ public Integer minValue() {
return Integer.MIN_VALUE;
}
- @Override public Integer maxValue() {
+ @Override
+ public Integer maxValue() {
return Integer.MAX_VALUE;
}
@@ -94,28 +98,30 @@ public abstract class DiscreteDomain<C extends Comparable> {
/**
* Returns the discrete domain for values of type {@code Long}.
- *
+ *
* @since 14.0 (since 10.0 as {@code DiscreteDomains.longs()})
*/
public static DiscreteDomain<Long> longs() {
return LongDomain.INSTANCE;
}
- private static final class LongDomain extends DiscreteDomain<Long>
- implements Serializable {
+ private static final class LongDomain extends DiscreteDomain<Long> implements Serializable {
private static final LongDomain INSTANCE = new LongDomain();
- @Override public Long next(Long value) {
+ @Override
+ public Long next(Long value) {
long l = value;
return (l == Long.MAX_VALUE) ? null : l + 1;
}
- @Override public Long previous(Long value) {
+ @Override
+ public Long previous(Long value) {
long l = value;
return (l == Long.MIN_VALUE) ? null : l - 1;
}
- @Override public long distance(Long start, Long end) {
+ @Override
+ public long distance(Long start, Long end) {
long result = end - start;
if (end > start && result < 0) { // overflow
return Long.MAX_VALUE;
@@ -126,11 +132,13 @@ public abstract class DiscreteDomain<C extends Comparable> {
return result;
}
- @Override public Long minValue() {
+ @Override
+ public Long minValue() {
return Long.MIN_VALUE;
}
- @Override public Long maxValue() {
+ @Override
+ public Long maxValue() {
return Long.MAX_VALUE;
}
@@ -145,7 +153,7 @@ public abstract class DiscreteDomain<C extends Comparable> {
private static final long serialVersionUID = 0;
}
-
+
/**
* Returns the discrete domain for values of type {@code BigInteger}.
*
@@ -159,21 +167,26 @@ public abstract class DiscreteDomain<C extends Comparable> {
implements Serializable {
private static final BigIntegerDomain INSTANCE = new BigIntegerDomain();
- private static final BigInteger MIN_LONG =
- BigInteger.valueOf(Long.MIN_VALUE);
- private static final BigInteger MAX_LONG =
- BigInteger.valueOf(Long.MAX_VALUE);
+ private static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE);
+ private static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
- @Override public BigInteger next(BigInteger value) {
+ @Override
+ public BigInteger next(BigInteger value) {
return value.add(BigInteger.ONE);
}
- @Override public BigInteger previous(BigInteger value) {
+ @Override
+ public BigInteger previous(BigInteger value) {
return value.subtract(BigInteger.ONE);
}
- @Override public long distance(BigInteger start, BigInteger end) {
- return end.subtract(start).max(MIN_LONG).min(MAX_LONG).longValue();
+ @Override
+ public long distance(BigInteger start, BigInteger end) {
+ return end
+ .subtract(start)
+ .max(MIN_LONG)
+ .min(MAX_LONG)
+ .longValue();
}
private Object readResolve() {
@@ -187,7 +200,7 @@ public abstract class DiscreteDomain<C extends Comparable> {
private static final long serialVersionUID = 0;
}
-
+
/** Constructor for use by subclasses. */
protected DiscreteDomain() {}
@@ -259,5 +272,4 @@ public abstract class DiscreteDomain<C extends Comparable> {
public C maxValue() {
throw new NoSuchElementException();
}
-
}
diff --git a/guava/src/com/google/common/collect/EmptyContiguousSet.java b/guava/src/com/google/common/collect/EmptyContiguousSet.java
index 4546349..2c08e69 100644
--- a/guava/src/com/google/common/collect/EmptyContiguousSet.java
+++ b/guava/src/com/google/common/collect/EmptyContiguousSet.java
@@ -10,7 +10,7 @@
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
-*/
+ */
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
@@ -34,74 +34,96 @@ final class EmptyContiguousSet<C extends Comparable> extends ContiguousSet<C> {
super(domain);
}
- @Override public C first() {
+ @Override
+ public C first() {
throw new NoSuchElementException();
}
- @Override public C last() {
+ @Override
+ public C last() {
throw new NoSuchElementException();
}
- @Override public int size() {
+ @Override
+ public int size() {
return 0;
}
- @Override public ContiguousSet<C> intersection(ContiguousSet<C> other) {
+ @Override
+ public ContiguousSet<C> intersection(ContiguousSet<C> other) {
return this;
}
- @Override public Range<C> range() {
+ @Override
+ public Range<C> range() {
throw new NoSuchElementException();
}
- @Override public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
+ @Override
+ public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
throw new NoSuchElementException();
}
- @Override ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
+ @Override
+ ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
return this;
}
- @Override ContiguousSet<C> subSetImpl(
+ @Override
+ ContiguousSet<C> subSetImpl(
C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
return this;
}
- @Override ContiguousSet<C> tailSetImpl(C fromElement, boolean fromInclusive) {
+ @Override
+ ContiguousSet<C> tailSetImpl(C fromElement, boolean fromInclusive) {
return this;
}
+ @Override
+ public boolean contains(Object object) {
+ return false;
+ }
+
@GwtIncompatible("not used by GWT emulation")
- @Override int indexOf(Object target) {
+ @Override
+ int indexOf(Object target) {
return -1;
}
- @Override public UnmodifiableIterator<C> iterator() {
+ @Override
+ public UnmodifiableIterator<C> iterator() {
return Iterators.emptyIterator();
}
@GwtIncompatible("NavigableSet")
- @Override public UnmodifiableIterator<C> descendingIterator() {
+ @Override
+ public UnmodifiableIterator<C> descendingIterator() {
return Iterators.emptyIterator();
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return false;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return true;
}
- @Override public ImmutableList<C> asList() {
+ @Override
+ public ImmutableList<C> asList() {
return ImmutableList.of();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "[]";
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object instanceof Set) {
Set<?> that = (Set<?>) object;
return that.isEmpty();
@@ -109,7 +131,14 @@ final class EmptyContiguousSet<C extends Comparable> extends ContiguousSet<C> {
return false;
}
- @Override public int hashCode() {
+ @GwtIncompatible("not used in GWT")
+ @Override
+ boolean isHashCodeFast() {
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
return 0;
}
@@ -136,6 +165,6 @@ final class EmptyContiguousSet<C extends Comparable> extends ContiguousSet<C> {
@GwtIncompatible("NavigableSet")
ImmutableSortedSet<C> createDescendingSet() {
- return new EmptyImmutableSortedSet<C>(Ordering.natural().reverse());
+ return ImmutableSortedSet.emptySet(Ordering.natural().reverse());
}
}
diff --git a/guava/src/com/google/common/collect/EmptyImmutableBiMap.java b/guava/src/com/google/common/collect/EmptyImmutableBiMap.java
deleted file mode 100644
index bc08588..0000000
--- a/guava/src/com/google/common/collect/EmptyImmutableBiMap.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2008 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.collect;
-
-import com.google.common.annotations.GwtCompatible;
-
-import javax.annotation.Nullable;
-
-/**
- * Bimap with no mappings.
- *
- * @author Jared Levy
- */
- at GwtCompatible(emulated = true)
- at SuppressWarnings("serial") // uses writeReplace(), not default serialization
-final class EmptyImmutableBiMap extends ImmutableBiMap<Object, Object> {
- static final EmptyImmutableBiMap INSTANCE = new EmptyImmutableBiMap();
-
- private EmptyImmutableBiMap() {}
-
- @Override public ImmutableBiMap<Object, Object> inverse() {
- return this;
- }
-
- @Override
- public int size() {
- return 0;
- }
-
- @Override
- public boolean isEmpty() {
- return true;
- }
-
- @Override
- public Object get(@Nullable Object key) {
- return null;
- }
-
- @Override
- public ImmutableSet<Entry<Object, Object>> entrySet() {
- return ImmutableSet.of();
- }
-
- @Override
- ImmutableSet<Entry<Object, Object>> createEntrySet() {
- throw new AssertionError("should never be called");
- }
-
- @Override
- public ImmutableSetMultimap<Object, Object> asMultimap() {
- return ImmutableSetMultimap.of();
- }
-
- @Override
- public ImmutableSet<Object> keySet() {
- return ImmutableSet.of();
- }
-
- @Override
- boolean isPartialView() {
- return false;
- }
-
- Object readResolve() {
- return INSTANCE; // preserve singleton property
- }
-}
diff --git a/guava/src/com/google/common/collect/EmptyImmutableListMultimap.java b/guava/src/com/google/common/collect/EmptyImmutableListMultimap.java
index 2a6836d..9b167fb 100644
--- a/guava/src/com/google/common/collect/EmptyImmutableListMultimap.java
+++ b/guava/src/com/google/common/collect/EmptyImmutableListMultimap.java
@@ -25,8 +25,7 @@ import com.google.common.annotations.GwtCompatible;
*/
@GwtCompatible(serializable = true)
class EmptyImmutableListMultimap extends ImmutableListMultimap<Object, Object> {
- static final EmptyImmutableListMultimap INSTANCE
- = new EmptyImmutableListMultimap();
+ static final EmptyImmutableListMultimap INSTANCE = new EmptyImmutableListMultimap();
private EmptyImmutableListMultimap() {
super(ImmutableMap.<Object, ImmutableList<Object>>of(), 0);
diff --git a/guava/src/com/google/common/collect/EmptyImmutableSet.java b/guava/src/com/google/common/collect/EmptyImmutableSet.java
deleted file mode 100644
index c808ec5..0000000
--- a/guava/src/com/google/common/collect/EmptyImmutableSet.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2007 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.collect;
-
-import com.google.common.annotations.GwtCompatible;
-
-import java.util.Collection;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-/**
- * An empty immutable set.
- *
- * @author Kevin Bourrillion
- */
- at GwtCompatible(serializable = true, emulated = true)
-final class EmptyImmutableSet extends ImmutableSet<Object> {
- static final EmptyImmutableSet INSTANCE = new EmptyImmutableSet();
-
- private EmptyImmutableSet() {}
-
- @Override
- public int size() {
- return 0;
- }
-
- @Override public boolean isEmpty() {
- return true;
- }
-
- @Override public boolean contains(@Nullable Object target) {
- return false;
- }
-
- @Override public boolean containsAll(Collection<?> targets) {
- return targets.isEmpty();
- }
-
- @Override public UnmodifiableIterator<Object> iterator() {
- return Iterators.emptyIterator();
- }
-
- @Override boolean isPartialView() {
- return false;
- }
-
- @Override
- int copyIntoArray(Object[] dst, int offset) {
- return offset;
- }
-
- @Override
- public ImmutableList<Object> asList() {
- return ImmutableList.of();
- }
-
- @Override public boolean equals(@Nullable Object object) {
- if (object instanceof Set) {
- Set<?> that = (Set<?>) object;
- return that.isEmpty();
- }
- return false;
- }
-
- @Override public final int hashCode() {
- return 0;
- }
-
- @Override boolean isHashCodeFast() {
- return true;
- }
-
- @Override public String toString() {
- return "[]";
- }
-
- Object readResolve() {
- return INSTANCE; // preserve singleton property
- }
-
- private static final long serialVersionUID = 0;
-}
diff --git a/guava/src/com/google/common/collect/EmptyImmutableSetMultimap.java b/guava/src/com/google/common/collect/EmptyImmutableSetMultimap.java
index 810de3c..ec2ce2e 100644
--- a/guava/src/com/google/common/collect/EmptyImmutableSetMultimap.java
+++ b/guava/src/com/google/common/collect/EmptyImmutableSetMultimap.java
@@ -25,8 +25,7 @@ import com.google.common.annotations.GwtCompatible;
*/
@GwtCompatible(serializable = true)
class EmptyImmutableSetMultimap extends ImmutableSetMultimap<Object, Object> {
- static final EmptyImmutableSetMultimap INSTANCE
- = new EmptyImmutableSetMultimap();
+ static final EmptyImmutableSetMultimap INSTANCE = new EmptyImmutableSetMultimap();
private EmptyImmutableSetMultimap() {
super(ImmutableMap.<Object, ImmutableSet<Object>>of(), 0, null);
diff --git a/guava/src/com/google/common/collect/EmptyImmutableSortedMap.java b/guava/src/com/google/common/collect/EmptyImmutableSortedMap.java
deleted file mode 100644
index 3734851..0000000
--- a/guava/src/com/google/common/collect/EmptyImmutableSortedMap.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2012 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.google.common.collect;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.common.annotations.GwtCompatible;
-
-import java.util.Comparator;
-
-import javax.annotation.Nullable;
-
-/**
- * An empty immutable sorted map.
- *
- * @author Louis Wasserman
- */
- at GwtCompatible(emulated = true)
- at SuppressWarnings("serial") // uses writeReplace, not default serialization
-final class EmptyImmutableSortedMap<K, V> extends ImmutableSortedMap<K, V> {
- private final transient ImmutableSortedSet<K> keySet;
-
- EmptyImmutableSortedMap(Comparator<? super K> comparator) {
- this.keySet = ImmutableSortedSet.emptySet(comparator);
- }
-
- EmptyImmutableSortedMap(
- Comparator<? super K> comparator, ImmutableSortedMap<K, V> descendingMap) {
- super(descendingMap);
- this.keySet = ImmutableSortedSet.emptySet(comparator);
- }
-
- @Override
- public V get(@Nullable Object key) {
- return null;
- }
-
- @Override
- public ImmutableSortedSet<K> keySet() {
- return keySet;
- }
-
- @Override
- public int size() {
- return 0;
- }
-
- @Override
- public boolean isEmpty() {
- return true;
- }
-
- @Override
- public ImmutableCollection<V> values() {
- return ImmutableList.of();
- }
-
- @Override
- public String toString() {
- return "{}";
- }
-
- @Override
- boolean isPartialView() {
- return false;
- }
-
- @Override
- public ImmutableSet<Entry<K, V>> entrySet() {
- return ImmutableSet.of();
- }
-
- @Override
- ImmutableSet<Entry<K, V>> createEntrySet() {
- throw new AssertionError("should never be called");
- }
-
- @Override
- public ImmutableSetMultimap<K, V> asMultimap() {
- return ImmutableSetMultimap.of();
- }
-
- @Override
- public ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive) {
- checkNotNull(toKey);
- return this;
- }
-
- @Override
- public ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive) {
- checkNotNull(fromKey);
- return this;
- }
-
- @Override
- ImmutableSortedMap<K, V> createDescendingMap() {
- return new EmptyImmutableSortedMap<K, V>(Ordering.from(comparator()).reverse(), this);
- }
-}
diff --git a/guava/src/com/google/common/collect/EmptyImmutableSortedMultiset.java b/guava/src/com/google/common/collect/EmptyImmutableSortedMultiset.java
deleted file mode 100644
index 6140f5f..0000000
--- a/guava/src/com/google/common/collect/EmptyImmutableSortedMultiset.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2011 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.google.common.collect;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Collection;
-import java.util.Comparator;
-
-import javax.annotation.Nullable;
-
-/**
- * An empty immutable sorted multiset.
- *
- * @author Louis Wasserman
- */
- at SuppressWarnings("serial") // Uses writeReplace, not default serialization
-final class EmptyImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E> {
- private final ImmutableSortedSet<E> elementSet;
-
- EmptyImmutableSortedMultiset(Comparator<? super E> comparator) {
- this.elementSet = ImmutableSortedSet.emptySet(comparator);
- }
-
- @Override
- public Entry<E> firstEntry() {
- return null;
- }
-
- @Override
- public Entry<E> lastEntry() {
- return null;
- }
-
- @Override
- public int count(@Nullable Object element) {
- return 0;
- }
-
- @Override
- public boolean containsAll(Collection<?> targets) {
- return targets.isEmpty();
- }
-
- @Override
- public int size() {
- return 0;
- }
-
- @Override
- public ImmutableSortedSet<E> elementSet() {
- return elementSet;
- }
-
- @Override
- Entry<E> getEntry(int index) {
- throw new AssertionError("should never be called");
- }
-
- @Override
- public ImmutableSortedMultiset<E> headMultiset(E upperBound, BoundType boundType) {
- checkNotNull(upperBound);
- checkNotNull(boundType);
- return this;
- }
-
- @Override
- public ImmutableSortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
- checkNotNull(lowerBound);
- checkNotNull(boundType);
- return this;
- }
-
- @Override
- public UnmodifiableIterator<E> iterator() {
- return Iterators.emptyIterator();
- }
-
- @Override
- public boolean equals(@Nullable Object object) {
- if (object instanceof Multiset) {
- Multiset<?> other = (Multiset<?>) object;
- return other.isEmpty();
- }
- return false;
- }
-
- @Override
- boolean isPartialView() {
- return false;
- }
-
- @Override
- int copyIntoArray(Object[] dst, int offset) {
- return offset;
- }
-
- @Override
- public ImmutableList<E> asList() {
- return ImmutableList.of();
- }
-}
diff --git a/guava/src/com/google/common/collect/EmptyImmutableSortedSet.java b/guava/src/com/google/common/collect/EmptyImmutableSortedSet.java
deleted file mode 100644
index c4d5a78..0000000
--- a/guava/src/com/google/common/collect/EmptyImmutableSortedSet.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2008 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.collect;
-
-import com.google.common.annotations.GwtCompatible;
-import com.google.common.annotations.GwtIncompatible;
-
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-/**
- * An empty immutable sorted set.
- *
- * @author Jared Levy
- */
- at GwtCompatible(serializable = true, emulated = true)
- at SuppressWarnings("serial") // uses writeReplace(), not default serialization
-class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
- EmptyImmutableSortedSet(Comparator<? super E> comparator) {
- super(comparator);
- }
-
- @Override
- public int size() {
- return 0;
- }
-
- @Override public boolean isEmpty() {
- return true;
- }
-
- @Override public boolean contains(@Nullable Object target) {
- return false;
- }
-
- @Override public boolean containsAll(Collection<?> targets) {
- return targets.isEmpty();
- }
-
- @Override public UnmodifiableIterator<E> iterator() {
- return Iterators.emptyIterator();
- }
-
- @GwtIncompatible("NavigableSet")
- @Override public UnmodifiableIterator<E> descendingIterator() {
- return Iterators.emptyIterator();
- }
-
- @Override boolean isPartialView() {
- return false;
- }
-
- @Override public ImmutableList<E> asList() {
- return ImmutableList.of();
- }
-
- @Override
- int copyIntoArray(Object[] dst, int offset) {
- return offset;
- }
-
- @Override public boolean equals(@Nullable Object object) {
- if (object instanceof Set) {
- Set<?> that = (Set<?>) object;
- return that.isEmpty();
- }
- return false;
- }
-
- @Override public int hashCode() {
- return 0;
- }
-
- @Override public String toString() {
- return "[]";
- }
-
- @Override
- public E first() {
- throw new NoSuchElementException();
- }
-
- @Override
- public E last() {
- throw new NoSuchElementException();
- }
-
- @Override
- ImmutableSortedSet<E> headSetImpl(E toElement, boolean inclusive) {
- return this;
- }
-
- @Override
- ImmutableSortedSet<E> subSetImpl(
- E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
- return this;
- }
-
- @Override
- ImmutableSortedSet<E> tailSetImpl(E fromElement, boolean inclusive) {
- return this;
- }
-
- @Override int indexOf(@Nullable Object target) {
- return -1;
- }
-
- @Override
- ImmutableSortedSet<E> createDescendingSet() {
- return new EmptyImmutableSortedSet<E>(Ordering.from(comparator).reverse());
- }
-}
diff --git a/guava/src/com/google/common/collect/EnumBiMap.java b/guava/src/com/google/common/collect/EnumBiMap.java
index 05d84ed..7696ffe 100644
--- a/guava/src/com/google/common/collect/EnumBiMap.java
+++ b/guava/src/com/google/common/collect/EnumBiMap.java
@@ -32,17 +32,16 @@ import java.util.Map;
* A {@code BiMap} backed by two {@code EnumMap} instances. Null keys and values
* are not permitted. An {@code EnumBiMap} and its inverse are both
* serializable.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap">
* {@code BiMap}</a>.
*
* @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
-public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
- extends AbstractBiMap<K, V> {
+public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>> extends AbstractBiMap<K, V> {
private transient Class<K> keyType;
private transient Class<V> valueType;
@@ -53,8 +52,8 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
* @param keyType the key type
* @param valueType the value type
*/
- public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V>
- create(Class<K> keyType, Class<V> valueType) {
+ public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V> create(
+ Class<K> keyType, Class<V> valueType) {
return new EnumBiMap<K, V>(keyType, valueType);
}
@@ -68,15 +67,15 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
* @throws IllegalArgumentException if map is not an {@code EnumBiMap}
* instance and contains no mappings
*/
- public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V>
- create(Map<K, V> map) {
+ public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V> create(Map<K, V> map) {
EnumBiMap<K, V> bimap = create(inferKeyType(map), inferValueType(map));
bimap.putAll(map);
return bimap;
}
private EnumBiMap(Class<K> keyType, Class<V> valueType) {
- super(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
+ super(
+ WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
WellBehavedMap.wrap(new EnumMap<V, K>(valueType)));
this.keyType = keyType;
this.valueType = valueType;
@@ -90,7 +89,11 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
return ((EnumHashBiMap<K, ?>) map).keyType();
}
checkArgument(!map.isEmpty());
- return map.keySet().iterator().next().getDeclaringClass();
+ return map
+ .keySet()
+ .iterator()
+ .next()
+ .getDeclaringClass();
}
private static <V extends Enum<V>> Class<V> inferValueType(Map<?, V> map) {
@@ -98,7 +101,11 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
return ((EnumBiMap<?, V>) map).valueType;
}
checkArgument(!map.isEmpty());
- return map.values().iterator().next().getDeclaringClass();
+ return map
+ .values()
+ .iterator()
+ .next()
+ .getDeclaringClass();
}
/** Returns the associated key type. */
@@ -135,8 +142,7 @@ public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>>
@SuppressWarnings("unchecked") // reading fields populated by writeObject
@GwtIncompatible("java.io.ObjectInputStream")
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
keyType = (Class<K>) stream.readObject();
valueType = (Class<V>) stream.readObject();
diff --git a/guava/src/com/google/common/collect/EnumHashBiMap.java b/guava/src/com/google/common/collect/EnumHashBiMap.java
index c43daf0..566b3fe 100644
--- a/guava/src/com/google/common/collect/EnumHashBiMap.java
+++ b/guava/src/com/google/common/collect/EnumHashBiMap.java
@@ -35,17 +35,16 @@ import javax.annotation.Nullable;
* a {@code HashMap} instance for values-to-keys. Null keys are not permitted,
* but null values are. An {@code EnumHashBiMap} and its inverse are both
* serializable.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap">
* {@code BiMap}</a>.
*
* @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
-public final class EnumHashBiMap<K extends Enum<K>, V>
- extends AbstractBiMap<K, V> {
+public final class EnumHashBiMap<K extends Enum<K>, V> extends AbstractBiMap<K, V> {
private transient Class<K> keyType;
/**
@@ -53,8 +52,7 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
*
* @param keyType the key type
*/
- public static <K extends Enum<K>, V> EnumHashBiMap<K, V>
- create(Class<K> keyType) {
+ public static <K extends Enum<K>, V> EnumHashBiMap<K, V> create(Class<K> keyType) {
return new EnumHashBiMap<K, V>(keyType);
}
@@ -68,18 +66,16 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
* @throws IllegalArgumentException if map is not an {@code EnumBiMap} or an
* {@code EnumHashBiMap} instance and contains no mappings
*/
- public static <K extends Enum<K>, V> EnumHashBiMap<K, V>
- create(Map<K, ? extends V> map) {
+ public static <K extends Enum<K>, V> EnumHashBiMap<K, V> create(Map<K, ? extends V> map) {
EnumHashBiMap<K, V> bimap = create(EnumBiMap.inferKeyType(map));
bimap.putAll(map);
return bimap;
}
private EnumHashBiMap(Class<K> keyType) {
- super(WellBehavedMap.wrap(
- new EnumMap<K, V>(keyType)),
- Maps.<V, K>newHashMapWithExpectedSize(
- keyType.getEnumConstants().length));
+ super(
+ WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
+ Maps.<V, K>newHashMapWithExpectedSize(keyType.getEnumConstants().length));
this.keyType = keyType;
}
@@ -90,11 +86,13 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
return checkNotNull(key);
}
- @Override public V put(K key, @Nullable V value) {
+ @Override
+ public V put(K key, @Nullable V value) {
return super.put(key, value);
}
- @Override public V forcePut(K key, @Nullable V value) {
+ @Override
+ public V forcePut(K key, @Nullable V value) {
return super.forcePut(key, value);
}
@@ -116,11 +114,11 @@ public final class EnumHashBiMap<K extends Enum<K>, V>
@SuppressWarnings("unchecked") // reading field populated by writeObject
@GwtIncompatible("java.io.ObjectInputStream")
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
keyType = (Class<K>) stream.readObject();
- setDelegates(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
+ setDelegates(
+ WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
new HashMap<V, K>(keyType.getEnumConstants().length * 3 / 2));
Serialization.populateMap(this, stream);
}
diff --git a/guava/src/com/google/common/collect/EnumMultiset.java b/guava/src/com/google/common/collect/EnumMultiset.java
index 2bb121c..1ed31a0 100644
--- a/guava/src/com/google/common/collect/EnumMultiset.java
+++ b/guava/src/com/google/common/collect/EnumMultiset.java
@@ -27,13 +27,13 @@ import java.util.Iterator;
/**
* Multiset implementation backed by an {@link EnumMap}.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
* {@code Multiset}</a>.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class EnumMultiset<E extends Enum<E>> extends AbstractMapBasedMultiset<E> {
@@ -58,12 +58,12 @@ public final class EnumMultiset<E extends Enum<E>> extends AbstractMapBasedMulti
Iterables.addAll(multiset, elements);
return multiset;
}
-
+
/**
* Returns a new {@code EnumMultiset} instance containing the given elements. Unlike
* {@link EnumMultiset#create(Iterable)}, this method does not produce an exception on an empty
* iterable.
- *
+ *
* @since 14.0
*/
public static <E extends Enum<E>> EnumMultiset<E> create(Iterable<E> elements, Class<E> type) {
diff --git a/guava/src/com/google/common/collect/EvictingQueue.java b/guava/src/com/google/common/collect/EvictingQueue.java
index c124a0c..56eaffc 100644
--- a/guava/src/com/google/common/collect/EvictingQueue.java
+++ b/guava/src/com/google/common/collect/EvictingQueue.java
@@ -20,17 +20,17 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
-import com.google.common.annotations.GwtIncompatible;
+import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.VisibleForTesting;
import java.io.Serializable;
-import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Queue;
/**
* A non-blocking queue which automatically evicts elements from the head of the queue when
- * attempting to add new elements onto the queue and it is full.
+ * attempting to add new elements onto the queue and it is full. This data structure is logically
+ * equivalent to a circular buffer (i.e., cyclic buffer or ring buffer).
*
* <p>An evicting queue must be configured with a maximum size. Each time an element is added
* to a full queue, the queue automatically removes its head element. This is different from
@@ -42,17 +42,16 @@ import java.util.Queue;
* @since 15.0
*/
@Beta
- at GwtIncompatible("java.util.ArrayDeque")
+ at GwtCompatible
public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serializable {
private final Queue<E> delegate;
- @VisibleForTesting
- final int maxSize;
+ @VisibleForTesting final int maxSize;
private EvictingQueue(int maxSize) {
checkArgument(maxSize >= 0, "maxSize (%s) must >= 0", maxSize);
- this.delegate = new ArrayDeque<E>(maxSize);
+ this.delegate = Platform.newFastestQueue(maxSize);
this.maxSize = maxSize;
}
@@ -76,7 +75,8 @@ public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serial
return maxSize - size();
}
- @Override protected Queue<E> delegate() {
+ @Override
+ protected Queue<E> delegate() {
return delegate;
}
@@ -86,7 +86,8 @@ public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serial
*
* @return {@code true} always
*/
- @Override public boolean offer(E e) {
+ @Override
+ public boolean offer(E e) {
return add(e);
}
@@ -96,8 +97,9 @@ public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serial
*
* @return {@code true} always
*/
- @Override public boolean add(E e) {
- checkNotNull(e); // check before removing
+ @Override
+ public boolean add(E e) {
+ checkNotNull(e); // check before removing
if (maxSize == 0) {
return true;
}
@@ -108,7 +110,8 @@ public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serial
return true;
}
- @Override public boolean addAll(Collection<? extends E> collection) {
+ @Override
+ public boolean addAll(Collection<? extends E> collection) {
return standardAddAll(collection);
}
@@ -122,7 +125,7 @@ public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serial
return delegate().remove(checkNotNull(object));
}
- // TODO(user): Do we want to checkNotNull each element in containsAll, removeAll, and retainAll?
+ // TODO(kak): Do we want to checkNotNull each element in containsAll, removeAll, and retainAll?
private static final long serialVersionUID = 0L;
}
diff --git a/guava/src/com/google/common/collect/ExplicitOrdering.java b/guava/src/com/google/common/collect/ExplicitOrdering.java
index 0a2e181..d31e4a5 100644
--- a/guava/src/com/google/common/collect/ExplicitOrdering.java
+++ b/guava/src/com/google/common/collect/ExplicitOrdering.java
@@ -29,14 +29,15 @@ final class ExplicitOrdering<T> extends Ordering<T> implements Serializable {
final ImmutableMap<T, Integer> rankMap;
ExplicitOrdering(List<T> valuesInOrder) {
- this(buildRankMap(valuesInOrder));
+ this(Maps.indexMap(valuesInOrder));
}
ExplicitOrdering(ImmutableMap<T, Integer> rankMap) {
this.rankMap = rankMap;
}
- @Override public int compare(T left, T right) {
+ @Override
+ public int compare(T left, T right) {
return rank(left) - rank(right); // safe because both are nonnegative
}
@@ -48,17 +49,8 @@ final class ExplicitOrdering<T> extends Ordering<T> implements Serializable {
return rank;
}
- private static <T> ImmutableMap<T, Integer> buildRankMap(
- List<T> valuesInOrder) {
- ImmutableMap.Builder<T, Integer> builder = ImmutableMap.builder();
- int rank = 0;
- for (T value : valuesInOrder) {
- builder.put(value, rank++);
- }
- return builder.build();
- }
-
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object instanceof ExplicitOrdering) {
ExplicitOrdering<?> that = (ExplicitOrdering<?>) object;
return this.rankMap.equals(that.rankMap);
@@ -66,11 +58,13 @@ final class ExplicitOrdering<T> extends Ordering<T> implements Serializable {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return rankMap.hashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Ordering.explicit(" + rankMap.keySet() + ")";
}
diff --git a/guava/src/com/google/common/collect/FilteredEntryMultimap.java b/guava/src/com/google/common/collect/FilteredEntryMultimap.java
index ebc3d4b..261c9a5 100644
--- a/guava/src/com/google/common/collect/FilteredEntryMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredEntryMultimap.java
@@ -24,7 +24,8 @@ import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.MoreObjects;
import com.google.common.base.Predicate;
-import com.google.common.collect.Maps.ImprovedAbstractMap;
+import com.google.common.collect.Maps.ViewCachingAbstractMap;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.Collection;
import java.util.Collections;
@@ -38,7 +39,7 @@ import javax.annotation.Nullable;
/**
* Implementation of {@link Multimaps#filterEntries(Multimap, Predicate)}.
- *
+ *
* @author Jared Levy
* @author Louis Wasserman
*/
@@ -51,7 +52,7 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
this.unfiltered = checkNotNull(unfiltered);
this.predicate = checkNotNull(predicate);
}
-
+
@Override
public Multimap<K, V> unfiltered() {
return unfiltered;
@@ -70,7 +71,6 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
private boolean satisfies(K key, V value) {
return predicate.apply(Maps.immutableEntry(key, value));
}
-
final class ValuePredicate implements Predicate<V> {
private final K key;
@@ -106,8 +106,8 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
Collection<V> unmodifiableEmptyCollection() {
// These return false, rather than throwing a UOE, on remove calls.
- return (unfiltered instanceof SetMultimap)
- ? Collections.<V>emptySet()
+ return (unfiltered instanceof SetMultimap)
+ ? Collections.<V>emptySet()
: Collections.<V>emptyList();
}
@@ -125,7 +125,7 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
Collection<Entry<K, V>> createEntries() {
return filterCollection(unfiltered.entries(), predicate);
}
-
+
@Override
Collection<V> createValues() {
return new FilteredMultimapValues<K, V>(this);
@@ -140,12 +140,12 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
Map<K, Collection<V>> createAsMap() {
return new AsMap();
}
-
+
@Override
public Set<K> keySet() {
return asMap().keySet();
}
-
+
boolean removeEntriesIf(Predicate<? super Entry<K, Collection<V>>> predicate) {
Iterator<Entry<K, Collection<V>>> entryIterator = unfiltered.asMap().entrySet().iterator();
boolean changed = false;
@@ -164,8 +164,9 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
}
return changed;
}
-
- class AsMap extends ImprovedAbstractMap<K, Collection<V>> {
+
+ @WeakOuter
+ class AsMap extends ViewCachingAbstractMap<K, Collection<V>> {
@Override
public boolean containsKey(@Nullable Object key) {
return get(key) != null;
@@ -187,7 +188,7 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
result = filterCollection(result, new ValuePredicate(k));
return result.isEmpty() ? null : result;
}
-
+
@Override
public Collection<V> remove(@Nullable Object key) {
Collection<V> collection = unfiltered.asMap().get(key);
@@ -213,10 +214,15 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
return Collections.unmodifiableList(result);
}
}
-
+
@Override
Set<K> createKeySet() {
- return new Maps.KeySet<K, Collection<V>>(this) {
+ @WeakOuter
+ class KeySetImpl extends Maps.KeySet<K, Collection<V>> {
+ KeySetImpl() {
+ super(AsMap.this);
+ }
+
@Override
public boolean removeAll(Collection<?> c) {
return removeEntriesIf(Maps.<K>keyPredicateOnEntries(in(c)));
@@ -231,12 +237,14 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
public boolean remove(@Nullable Object o) {
return AsMap.this.remove(o) != null;
}
- };
+ }
+ return new KeySetImpl();
}
@Override
Set<Entry<K, Collection<V>>> createEntrySet() {
- return new Maps.EntrySet<K, Collection<V>>() {
+ @WeakOuter
+ class EntrySetImpl extends Maps.EntrySet<K, Collection<V>> {
@Override
Map<K, Collection<V>> map() {
return AsMap.this;
@@ -245,16 +253,16 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
@Override
public Iterator<Entry<K, Collection<V>>> iterator() {
return new AbstractIterator<Entry<K, Collection<V>>>() {
- final Iterator<Entry<K, Collection<V>>> backingIterator
- = unfiltered.asMap().entrySet().iterator();
+ final Iterator<Entry<K, Collection<V>>> backingIterator =
+ unfiltered.asMap().entrySet().iterator();
@Override
protected Entry<K, Collection<V>> computeNext() {
while (backingIterator.hasNext()) {
Entry<K, Collection<V>> entry = backingIterator.next();
K key = entry.getKey();
- Collection<V> collection
- = filterCollection(entry.getValue(), new ValuePredicate(key));
+ Collection<V> collection =
+ filterCollection(entry.getValue(), new ValuePredicate(key));
if (!collection.isEmpty()) {
return Maps.immutableEntry(key, collection);
}
@@ -273,28 +281,34 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
public boolean retainAll(Collection<?> c) {
return removeEntriesIf(not(in(c)));
}
-
+
@Override
public int size() {
return Iterators.size(iterator());
}
- };
+ }
+ return new EntrySetImpl();
}
-
+
@Override
Collection<Collection<V>> createValues() {
- return new Maps.Values<K, Collection<V>>(AsMap.this) {
+ @WeakOuter
+ class ValuesImpl extends Maps.Values<K, Collection<V>> {
+ ValuesImpl() {
+ super(AsMap.this);
+ }
+
@Override
public boolean remove(@Nullable Object o) {
if (o instanceof Collection) {
Collection<?> c = (Collection<?>) o;
- Iterator<Entry<K, Collection<V>>> entryIterator
- = unfiltered.asMap().entrySet().iterator();
+ Iterator<Entry<K, Collection<V>>> entryIterator =
+ unfiltered.asMap().entrySet().iterator();
while (entryIterator.hasNext()) {
Entry<K, Collection<V>> entry = entryIterator.next();
K key = entry.getKey();
- Collection<V> collection
- = filterCollection(entry.getValue(), new ValuePredicate(key));
+ Collection<V> collection =
+ filterCollection(entry.getValue(), new ValuePredicate(key));
if (!collection.isEmpty() && c.equals(collection)) {
if (collection.size() == entry.getValue().size()) {
entryIterator.remove();
@@ -317,15 +331,17 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
public boolean retainAll(Collection<?> c) {
return removeEntriesIf(Maps.<Collection<V>>valuePredicateOnEntries(not(in(c))));
}
- };
+ }
+ return new ValuesImpl();
}
}
-
+
@Override
Multiset<K> createKeys() {
return new Keys();
}
-
+
+ @WeakOuter
class Keys extends Multimaps.Keys<K, V> {
Keys() {
super(FilteredEntryMultimap.this);
@@ -375,23 +391,24 @@ class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements Filt
public int size() {
return FilteredEntryMultimap.this.keySet().size();
}
-
+
private boolean removeEntriesIf(final Predicate<? super Multiset.Entry<K>> predicate) {
- return FilteredEntryMultimap.this.removeEntriesIf(
- new Predicate<Map.Entry<K, Collection<V>>>() {
- @Override
- public boolean apply(Map.Entry<K, Collection<V>> entry) {
- return predicate.apply(
- Multisets.immutableEntry(entry.getKey(), entry.getValue().size()));
- }
- });
+ return FilteredEntryMultimap.this
+ .removeEntriesIf(
+ new Predicate<Map.Entry<K, Collection<V>>>() {
+ @Override
+ public boolean apply(Map.Entry<K, Collection<V>> entry) {
+ return predicate.apply(
+ Multisets.immutableEntry(entry.getKey(), entry.getValue().size()));
+ }
+ });
}
-
+
@Override
public boolean removeAll(Collection<?> c) {
return removeEntriesIf(in(c));
}
-
+
@Override
public boolean retainAll(Collection<?> c) {
return removeEntriesIf(not(in(c)));
diff --git a/guava/src/com/google/common/collect/FilteredEntrySetMultimap.java b/guava/src/com/google/common/collect/FilteredEntrySetMultimap.java
index 2e12937..674144c 100644
--- a/guava/src/com/google/common/collect/FilteredEntrySetMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredEntrySetMultimap.java
@@ -24,7 +24,7 @@ import java.util.Set;
/**
* Implementation of {@link Multimaps#filterEntries(SetMultimap, Predicate)}.
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible
@@ -34,7 +34,7 @@ final class FilteredEntrySetMultimap<K, V> extends FilteredEntryMultimap<K, V>
FilteredEntrySetMultimap(SetMultimap<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
super(unfiltered, predicate);
}
-
+
@Override
public SetMultimap<K, V> unfiltered() {
return (SetMultimap<K, V>) unfiltered;
@@ -44,7 +44,7 @@ final class FilteredEntrySetMultimap<K, V> extends FilteredEntryMultimap<K, V>
public Set<V> get(K key) {
return (Set<V>) super.get(key);
}
-
+
@Override
public Set<V> removeAll(Object key) {
return (Set<V>) super.removeAll(key);
diff --git a/guava/src/com/google/common/collect/FilteredKeyListMultimap.java b/guava/src/com/google/common/collect/FilteredKeyListMultimap.java
index bf4b8da..27041aa 100644
--- a/guava/src/com/google/common/collect/FilteredKeyListMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredKeyListMultimap.java
@@ -25,11 +25,11 @@ import javax.annotation.Nullable;
/**
* Implementation of {@link Multimaps#filterKeys(ListMultimap, Predicate)}.
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible
-final class FilteredKeyListMultimap<K, V> extends FilteredKeyMultimap<K, V>
+final class FilteredKeyListMultimap<K, V> extends FilteredKeyMultimap<K, V>
implements ListMultimap<K, V> {
FilteredKeyListMultimap(ListMultimap<K, V> unfiltered, Predicate<? super K> keyPredicate) {
super(unfiltered, keyPredicate);
diff --git a/guava/src/com/google/common/collect/FilteredKeyMultimap.java b/guava/src/com/google/common/collect/FilteredKeyMultimap.java
index 3788b72..027169f 100644
--- a/guava/src/com/google/common/collect/FilteredKeyMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredKeyMultimap.java
@@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkPositionIndex;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Predicate;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.Collection;
import java.util.Collections;
@@ -180,6 +181,7 @@ class FilteredKeyMultimap<K, V> extends AbstractMultimap<K, V> implements Filter
return new Entries();
}
+ @WeakOuter
class Entries extends ForwardingCollection<Entry<K, V>> {
@Override
protected Collection<Entry<K, V>> delegate() {
@@ -200,7 +202,7 @@ class FilteredKeyMultimap<K, V> extends AbstractMultimap<K, V> implements Filter
return false;
}
}
-
+
@Override
Collection<V> createValues() {
return new FilteredMultimapValues<K, V>(this);
diff --git a/guava/src/com/google/common/collect/FilteredKeySetMultimap.java b/guava/src/com/google/common/collect/FilteredKeySetMultimap.java
index b8a6a57..29dc133 100644
--- a/guava/src/com/google/common/collect/FilteredKeySetMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredKeySetMultimap.java
@@ -26,7 +26,7 @@ import javax.annotation.Nullable;
/**
* Implementation of {@link Multimaps#filterKeys(SetMultimap, Predicate)}.
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible
@@ -66,13 +66,13 @@ final class FilteredKeySetMultimap<K, V> extends FilteredKeyMultimap<K, V>
Set<Entry<K, V>> createEntries() {
return new EntrySet();
}
-
+
class EntrySet extends Entries implements Set<Entry<K, V>> {
@Override
public int hashCode() {
return Sets.hashCodeImpl(this);
}
-
+
@Override
public boolean equals(@Nullable Object o) {
return Sets.equalsImpl(this, o);
diff --git a/guava/src/com/google/common/collect/FilteredMultimap.java b/guava/src/com/google/common/collect/FilteredMultimap.java
index e97cfdb..22c2b3d 100644
--- a/guava/src/com/google/common/collect/FilteredMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredMultimap.java
@@ -23,11 +23,11 @@ import java.util.Map.Entry;
/**
* An interface for all filtered multimap types.
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible
-interface FilteredMultimap<K, V> extends Multimap<K, V> {
+interface FilteredMultimap<K, V> extends Multimap<K, V> {
Multimap<K, V> unfiltered();
Predicate<? super Entry<K, V>> entryPredicate();
diff --git a/guava/src/com/google/common/collect/FilteredMultimapValues.java b/guava/src/com/google/common/collect/FilteredMultimapValues.java
index ae6f785..c34e92f 100644
--- a/guava/src/com/google/common/collect/FilteredMultimapValues.java
+++ b/guava/src/com/google/common/collect/FilteredMultimapValues.java
@@ -20,6 +20,7 @@ import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
+import com.google.j2objc.annotations.Weak;
import java.util.AbstractCollection;
import java.util.Collection;
@@ -31,12 +32,12 @@ import javax.annotation.Nullable;
/**
* Implementation for {@link FilteredMultimap#values()}.
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible
final class FilteredMultimapValues<K, V> extends AbstractCollection<V> {
- private final FilteredMultimap<K, V> multimap;
+ @Weak private final FilteredMultimap<K, V> multimap;
FilteredMultimapValues(FilteredMultimap<K, V> multimap) {
this.multimap = checkNotNull(multimap);
@@ -73,17 +74,20 @@ final class FilteredMultimapValues<K, V> extends AbstractCollection<V> {
@Override
public boolean removeAll(Collection<?> c) {
- return Iterables.removeIf(multimap.unfiltered().entries(),
+ return Iterables.removeIf(
+ multimap.unfiltered().entries(),
// explicit <Entry<K, V>> is required to build with JDK6
- Predicates.<Entry<K, V>>and(multimap.entryPredicate(),
- Maps.<V>valuePredicateOnEntries(Predicates.in(c))));
+ Predicates.<Entry<K, V>>and(
+ multimap.entryPredicate(), Maps.<V>valuePredicateOnEntries(Predicates.in(c))));
}
@Override
public boolean retainAll(Collection<?> c) {
- return Iterables.removeIf(multimap.unfiltered().entries(),
+ return Iterables.removeIf(
+ multimap.unfiltered().entries(),
// explicit <Entry<K, V>> is required to build with JDK6
- Predicates.<Entry<K, V>>and(multimap.entryPredicate(),
+ Predicates.<Entry<K, V>>and(
+ multimap.entryPredicate(),
Maps.<V>valuePredicateOnEntries(Predicates.not(Predicates.in(c)))));
}
diff --git a/guava/src/com/google/common/collect/FilteredSetMultimap.java b/guava/src/com/google/common/collect/FilteredSetMultimap.java
index 6b73281..a0a149f 100644
--- a/guava/src/com/google/common/collect/FilteredSetMultimap.java
+++ b/guava/src/com/google/common/collect/FilteredSetMultimap.java
@@ -20,7 +20,7 @@ import com.google.common.annotations.GwtCompatible;
/**
* A supertype for filtered {@link SetMultimap} implementations.
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible
diff --git a/guava/src/com/google/common/collect/FluentIterable.java b/guava/src/com/google/common/collect/FluentIterable.java
index e007ef7..59c2a64 100644
--- a/guava/src/com/google/common/collect/FluentIterable.java
+++ b/guava/src/com/google/common/collect/FluentIterable.java
@@ -37,34 +37,72 @@ import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
- * {@code FluentIterable} provides a rich interface for manipulating {@code Iterable} instances in a
- * chained fashion. A {@code FluentIterable} can be created from an {@code Iterable}, or from a set
- * of elements. The following types of methods are provided on {@code FluentIterable}:
+ * An expanded {@code Iterable} API, providing functionality similar to Java 8's powerful <a href=
+ * "https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#package.description"
+ * >streams library</a> in a slightly different way.
+ *
+ * <p>The following types of methods are provided:
+ *
* <ul>
- * <li>chained methods which return a new {@code FluentIterable} based in some way on the contents
- * of the current one (for example {@link #transform})
- * <li>conversion methods which copy the {@code FluentIterable}'s contents into a new collection or
- * array (for example {@link #toList})
+ * <li>chaining methods which return a new {@code FluentIterable} based in some way on the contents
+ * of the current one (for example {@link #transform})
* <li>element extraction methods which facilitate the retrieval of certain elements (for example
- * {@link #last})
+ * {@link #last})
* <li>query methods which answer questions about the {@code FluentIterable}'s contents (for example
- * {@link #anyMatch})
+ * {@link #anyMatch})
+ * <li>conversion methods which copy the {@code FluentIterable}'s contents into a new collection or
+ * array (for example {@link #toList})
* </ul>
*
- * <p>Here is an example that merges the lists returned by two separate database calls, transforms
- * it by invoking {@code toString()} on each element, and returns the first 10 elements as an
- * {@code ImmutableList}: <pre> {@code
+ * <p>Several lesser-used features are currently available only as static methods on the {@link
+ * Iterables} class.
+ *
+ * <a name="streams"></a>
+ * <h3>Comparison to streams</h3>
+ *
+ * <p>Starting with Java 8, the core Java class libraries provide a new "Streams" library (in {@code
+ * java.util.stream}), which is similar to {@code FluentIterable} but generally more powerful. Key
+ * differences include:</b>
+ *
+ * <ul>
+ * <li>A stream is <i>single-use</i>; it becomes invalid as soon as any "terminal operation" such as
+ * {@code findFirst()} or {@code iterator()} is invoked. (Even though {@code Stream} contains
+ * all the right method <i>signatures</i> to implement {@link Iterable}, it does not actually
+ * do so, to avoid implying repeat-iterability.) {@code FluentIterable}, on the other hand, is
+ * multiple-use, and does implement {@link Iterable}.
+ * <li>Streams offer many features not found here, including {@code min/max}, {@code
+ * distinct}, {@code reduce}, {@code sorted}, the very powerful {@code collect}, and built-in
+ * support for parallelizing stream operations.
+ * <li>{@code FluentIterable} contains several features not available on {@code Stream}, which are
+ * noted in the method descriptions below.
+ * <li>Streams include primitive-specialized variants such as {@code IntStream}, the use of which is
+ * strongly recommended.
+ * <li>Streams are standard Java, not requiring a third-party dependency (but do render your code
+ * incompatible with Java 7 and earlier).
+ * </ul>
+ *
+ * <h3>Example</h3>
+ *
+ * <p>Here is an example that accepts a list from a database call, filters it based on a predicate,
+ * transforms it by invoking {@code toString()} on each element, and returns the first 10 elements
+ * as a {@code List}: <pre> {@code
*
- * FluentIterable
- * .from(database.getClientList())
- * .filter(activeInLastMonth())
- * .transform(Functions.toStringFunction())
- * .limit(10)
- * .toList();}</pre>
+ * List<String> results =
+ * FluentIterable.from(database.getClientList())
+ * .filter(activeInLastMonthPredicate)
+ * .transform(Functions.toStringFunction())
+ * .limit(10)
+ * .toList();}</pre>
*
- * <p>Anything which can be done using {@code FluentIterable} could be done in a different fashion
- * (often with {@link Iterables}), however the use of {@code FluentIterable} makes many sets of
- * operations significantly more concise.
+ * The approximate stream equivalent is: <pre> {@code
+ *
+ * List<String> results =
+ * database.getClientList()
+ * .stream()
+ * .filter(activeInLastMonthPredicate)
+ * .map(Functions.toStringFunction())
+ * .limit(10)
+ * .collect(Collectors.toList());}</pre>
*
* @author Marcin Mikosik
* @since 12.0
@@ -87,9 +125,14 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns a fluent iterable that wraps {@code iterable}, or {@code iterable} itself if it
* is already a {@code FluentIterable}.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code iterable.stream()} if {@code iterable} is a
+ * {@link Collection}; {@code StreamSupport.stream(iterable.spliterator(), false)} otherwise.
*/
+ @CheckReturnValue
public static <E> FluentIterable<E> from(final Iterable<E> iterable) {
- return (iterable instanceof FluentIterable) ? (FluentIterable<E>) iterable
+ return (iterable instanceof FluentIterable)
+ ? (FluentIterable<E>) iterable
: new FluentIterable<E>(iterable) {
@Override
public Iterator<E> iterator() {
@@ -107,6 +150,7 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* {@code FluentIterable}
*/
@Deprecated
+ @CheckReturnValue
public static <E> FluentIterable<E> from(FluentIterable<E> iterable) {
return checkNotNull(iterable);
}
@@ -114,9 +158,13 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns a fluent iterable containing {@code elements} in the specified order.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code Stream.of(elements)} or {@code
+ * Arrays.stream(elements)}.
+ *
* @since 18.0
*/
@Beta
+ @CheckReturnValue
public static <E> FluentIterable<E> of(E[] elements) {
return from(Lists.newArrayList(elements));
}
@@ -124,25 +172,35 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns a string representation of this fluent iterable, with the format
* {@code [e1, e2, ..., en]}.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.collect(Collectors.joining(", ", "[", "]"))}
+ * or (less efficiently) {@code collect(Collectors.toList()).toString()}.
*/
@Override
+ @CheckReturnValue
public String toString() {
return Iterables.toString(iterable);
}
/**
* Returns the number of elements in this fluent iterable.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.count()}.
*/
+ @CheckReturnValue
public final int size() {
return Iterables.size(iterable);
}
/**
* Returns {@code true} if this fluent iterable contains any object for which
- * {@code equals(element)} is true.
+ * {@code equals(target)} is true.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.anyMatch(Predicate.isEqual(target))}.
*/
- public final boolean contains(@Nullable Object element) {
- return Iterables.contains(iterable, element);
+ @CheckReturnValue
+ public final boolean contains(@Nullable Object target) {
+ return Iterables.contains(iterable, target);
}
/**
@@ -157,6 +215,11 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* <p><b>Warning:</b> Typical uses of the resulting iterator may produce an infinite loop. You
* should use an explicit {@code break} or be certain that you will eventually remove all the
* elements.
+ *
+ * <p><b>{@code Stream} equivalent:</b> if the source iterable has only a single element {@code
+ * element}, use {@code Stream.generate(() -> element)}. Otherwise, if the source iterable has
+ * a {@code stream} method (for example, if it is a {@link Collection}), use
+ * {@code Stream.generate(iterable::stream).flatMap(s -> s)}.
*/
@CheckReturnValue
public final FluentIterable<E> cycle() {
@@ -170,6 +233,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* <p>The returned iterable's {@code Iterator} supports {@code remove()} when the corresponding
* {@code Iterator} supports it.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code Stream.concat(thisStream, otherStream)}.
+ *
* @since 18.0
*/
@Beta
@@ -182,6 +247,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Returns a fluent iterable whose iterators traverse first the elements of this fluent iterable,
* followed by {@code elements}.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code Stream.concat(thisStream, Stream.of(elements))}.
+ *
* @since 18.0
*/
@Beta
@@ -193,6 +260,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns the elements from this fluent iterable that satisfy a predicate. The
* resulting fluent iterable's iterator does not support {@code remove()}.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.filter(predicate)} (same).
*/
@CheckReturnValue
public final FluentIterable<E> filter(Predicate<? super E> predicate) {
@@ -203,6 +272,16 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Returns the elements from this fluent iterable that are instances of class {@code type}.
*
* @param type the type of elements desired
+ *
+ * <p><b>{@code Stream} equivalent:</b> <pre> {@code
+ *
+ * @SuppressWarnings("unchecked") // safe by runtime check
+ * Stream<T> result = (Stream) stream.filter(type::isInstance);}</pre>
+ *
+ * ... or if {@code type} is a class literal {@code MyType.class}, <pre> {@code
+ *
+ * @SuppressWarnings("unchecked") // safe by runtime check
+ * Stream<MyType> result = (Stream) stream.filter(e -> e instanceof MyType);}</pre>
*/
@GwtIncompatible("Class.isInstance")
@CheckReturnValue
@@ -212,7 +291,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns {@code true} if any element in this fluent iterable satisfies the predicate.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.anyMatch(predicate)} (same).
*/
+ @CheckReturnValue
public final boolean anyMatch(Predicate<? super E> predicate) {
return Iterables.any(iterable, predicate);
}
@@ -220,7 +302,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns {@code true} if every element in this fluent iterable satisfies the predicate.
* If this fluent iterable is empty, {@code true} is returned.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.allMatch(predicate)} (same).
*/
+ @CheckReturnValue
public final boolean allMatch(Predicate<? super E> predicate) {
return Iterables.all(iterable, predicate);
}
@@ -231,7 +316,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
*
* <p><b>Warning:</b> avoid using a {@code predicate} that matches {@code null}. If {@code null}
* is matched in this fluent iterable, a {@link NullPointerException} will be thrown.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.filter(predicate).findFirst()}.
*/
+ @CheckReturnValue
public final Optional<E> firstMatch(Predicate<? super E> predicate) {
return Iterables.tryFind(iterable, predicate);
}
@@ -243,7 +331,10 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* <p>The returned fluent iterable's iterator supports {@code remove()} if this iterable's
* iterator does. After a successful {@code remove()} call, this fluent iterable no longer
* contains the corresponding element.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.map(function)}.
*/
+ @CheckReturnValue
public final <T> FluentIterable<T> transform(Function<? super E, T> function) {
return from(Iterables.transform(iterable, function));
}
@@ -257,8 +348,12 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* function-returned iterables' iterator does. After a successful {@code remove()} call,
* the returned fluent iterable no longer contains the corresponding element.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.flatMap(function)} (using a function that
+ * produces streams, not iterables).
+ *
* @since 13.0 (required {@code Function<E, Iterable<T>>} until 14.0)
*/
+ @CheckReturnValue
public <T> FluentIterable<T> transformAndConcat(
Function<? super E, ? extends Iterable<? extends T>> function) {
return from(Iterables.concat(transform(function)));
@@ -268,23 +363,29 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Returns an {@link Optional} containing the first element in this fluent iterable.
* If the iterable is empty, {@code Optional.absent()} is returned.
*
+ * <p><b>{@code Stream} equivalent:</b> if the goal is to obtain any element, {@code
+ * stream.findAny()}; if it must specifically be the <i>first</i> element, {@code
+ * stream.findFirst()}.
+ *
* @throws NullPointerException if the first element is null; if this is a possibility, use
* {@code iterator().next()} or {@link Iterables#getFirst} instead.
*/
+ @CheckReturnValue
public final Optional<E> first() {
Iterator<E> iterator = iterable.iterator();
- return iterator.hasNext()
- ? Optional.of(iterator.next())
- : Optional.<E>absent();
+ return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.<E>absent();
}
/**
* Returns an {@link Optional} containing the last element in this fluent iterable.
* If the iterable is empty, {@code Optional.absent()} is returned.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.reduce((a, b) -> b)}.
+ *
* @throws NullPointerException if the last element is null; if this is a possibility, use
* {@link Iterables#getLast} instead.
*/
+ @CheckReturnValue
public final Optional<E> last() {
// Iterables#getLast was inlined here so we don't have to throw/catch a NSEE
@@ -335,6 +436,8 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* returned fluent iterable's iterator, as the {@code Iterator} contract states that a call
* to {@code * remove()} before a call to {@code next()} will throw an
* {@link IllegalStateException}.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.skip(numberToSkip)} (same).
*/
@CheckReturnValue
public final FluentIterable<E> skip(int numberToSkip) {
@@ -348,17 +451,22 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* The returned fluent iterable's iterator supports {@code remove()} if this
* fluent iterable's iterator does.
*
- * @param size the maximum number of elements in the returned fluent iterable
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.limit(maxSize)} (same).
+ *
+ * @param maxSize the maximum number of elements in the returned fluent iterable
* @throws IllegalArgumentException if {@code size} is negative
*/
@CheckReturnValue
- public final FluentIterable<E> limit(int size) {
- return from(Iterables.limit(iterable, size));
+ public final FluentIterable<E> limit(int maxSize) {
+ return from(Iterables.limit(iterable, maxSize));
}
/**
* Determines whether this fluent iterable is empty.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code !stream.findAny().isPresent()}.
*/
+ @CheckReturnValue
public final boolean isEmpty() {
return !iterable.iterator().hasNext();
}
@@ -367,8 +475,11 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Returns an {@code ImmutableList} containing all of the elements from this fluent iterable in
* proper sequence.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code ImmutableList.copyOf(stream.iterator())}.
+ *
* @since 14.0 (since 12.0 as {@code toImmutableList()}).
*/
+ @CheckReturnValue
public final ImmutableList<E> toList() {
return ImmutableList.copyOf(iterable);
}
@@ -378,10 +489,14 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* FluentIterable} in the order specified by {@code comparator}. To produce an {@code
* ImmutableList} sorted by its natural ordering, use {@code toSortedList(Ordering.natural())}.
*
+ * <p><b>{@code Stream} equivalent:</b>
+ * {@code ImmutableList.copyOf(stream.sorted(comparator).iterator())}.
+ *
* @param comparator the function by which to sort list elements
* @throws NullPointerException if any element is null
* @since 14.0 (since 13.0 as {@code toSortedImmutableList()}).
*/
+ @CheckReturnValue
public final ImmutableList<E> toSortedList(Comparator<? super E> comparator) {
return Ordering.from(comparator).immutableSortedCopy(iterable);
}
@@ -390,8 +505,11 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Returns an {@code ImmutableSet} containing all of the elements from this fluent iterable with
* duplicates removed.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code ImmutableSet.copyOf(stream.iterator())}.
+ *
* @since 14.0 (since 12.0 as {@code toImmutableSet()}).
*/
+ @CheckReturnValue
public final ImmutableSet<E> toSet() {
return ImmutableSet.copyOf(iterable);
}
@@ -402,24 +520,48 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* {@code comparator.compare(x, y) == 0}) removed. To produce an {@code ImmutableSortedSet} sorted
* by its natural ordering, use {@code toSortedSet(Ordering.natural())}.
*
+ * <p><b>{@code Stream} equivalent:</b>
+ * {@code ImmutableSortedSet.copyOf(comparator, stream.iterator())}.
+ *
* @param comparator the function by which to sort set elements
* @throws NullPointerException if any element is null
* @since 14.0 (since 12.0 as {@code toImmutableSortedSet()}).
*/
+ @CheckReturnValue
public final ImmutableSortedSet<E> toSortedSet(Comparator<? super E> comparator) {
return ImmutableSortedSet.copyOf(comparator, iterable);
}
/**
- * Returns an immutable map for which the elements of this {@code FluentIterable} are the keys in
- * the same order, mapped to values by the given function. If this iterable contains duplicate
- * elements, the returned map will contain each distinct element once in the order it first
- * appears.
+ * Returns an {@code ImmutableMultiset} containing all of the elements from this fluent iterable.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code ImmutableMultiset.copyOf(stream.iterator())}.
+ *
+ * @since 19.0
+ */
+ @CheckReturnValue
+ public final ImmutableMultiset<E> toMultiset() {
+ return ImmutableMultiset.copyOf(iterable);
+ }
+
+ /**
+ * Returns an immutable map whose keys are the distinct elements of this {@code FluentIterable}
+ * and whose value for each key was computed by {@code valueFunction}. The map's iteration order
+ * is the order of the first appearance of each key in this iterable.
+ *
+ * <p>When there are multiple instances of a key in this iterable, it is unspecified whether
+ * {@code valueFunction} will be applied to more than one instance of that key and, if it is,
+ * which result will be mapped to that key in the returned map.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code
+ * ImmutableMap.copyOf(stream.collect(Collectors.toMap(k -> k, valueFunction)))} (but note that
+ * this may not preserve the order of entries).
*
* @throws NullPointerException if any element of this iterable is {@code null}, or if {@code
* valueFunction} produces {@code null} for any key
* @since 14.0
*/
+ @CheckReturnValue
public final <V> ImmutableMap<E, V> toMap(Function<? super E, V> valueFunction) {
return Maps.toMap(iterable, valueFunction);
}
@@ -440,24 +582,49 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* <li>An element in this fluent iterable is null
* <li>{@code keyFunction} returns {@code null} for any element of this iterable
* </ul>
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.collect(Collectors.groupingBy(keyFunction))}
+ * behaves similarly, but returns a mutable {@code Map<K, List<E>>} instead, and may not preserve
+ * the order of entries).
+ *
* @since 14.0
*/
+ @CheckReturnValue
public final <K> ImmutableListMultimap<K, E> index(Function<? super E, K> keyFunction) {
return Multimaps.index(iterable, keyFunction);
}
/**
- * Returns an immutable map for which the {@link java.util.Map#values} are the elements of this
- * {@code FluentIterable} in the given order, and each key is the product of invoking a supplied
- * function on its corresponding value.
+ * Returns a map with the contents of this {@code FluentIterable} as its {@code values}, indexed
+ * by keys derived from those values. In other words, each input value produces an entry in the
+ * map whose key is the result of applying {@code keyFunction} to that value. These entries appear
+ * in the same order as they appeared in this fluent iterable. Example usage:
+ * <pre> {@code
+ *
+ * Color red = new Color("red", 255, 0, 0);
+ * ...
+ * FluentIterable<Color> allColors = FluentIterable.from(ImmutableSet.of(red, green, blue));
+ *
+ * Map<String, Color> colorForName = allColors.uniqueIndex(toStringFunction());
+ * assertThat(colorForName).containsEntry("red", red);}</pre>
+ *
+ * <p>If your index may associate multiple values with each key, use {@link #index(Function)
+ * index}.
+ *
+ * <p><b>{@code Stream} equivalent:</b> {@code
+ * ImmutableMap.copyOf(stream.collect(Collectors.toMap(keyFunction, v -> v)))} (but note that this
+ * may not preserve the order of entries).
*
* @param keyFunction the function used to produce the key for each value
- * @throws IllegalArgumentException if {@code keyFunction} produces the same key for more than one
- * value in this fluent iterable
- * @throws NullPointerException if any element of this fluent iterable is null, or if
- * {@code keyFunction} produces {@code null} for any value
+ * @return a map mapping the result of evaluating the function {@code
+ * keyFunction} on each value in this fluent iterable to that value
+ * @throws IllegalArgumentException if {@code keyFunction} produces the same
+ * key for more than one value in this fluent iterable
+ * @throws NullPointerException if any elements of this fluent iterable is null, or
+ * if {@code keyFunction} produces {@code null} for any value
* @since 14.0
*/
+ @CheckReturnValue
public final <K> ImmutableMap<K, E> uniqueIndex(Function<? super E, K> keyFunction) {
return Maps.uniqueIndex(iterable, keyFunction);
}
@@ -465,11 +632,17 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns an array containing all of the elements from this fluent iterable in iteration order.
*
+ * <p><b>{@code Stream} equivalent:</b> if an object array is acceptable, use
+ * {@code stream.toArray()}; if {@code type} is a class literal such as {@code MyType.class}, use
+ * {@code stream.toArray(MyType[]::new)}. Otherwise use {@code stream.toArray(
+ * len -> (E[]) Array.newInstance(type, len))}.
+ *
* @param type the type of the elements
* @return a newly-allocated array into which all the elements of this fluent iterable have
* been copied
*/
@GwtIncompatible("Array.newArray(Class, int)")
+ @CheckReturnValue
public final E[] toArray(Class<E> type) {
return Iterables.toArray(iterable, type);
}
@@ -478,6 +651,9 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Copies all the elements from this fluent iterable to {@code collection}. This is equivalent to
* calling {@code Iterables.addAll(collection, this)}.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.forEachOrdered(collection::add)} or
+ * {@code stream.forEach(collection::add)}.
+ *
* @param collection the collection to copy elements to
* @return {@code collection}, for convenience
* @since 14.0
@@ -498,9 +674,14 @@ public abstract class FluentIterable<E> implements Iterable<E> {
* Returns a {@link String} containing all of the elements of this fluent iterable joined with
* {@code joiner}.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code joiner.join(stream.iterator())}, or, if you are not
+ * using any optional {@code Joiner} features,
+ * {@code stream.collect(Collectors.joining(delimiter)}.
+ *
* @since 18.0
*/
@Beta
+ @CheckReturnValue
public final String join(Joiner joiner) {
return joiner.join(this);
}
@@ -508,11 +689,17 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Returns the element at the specified position in this fluent iterable.
*
+ * <p><b>{@code Stream} equivalent:</b> {@code stream.skip(position).findFirst().get()} (but note
+ * that this throws different exception types, and throws an exception if {@code null} would be
+ * returned).
+ *
* @param position position of the element to return
* @return the element at the specified position in this fluent iterable
* @throws IndexOutOfBoundsException if {@code position} is negative or greater than or equal to
* the size of this fluent iterable
*/
+ // TODO(kevinb): add @Nullable?
+ @CheckReturnValue
public final E get(int position) {
return Iterables.get(iterable, position);
}
@@ -520,8 +707,7 @@ public abstract class FluentIterable<E> implements Iterable<E> {
/**
* Function that transforms {@code Iterable<E>} into a fluent iterable.
*/
- private static class FromIterableFunction<E>
- implements Function<Iterable<E>, FluentIterable<E>> {
+ private static class FromIterableFunction<E> implements Function<Iterable<E>, FluentIterable<E>> {
@Override
public FluentIterable<E> apply(Iterable<E> fromObject) {
return FluentIterable.from(fromObject);
diff --git a/guava/src/com/google/common/collect/ForwardingBlockingDeque.java b/guava/src/com/google/common/collect/ForwardingBlockingDeque.java
index a6fb43d..ad3a21e 100644
--- a/guava/src/com/google/common/collect/ForwardingBlockingDeque.java
+++ b/guava/src/com/google/common/collect/ForwardingBlockingDeque.java
@@ -38,13 +38,14 @@ import java.util.concurrent.TimeUnit;
* @author Emily Soldal
* @since 14.0
*/
-public abstract class ForwardingBlockingDeque<E>
- extends ForwardingDeque<E> implements BlockingDeque<E> {
+public abstract class ForwardingBlockingDeque<E> extends ForwardingDeque<E>
+ implements BlockingDeque<E> {
/** Constructor for use by subclasses. */
protected ForwardingBlockingDeque() {}
- @Override protected abstract BlockingDeque<E> delegate();
+ @Override
+ protected abstract BlockingDeque<E> delegate();
@Override
public int remainingCapacity() {
diff --git a/guava/src/com/google/common/collect/ForwardingCollection.java b/guava/src/com/google/common/collect/ForwardingCollection.java
index 8c1b22e..434e471 100644
--- a/guava/src/com/google/common/collect/ForwardingCollection.java
+++ b/guava/src/com/google/common/collect/ForwardingCollection.java
@@ -42,17 +42,17 @@ import javax.annotation.Nullable;
*
* @author Kevin Bourrillion
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
-public abstract class ForwardingCollection<E> extends ForwardingObject
- implements Collection<E> {
- // TODO(user): identify places where thread safety is actually lost
+public abstract class ForwardingCollection<E> extends ForwardingObject implements Collection<E> {
+ // TODO(lowasser): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingCollection() {}
- @Override protected abstract Collection<E> delegate();
+ @Override
+ protected abstract Collection<E> delegate();
@Override
public Iterator<E> iterator() {
diff --git a/guava/src/com/google/common/collect/ForwardingConcurrentMap.java b/guava/src/com/google/common/collect/ForwardingConcurrentMap.java
index 0336dd1..de42066 100644
--- a/guava/src/com/google/common/collect/ForwardingConcurrentMap.java
+++ b/guava/src/com/google/common/collect/ForwardingConcurrentMap.java
@@ -27,7 +27,7 @@ import java.util.concurrent.ConcurrentMap;
* href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
*
* @author Charles Fry
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public abstract class ForwardingConcurrentMap<K, V> extends ForwardingMap<K, V>
@@ -36,7 +36,8 @@ public abstract class ForwardingConcurrentMap<K, V> extends ForwardingMap<K, V>
/** Constructor for use by subclasses. */
protected ForwardingConcurrentMap() {}
- @Override protected abstract ConcurrentMap<K, V> delegate();
+ @Override
+ protected abstract ConcurrentMap<K, V> delegate();
@Override
public V putIfAbsent(K key, V value) {
@@ -57,5 +58,4 @@ public abstract class ForwardingConcurrentMap<K, V> extends ForwardingMap<K, V>
public boolean replace(K key, V oldValue, V newValue) {
return delegate().replace(key, oldValue, newValue);
}
-
}
diff --git a/guava/src/com/google/common/collect/ForwardingDeque.java b/guava/src/com/google/common/collect/ForwardingDeque.java
index 070f622..a58636a 100644
--- a/guava/src/com/google/common/collect/ForwardingDeque.java
+++ b/guava/src/com/google/common/collect/ForwardingDeque.java
@@ -34,13 +34,13 @@ import java.util.Iterator;
* @author Kurt Alfred Kluever
* @since 12.0
*/
-public abstract class ForwardingDeque<E> extends ForwardingQueue<E>
- implements Deque<E> {
+public abstract class ForwardingDeque<E> extends ForwardingQueue<E> implements Deque<E> {
/** Constructor for use by subclasses. */
protected ForwardingDeque() {}
- @Override protected abstract Deque<E> delegate();
+ @Override
+ protected abstract Deque<E> delegate();
@Override
public void addFirst(E e) {
diff --git a/guava/src/com/google/common/collect/ForwardingIterator.java b/guava/src/com/google/common/collect/ForwardingIterator.java
index b8927d4..03cbc75 100644
--- a/guava/src/com/google/common/collect/ForwardingIterator.java
+++ b/guava/src/com/google/common/collect/ForwardingIterator.java
@@ -27,16 +27,16 @@ import java.util.Iterator;
* href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
-public abstract class ForwardingIterator<T>
- extends ForwardingObject implements Iterator<T> {
+public abstract class ForwardingIterator<T> extends ForwardingObject implements Iterator<T> {
/** Constructor for use by subclasses. */
protected ForwardingIterator() {}
- @Override protected abstract Iterator<T> delegate();
+ @Override
+ protected abstract Iterator<T> delegate();
@Override
public boolean hasNext() {
diff --git a/guava/src/com/google/common/collect/ForwardingList.java b/guava/src/com/google/common/collect/ForwardingList.java
index 71ae993..288340f 100644
--- a/guava/src/com/google/common/collect/ForwardingList.java
+++ b/guava/src/com/google/common/collect/ForwardingList.java
@@ -49,17 +49,17 @@ import javax.annotation.Nullable;
*
* @author Mike Bostock
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
-public abstract class ForwardingList<E> extends ForwardingCollection<E>
- implements List<E> {
- // TODO(user): identify places where thread safety is actually lost
+public abstract class ForwardingList<E> extends ForwardingCollection<E> implements List<E> {
+ // TODO(lowasser): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingList() {}
- @Override protected abstract List<E> delegate();
+ @Override
+ protected abstract List<E> delegate();
@Override
public void add(int index, E element) {
@@ -111,11 +111,13 @@ public abstract class ForwardingList<E> extends ForwardingCollection<E>
return delegate().subList(fromIndex, toIndex);
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return object == this || delegate().equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return delegate().hashCode();
}
@@ -140,8 +142,7 @@ public abstract class ForwardingList<E> extends ForwardingCollection<E>
*
* @since 7.0
*/
- protected boolean standardAddAll(
- int index, Iterable<? extends E> elements) {
+ protected boolean standardAddAll(int index, Iterable<? extends E> elements) {
return Lists.addAllImpl(this, index, elements);
}
@@ -200,7 +201,8 @@ public abstract class ForwardingList<E> extends ForwardingCollection<E>
*
* @since 7.0
*/
- @Beta protected ListIterator<E> standardListIterator(int start) {
+ @Beta
+ protected ListIterator<E> standardListIterator(int start) {
return Lists.listIteratorImpl(this, start);
}
@@ -211,7 +213,8 @@ public abstract class ForwardingList<E> extends ForwardingCollection<E>
*
* @since 7.0
*/
- @Beta protected List<E> standardSubList(int fromIndex, int toIndex) {
+ @Beta
+ protected List<E> standardSubList(int fromIndex, int toIndex) {
return Lists.subListImpl(this, fromIndex, toIndex);
}
@@ -222,7 +225,8 @@ public abstract class ForwardingList<E> extends ForwardingCollection<E>
*
* @since 7.0
*/
- @Beta protected boolean standardEquals(@Nullable Object object) {
+ @Beta
+ protected boolean standardEquals(@Nullable Object object) {
return Lists.equalsImpl(this, object);
}
@@ -233,7 +237,8 @@ public abstract class ForwardingList<E> extends ForwardingCollection<E>
*
* @since 7.0
*/
- @Beta protected int standardHashCode() {
+ @Beta
+ protected int standardHashCode() {
return Lists.hashCodeImpl(this);
}
}
diff --git a/guava/src/com/google/common/collect/ForwardingListIterator.java b/guava/src/com/google/common/collect/ForwardingListIterator.java
index e2ebe55..b7239ba 100644
--- a/guava/src/com/google/common/collect/ForwardingListIterator.java
+++ b/guava/src/com/google/common/collect/ForwardingListIterator.java
@@ -27,7 +27,7 @@ import java.util.ListIterator;
* href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
*
* @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public abstract class ForwardingListIterator<E> extends ForwardingIterator<E>
@@ -36,7 +36,8 @@ public abstract class ForwardingListIterator<E> extends ForwardingIterator<E>
/** Constructor for use by subclasses. */
protected ForwardingListIterator() {}
- @Override protected abstract ListIterator<E> delegate();
+ @Override
+ protected abstract ListIterator<E> delegate();
@Override
public void add(E element) {
diff --git a/guava/src/com/google/common/collect/ForwardingListMultimap.java b/guava/src/com/google/common/collect/ForwardingListMultimap.java
index 3b1d55e..477af99 100644
--- a/guava/src/com/google/common/collect/ForwardingListMultimap.java
+++ b/guava/src/com/google/common/collect/ForwardingListMultimap.java
@@ -32,23 +32,27 @@ import javax.annotation.Nullable;
* @since 3.0
*/
@GwtCompatible
-public abstract class ForwardingListMultimap<K, V>
- extends ForwardingMultimap<K, V> implements ListMultimap<K, V> {
+public abstract class ForwardingListMultimap<K, V> extends ForwardingMultimap<K, V>
+ implements ListMultimap<K, V> {
/** Constructor for use by subclasses. */
protected ForwardingListMultimap() {}
- @Override protected abstract ListMultimap<K, V> delegate();
+ @Override
+ protected abstract ListMultimap<K, V> delegate();
- @Override public List<V> get(@Nullable K key) {
+ @Override
+ public List<V> get(@Nullable K key) {
return delegate().get(key);
}
- @Override public List<V> removeAll(@Nullable Object key) {
+ @Override
+ public List<V> removeAll(@Nullable Object key) {
return delegate().removeAll(key);
}
- @Override public List<V> replaceValues(K key, Iterable<? extends V> values) {
+ @Override
+ public List<V> replaceValues(K key, Iterable<? extends V> values) {
return delegate().replaceValues(key, values);
}
}
diff --git a/guava/src/com/google/common/collect/ForwardingMap.java b/guava/src/com/google/common/collect/ForwardingMap.java
index 6816ba0..c550789 100644
--- a/guava/src/com/google/common/collect/ForwardingMap.java
+++ b/guava/src/com/google/common/collect/ForwardingMap.java
@@ -53,17 +53,17 @@ import javax.annotation.Nullable;
* @author Kevin Bourrillion
* @author Jared Levy
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
-public abstract class ForwardingMap<K, V> extends ForwardingObject
- implements Map<K, V> {
- // TODO(user): identify places where thread safety is actually lost
+public abstract class ForwardingMap<K, V> extends ForwardingObject implements Map<K, V> {
+ // TODO(lowasser): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingMap() {}
- @Override protected abstract Map<K, V> delegate();
+ @Override
+ protected abstract Map<K, V> delegate();
@Override
public int size() {
@@ -125,11 +125,13 @@ public abstract class ForwardingMap<K, V> extends ForwardingObject
return delegate().entrySet();
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return object == this || delegate().equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return delegate().hashCode();
}
@@ -157,7 +159,8 @@ public abstract class ForwardingMap<K, V> extends ForwardingObject
*
* @since 7.0
*/
- @Beta protected V standardRemove(@Nullable Object key) {
+ @Beta
+ protected V standardRemove(@Nullable Object key) {
Iterator<Entry<K, V>> entryIterator = entrySet().iterator();
while (entryIterator.hasNext()) {
Entry<K, V> entry = entryIterator.next();
@@ -208,7 +211,8 @@ public abstract class ForwardingMap<K, V> extends ForwardingObject
*
* @since 7.0
*/
- @Beta protected boolean standardContainsKey(@Nullable Object key) {
+ @Beta
+ protected boolean standardContainsKey(@Nullable Object key) {
return Maps.containsKeyImpl(this, key);
}
diff --git a/guava/src/com/google/common/collect/ForwardingMapEntry.java b/guava/src/com/google/common/collect/ForwardingMapEntry.java
index 4d63757..559f0bb 100644
--- a/guava/src/com/google/common/collect/ForwardingMapEntry.java
+++ b/guava/src/com/google/common/collect/ForwardingMapEntry.java
@@ -49,17 +49,17 @@ import javax.annotation.Nullable;
*
* @author Mike Bostock
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
-public abstract class ForwardingMapEntry<K, V>
- extends ForwardingObject implements Map.Entry<K, V> {
- // TODO(user): identify places where thread safety is actually lost
+public abstract class ForwardingMapEntry<K, V> extends ForwardingObject implements Map.Entry<K, V> {
+ // TODO(lowasser): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingMapEntry() {}
- @Override protected abstract Map.Entry<K, V> delegate();
+ @Override
+ protected abstract Map.Entry<K, V> delegate();
@Override
public K getKey() {
@@ -76,11 +76,13 @@ public abstract class ForwardingMapEntry<K, V>
return delegate().setValue(value);
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return delegate().equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return delegate().hashCode();
}
@@ -122,7 +124,8 @@ public abstract class ForwardingMapEntry<K, V>
*
* @since 7.0
*/
- @Beta protected String standardToString() {
+ @Beta
+ protected String standardToString() {
return getKey() + "=" + getValue();
}
}
diff --git a/guava/src/com/google/common/collect/ForwardingMultimap.java b/guava/src/com/google/common/collect/ForwardingMultimap.java
index c860820..5410a1b 100644
--- a/guava/src/com/google/common/collect/ForwardingMultimap.java
+++ b/guava/src/com/google/common/collect/ForwardingMultimap.java
@@ -32,16 +32,16 @@ import javax.annotation.Nullable;
* href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
*
* @author Robert Konigsberg
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
-public abstract class ForwardingMultimap<K, V> extends ForwardingObject
- implements Multimap<K, V> {
+public abstract class ForwardingMultimap<K, V> extends ForwardingObject implements Multimap<K, V> {
/** Constructor for use by subclasses. */
protected ForwardingMultimap() {}
- @Override protected abstract Multimap<K, V> delegate();
+ @Override
+ protected abstract Multimap<K, V> delegate();
@Override
public Map<K, Collection<V>> asMap() {
@@ -133,11 +133,13 @@ public abstract class ForwardingMultimap<K, V> extends ForwardingObject
return delegate().values();
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return object == this || delegate().equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return delegate().hashCode();
}
}
diff --git a/guava/src/com/google/common/collect/ForwardingMultiset.java b/guava/src/com/google/common/collect/ForwardingMultiset.java
index 9834751..9d70d84 100644
--- a/guava/src/com/google/common/collect/ForwardingMultiset.java
+++ b/guava/src/com/google/common/collect/ForwardingMultiset.java
@@ -46,16 +46,16 @@ import javax.annotation.Nullable;
*
* @author Kevin Bourrillion
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
-public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
- implements Multiset<E> {
+public abstract class ForwardingMultiset<E> extends ForwardingCollection<E> implements Multiset<E> {
/** Constructor for use by subclasses. */
protected ForwardingMultiset() {}
- @Override protected abstract Multiset<E> delegate();
+ @Override
+ protected abstract Multiset<E> delegate();
@Override
public int count(Object element) {
@@ -82,11 +82,13 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
return delegate().entrySet();
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return object == this || delegate().equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return delegate().hashCode();
}
@@ -104,10 +106,11 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
* A sensible definition of {@link #contains} in terms of {@link #count}. If
* you override {@link #count}, you may wish to override {@link #contains} to
* forward to this implementation.
- *
+ *
* @since 7.0
*/
- @Override protected boolean standardContains(@Nullable Object object) {
+ @Override
+ protected boolean standardContains(@Nullable Object object) {
return count(object) > 0;
}
@@ -118,7 +121,8 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
*
* @since 7.0
*/
- @Override protected void standardClear() {
+ @Override
+ protected void standardClear() {
Iterators.clear(entrySet().iterator());
}
@@ -126,10 +130,11 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
* A sensible, albeit inefficient, definition of {@link #count} in terms of
* {@link #entrySet}. If you override {@link #entrySet}, you may wish to
* override {@link #count} to forward to this implementation.
- *
+ *
* @since 7.0
*/
- @Beta protected int standardCount(@Nullable Object object) {
+ @Beta
+ protected int standardCount(@Nullable Object object) {
for (Entry<?> entry : this.entrySet()) {
if (Objects.equal(entry.getElement(), object)) {
return entry.getCount();
@@ -142,7 +147,7 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
* A sensible definition of {@link #add(Object)} in terms of {@link
* #add(Object, int)}. If you override {@link #add(Object, int)}, you may
* wish to override {@link #add(Object)} to forward to this implementation.
- *
+ *
* @since 7.0
*/
protected boolean standardAdd(E element) {
@@ -155,11 +160,12 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
* #add(Object)} and {@link #add(Object, int)}. If you override either of
* these methods, you may wish to override {@link #addAll(Collection)} to
* forward to this implementation.
- *
+ *
* @since 7.0
*/
- @Beta @Override protected boolean standardAddAll(
- Collection<? extends E> elementsToAdd) {
+ @Beta
+ @Override
+ protected boolean standardAddAll(Collection<? extends E> elementsToAdd) {
return Multisets.addAllImpl(this, elementsToAdd);
}
@@ -168,10 +174,11 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
* #remove(Object, int)}. If you override {@link #remove(Object, int)}, you
* may wish to override {@link #remove(Object)} to forward to this
* implementation.
- *
+ *
* @since 7.0
*/
- @Override protected boolean standardRemove(Object element) {
+ @Override
+ protected boolean standardRemove(Object element) {
return remove(element, 1) > 0;
}
@@ -183,8 +190,8 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
*
* @since 7.0
*/
- @Override protected boolean standardRemoveAll(
- Collection<?> elementsToRemove) {
+ @Override
+ protected boolean standardRemoveAll(Collection<?> elementsToRemove) {
return Multisets.removeAllImpl(this, elementsToRemove);
}
@@ -196,8 +203,8 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
*
* @since 7.0
*/
- @Override protected boolean standardRetainAll(
- Collection<?> elementsToRetain) {
+ @Override
+ protected boolean standardRetainAll(Collection<?> elementsToRetain) {
return Multisets.retainAllImpl(this, elementsToRetain);
}
@@ -207,7 +214,7 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
* int)}. {@link #entrySet()}. If you override any of these methods, you may
* wish to override {@link #setCount(Object, int)} to forward to this
* implementation.
- *
+ *
* @since 7.0
*/
protected int standardSetCount(E element, int count) {
@@ -249,12 +256,12 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
return ForwardingMultiset.this;
}
}
-
+
/**
* A sensible definition of {@link #iterator} in terms of {@link #entrySet}
* and {@link #remove(Object)}. If you override either of these methods, you
* may wish to override {@link #iterator} to forward to this implementation.
- *
+ *
* @since 7.0
*/
protected Iterator<E> standardIterator() {
@@ -265,7 +272,7 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
* A sensible, albeit inefficient, definition of {@link #size} in terms of
* {@link #entrySet}. If you override {@link #entrySet}, you may wish to
* override {@link #size} to forward to this implementation.
- *
+ *
* @since 7.0
*/
protected int standardSize() {
@@ -302,7 +309,8 @@ public abstract class ForwardingMultiset<E> extends ForwardingCollection<E>
*
* @since 7.0
*/
- @Override protected String standardToString() {
+ @Override
+ protected String standardToString() {
return entrySet().toString();
}
}
diff --git a/guava/src/com/google/common/collect/ForwardingNavigableMap.java b/guava/src/com/google/common/collect/ForwardingNavigableMap.java
index 3e11239..b022d1a 100644
--- a/guava/src/com/google/common/collect/ForwardingNavigableMap.java
+++ b/guava/src/com/google/common/collect/ForwardingNavigableMap.java
@@ -49,8 +49,8 @@ import java.util.SortedMap;
* @author Louis Wasserman
* @since 12.0
*/
-public abstract class ForwardingNavigableMap<K, V>
- extends ForwardingSortedMap<K, V> implements NavigableMap<K, V> {
+public abstract class ForwardingNavigableMap<K, V> extends ForwardingSortedMap<K, V>
+ implements NavigableMap<K, V> {
/** Constructor for use by subclasses. */
protected ForwardingNavigableMap() {}
diff --git a/guava/src/com/google/common/collect/ForwardingNavigableSet.java b/guava/src/com/google/common/collect/ForwardingNavigableSet.java
index dff5ea0..447f397 100644
--- a/guava/src/com/google/common/collect/ForwardingNavigableSet.java
+++ b/guava/src/com/google/common/collect/ForwardingNavigableSet.java
@@ -44,8 +44,8 @@ import java.util.SortedSet;
* @author Louis Wasserman
* @since 12.0
*/
-public abstract class ForwardingNavigableSet<E>
- extends ForwardingSortedSet<E> implements NavigableSet<E> {
+public abstract class ForwardingNavigableSet<E> extends ForwardingSortedSet<E>
+ implements NavigableSet<E> {
/** Constructor for use by subclasses. */
protected ForwardingNavigableSet() {}
@@ -174,10 +174,7 @@ public abstract class ForwardingNavigableSet<E>
@Override
public NavigableSet<E> subSet(
- E fromElement,
- boolean fromInclusive,
- E toElement,
- boolean toInclusive) {
+ E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
return delegate().subSet(fromElement, fromInclusive, toElement, toInclusive);
}
@@ -188,10 +185,7 @@ public abstract class ForwardingNavigableSet<E>
*/
@Beta
protected NavigableSet<E> standardSubSet(
- E fromElement,
- boolean fromInclusive,
- E toElement,
- boolean toInclusive) {
+ E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
return tailSet(fromElement, fromInclusive).headSet(toElement, toInclusive);
}
diff --git a/guava/src/com/google/common/collect/ForwardingObject.java b/guava/src/com/google/common/collect/ForwardingObject.java
index 7fecdee..b25538c 100644
--- a/guava/src/com/google/common/collect/ForwardingObject.java
+++ b/guava/src/com/google/common/collect/ForwardingObject.java
@@ -47,7 +47,7 @@ import java.io.Serializable;
* created since this class has a parameter-less constructor.
*
* @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public abstract class ForwardingObject {
@@ -68,7 +68,8 @@ public abstract class ForwardingObject {
* Returns the string representation generated by the delegate's
* {@code toString} method.
*/
- @Override public String toString() {
+ @Override
+ public String toString() {
return delegate().toString();
}
diff --git a/guava/src/com/google/common/collect/ForwardingQueue.java b/guava/src/com/google/common/collect/ForwardingQueue.java
index 569880a..c150bdb 100644
--- a/guava/src/com/google/common/collect/ForwardingQueue.java
+++ b/guava/src/com/google/common/collect/ForwardingQueue.java
@@ -39,16 +39,16 @@ import java.util.Queue;
*
* @author Mike Bostock
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
-public abstract class ForwardingQueue<E> extends ForwardingCollection<E>
- implements Queue<E> {
+public abstract class ForwardingQueue<E> extends ForwardingCollection<E> implements Queue<E> {
/** Constructor for use by subclasses. */
protected ForwardingQueue() {}
- @Override protected abstract Queue<E> delegate();
+ @Override
+ protected abstract Queue<E> delegate();
@Override
public boolean offer(E o) {
@@ -79,7 +79,7 @@ public abstract class ForwardingQueue<E> extends ForwardingCollection<E>
* A sensible definition of {@link #offer} in terms of {@link #add}. If you
* override {@link #add}, you may wish to override {@link #offer} to forward
* to this implementation.
- *
+ *
* @since 7.0
*/
protected boolean standardOffer(E e) {
@@ -94,7 +94,7 @@ public abstract class ForwardingQueue<E> extends ForwardingCollection<E>
* A sensible definition of {@link #peek} in terms of {@link #element}. If you
* override {@link #element}, you may wish to override {@link #peek} to
* forward to this implementation.
- *
+ *
* @since 7.0
*/
protected E standardPeek() {
@@ -109,7 +109,7 @@ public abstract class ForwardingQueue<E> extends ForwardingCollection<E>
* A sensible definition of {@link #poll} in terms of {@link #remove}. If you
* override {@link #remove}, you may wish to override {@link #poll} to forward
* to this implementation.
- *
+ *
* @since 7.0
*/
protected E standardPoll() {
diff --git a/guava/src/com/google/common/collect/ForwardingSet.java b/guava/src/com/google/common/collect/ForwardingSet.java
index e1a4485..0430af8 100644
--- a/guava/src/com/google/common/collect/ForwardingSet.java
+++ b/guava/src/com/google/common/collect/ForwardingSet.java
@@ -43,23 +43,25 @@ import javax.annotation.Nullable;
*
* @author Kevin Bourrillion
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
-public abstract class ForwardingSet<E> extends ForwardingCollection<E>
- implements Set<E> {
- // TODO(user): identify places where thread safety is actually lost
+public abstract class ForwardingSet<E> extends ForwardingCollection<E> implements Set<E> {
+ // TODO(lowasser): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingSet() {}
- @Override protected abstract Set<E> delegate();
+ @Override
+ protected abstract Set<E> delegate();
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return object == this || delegate().equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return delegate().hashCode();
}
diff --git a/guava/src/com/google/common/collect/ForwardingSetMultimap.java b/guava/src/com/google/common/collect/ForwardingSetMultimap.java
index a923946..dde1ff6 100644
--- a/guava/src/com/google/common/collect/ForwardingSetMultimap.java
+++ b/guava/src/com/google/common/collect/ForwardingSetMultimap.java
@@ -33,24 +33,29 @@ import javax.annotation.Nullable;
* @since 3.0
*/
@GwtCompatible
-public abstract class ForwardingSetMultimap<K, V>
- extends ForwardingMultimap<K, V> implements SetMultimap<K, V> {
+public abstract class ForwardingSetMultimap<K, V> extends ForwardingMultimap<K, V>
+ implements SetMultimap<K, V> {
- @Override protected abstract SetMultimap<K, V> delegate();
+ @Override
+ protected abstract SetMultimap<K, V> delegate();
- @Override public Set<Entry<K, V>> entries() {
+ @Override
+ public Set<Entry<K, V>> entries() {
return delegate().entries();
}
- @Override public Set<V> get(@Nullable K key) {
+ @Override
+ public Set<V> get(@Nullable K key) {
return delegate().get(key);
}
- @Override public Set<V> removeAll(@Nullable Object key) {
+ @Override
+ public Set<V> removeAll(@Nullable Object key) {
return delegate().removeAll(key);
}
- @Override public Set<V> replaceValues(K key, Iterable<? extends V> values) {
+ @Override
+ public Set<V> replaceValues(K key, Iterable<? extends V> values) {
return delegate().replaceValues(key, values);
}
}
diff --git a/guava/src/com/google/common/collect/ForwardingSortedMap.java b/guava/src/com/google/common/collect/ForwardingSortedMap.java
index 1235e56..5ccd45b 100644
--- a/guava/src/com/google/common/collect/ForwardingSortedMap.java
+++ b/guava/src/com/google/common/collect/ForwardingSortedMap.java
@@ -50,17 +50,18 @@ import javax.annotation.Nullable;
*
* @author Mike Bostock
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public abstract class ForwardingSortedMap<K, V> extends ForwardingMap<K, V>
implements SortedMap<K, V> {
- // TODO(user): identify places where thread safety is actually lost
+ // TODO(lowasser): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingSortedMap() {}
- @Override protected abstract SortedMap<K, V> delegate();
+ @Override
+ protected abstract SortedMap<K, V> delegate();
@Override
public Comparator<? super K> comparator() {
@@ -126,7 +127,9 @@ public abstract class ForwardingSortedMap<K, V> extends ForwardingMap<K, V>
*
* @since 7.0
*/
- @Override @Beta protected boolean standardContainsKey(@Nullable Object key) {
+ @Override
+ @Beta
+ protected boolean standardContainsKey(@Nullable Object key) {
try {
// any CCE will be caught
@SuppressWarnings("unchecked")
@@ -150,7 +153,8 @@ public abstract class ForwardingSortedMap<K, V> extends ForwardingMap<K, V>
*
* @since 7.0
*/
- @Beta protected SortedMap<K, V> standardSubMap(K fromKey, K toKey) {
+ @Beta
+ protected SortedMap<K, V> standardSubMap(K fromKey, K toKey) {
checkArgument(unsafeCompare(fromKey, toKey) <= 0, "fromKey must be <= toKey");
return tailMap(fromKey).headMap(toKey);
}
diff --git a/guava/src/com/google/common/collect/ForwardingSortedMultiset.java b/guava/src/com/google/common/collect/ForwardingSortedMultiset.java
index 9ec79b8..2f0cbbe 100644
--- a/guava/src/com/google/common/collect/ForwardingSortedMultiset.java
+++ b/guava/src/com/google/common/collect/ForwardingSortedMultiset.java
@@ -92,8 +92,7 @@ public abstract class ForwardingSortedMultiset<E> extends ForwardingMultiset<E>
* In many cases, you may wish to override {@link #descendingMultiset()} to return an instance of
* a subclass of {@code StandardDescendingMultiset}.
*/
- protected abstract class StandardDescendingMultiset
- extends DescendingMultiset<E> {
+ protected abstract class StandardDescendingMultiset extends DescendingMultiset<E> {
/** Constructor for use by subclasses. */
public StandardDescendingMultiset() {}
@@ -136,9 +135,7 @@ public abstract class ForwardingSortedMultiset<E> extends ForwardingMultiset<E>
* {@link #firstEntry()} to forward to this implementation.
*/
protected Entry<E> standardLastEntry() {
- Iterator<Entry<E>> entryIterator = descendingMultiset()
- .entrySet()
- .iterator();
+ Iterator<Entry<E>> entryIterator = descendingMultiset().entrySet().iterator();
if (!entryIterator.hasNext()) {
return null;
}
@@ -181,9 +178,7 @@ public abstract class ForwardingSortedMultiset<E> extends ForwardingMultiset<E>
* {@link #pollLastEntry()} to forward to this implementation.
*/
protected Entry<E> standardPollLastEntry() {
- Iterator<Entry<E>> entryIterator = descendingMultiset()
- .entrySet()
- .iterator();
+ Iterator<Entry<E>> entryIterator = descendingMultiset().entrySet().iterator();
if (!entryIterator.hasNext()) {
return null;
}
@@ -221,5 +216,4 @@ public abstract class ForwardingSortedMultiset<E> extends ForwardingMultiset<E>
public SortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
return delegate().tailMultiset(lowerBound, boundType);
}
-
}
diff --git a/guava/src/com/google/common/collect/ForwardingSortedSet.java b/guava/src/com/google/common/collect/ForwardingSortedSet.java
index 756d9af..63ebec2 100644
--- a/guava/src/com/google/common/collect/ForwardingSortedSet.java
+++ b/guava/src/com/google/common/collect/ForwardingSortedSet.java
@@ -51,16 +51,16 @@ import javax.annotation.Nullable;
*
* @author Mike Bostock
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
-public abstract class ForwardingSortedSet<E> extends ForwardingSet<E>
- implements SortedSet<E> {
+public abstract class ForwardingSortedSet<E> extends ForwardingSet<E> implements SortedSet<E> {
/** Constructor for use by subclasses. */
protected ForwardingSortedSet() {}
- @Override protected abstract SortedSet<E> delegate();
+ @Override
+ protected abstract SortedSet<E> delegate();
@Override
public Comparator<? super E> comparator() {
@@ -108,7 +108,9 @@ public abstract class ForwardingSortedSet<E> extends ForwardingSet<E>
*
* @since 7.0
*/
- @Override @Beta protected boolean standardContains(@Nullable Object object) {
+ @Override
+ @Beta
+ protected boolean standardContains(@Nullable Object object) {
try {
// any ClassCastExceptions are caught
@SuppressWarnings("unchecked")
@@ -131,7 +133,9 @@ public abstract class ForwardingSortedSet<E> extends ForwardingSet<E>
*
* @since 7.0
*/
- @Override @Beta protected boolean standardRemove(@Nullable Object object) {
+ @Override
+ @Beta
+ protected boolean standardRemove(@Nullable Object object) {
try {
// any ClassCastExceptions are caught
@SuppressWarnings("unchecked")
@@ -160,7 +164,8 @@ public abstract class ForwardingSortedSet<E> extends ForwardingSet<E>
*
* @since 7.0
*/
- @Beta protected SortedSet<E> standardSubSet(E fromElement, E toElement) {
+ @Beta
+ protected SortedSet<E> standardSubSet(E fromElement, E toElement) {
return tailSet(fromElement).headSet(toElement);
}
}
diff --git a/guava/src/com/google/common/collect/ForwardingSortedSetMultimap.java b/guava/src/com/google/common/collect/ForwardingSortedSetMultimap.java
index d90c305..b800b7b 100644
--- a/guava/src/com/google/common/collect/ForwardingSortedSetMultimap.java
+++ b/guava/src/com/google/common/collect/ForwardingSortedSetMultimap.java
@@ -33,28 +33,32 @@ import javax.annotation.Nullable;
* @since 3.0
*/
@GwtCompatible
-public abstract class ForwardingSortedSetMultimap<K, V>
- extends ForwardingSetMultimap<K, V> implements SortedSetMultimap<K, V> {
+public abstract class ForwardingSortedSetMultimap<K, V> extends ForwardingSetMultimap<K, V>
+ implements SortedSetMultimap<K, V> {
/** Constructor for use by subclasses. */
protected ForwardingSortedSetMultimap() {}
- @Override protected abstract SortedSetMultimap<K, V> delegate();
+ @Override
+ protected abstract SortedSetMultimap<K, V> delegate();
- @Override public SortedSet<V> get(@Nullable K key) {
+ @Override
+ public SortedSet<V> get(@Nullable K key) {
return delegate().get(key);
}
- @Override public SortedSet<V> removeAll(@Nullable Object key) {
+ @Override
+ public SortedSet<V> removeAll(@Nullable Object key) {
return delegate().removeAll(key);
}
- @Override public SortedSet<V> replaceValues(
- K key, Iterable<? extends V> values) {
+ @Override
+ public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
return delegate().replaceValues(key, values);
}
- @Override public Comparator<? super V> valueComparator() {
+ @Override
+ public Comparator<? super V> valueComparator() {
return delegate().valueComparator();
}
}
diff --git a/guava/src/com/google/common/collect/ForwardingTable.java b/guava/src/com/google/common/collect/ForwardingTable.java
index 92cc876..a5f1b83 100644
--- a/guava/src/com/google/common/collect/ForwardingTable.java
+++ b/guava/src/com/google/common/collect/ForwardingTable.java
@@ -32,12 +32,12 @@ import java.util.Set;
* @since 7.0
*/
@GwtCompatible
-public abstract class ForwardingTable<R, C, V> extends ForwardingObject
- implements Table<R, C, V> {
+public abstract class ForwardingTable<R, C, V> extends ForwardingObject implements Table<R, C, V> {
/** Constructor for use by subclasses. */
protected ForwardingTable() {}
- @Override protected abstract Table<R, C, V> delegate();
+ @Override
+ protected abstract Table<R, C, V> delegate();
@Override
public Set<Cell<R, C, V>> cellSet() {
@@ -134,11 +134,13 @@ public abstract class ForwardingTable<R, C, V> extends ForwardingObject
return delegate().values();
}
- @Override public boolean equals(Object obj) {
+ @Override
+ public boolean equals(Object obj) {
return (obj == this) || delegate().equals(obj);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return delegate().hashCode();
}
}
diff --git a/guava/src/com/google/common/collect/GeneralRange.java b/guava/src/com/google/common/collect/GeneralRange.java
index cb3b2c8..74fe62b 100644
--- a/guava/src/com/google/common/collect/GeneralRange.java
+++ b/guava/src/com/google/common/collect/GeneralRange.java
@@ -42,15 +42,19 @@ final class GeneralRange<T> implements Serializable {
* Converts a Range to a GeneralRange.
*/
static <T extends Comparable> GeneralRange<T> from(Range<T> range) {
- @Nullable
- T lowerEndpoint = range.hasLowerBound() ? range.lowerEndpoint() : null;
+ @Nullable T lowerEndpoint = range.hasLowerBound() ? range.lowerEndpoint() : null;
BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : OPEN;
- @Nullable
- T upperEndpoint = range.hasUpperBound() ? range.upperEndpoint() : null;
+ @Nullable T upperEndpoint = range.hasUpperBound() ? range.upperEndpoint() : null;
BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : OPEN;
- return new GeneralRange<T>(Ordering.natural(), range.hasLowerBound(), lowerEndpoint,
- lowerBoundType, range.hasUpperBound(), upperEndpoint, upperBoundType);
+ return new GeneralRange<T>(
+ Ordering.natural(),
+ range.hasLowerBound(),
+ lowerEndpoint,
+ lowerBoundType,
+ range.hasUpperBound(),
+ upperEndpoint,
+ upperBoundType);
}
/**
@@ -64,8 +68,8 @@ final class GeneralRange<T> implements Serializable {
* Returns everything above the endpoint relative to the specified comparator, with the specified
* endpoint behavior.
*/
- static <T> GeneralRange<T> downTo(Comparator<? super T> comparator, @Nullable T endpoint,
- BoundType boundType) {
+ static <T> GeneralRange<T> downTo(
+ Comparator<? super T> comparator, @Nullable T endpoint, BoundType boundType) {
return new GeneralRange<T>(comparator, true, endpoint, boundType, false, null, OPEN);
}
@@ -73,8 +77,8 @@ final class GeneralRange<T> implements Serializable {
* Returns everything below the endpoint relative to the specified comparator, with the specified
* endpoint behavior.
*/
- static <T> GeneralRange<T> upTo(Comparator<? super T> comparator, @Nullable T endpoint,
- BoundType boundType) {
+ static <T> GeneralRange<T> upTo(
+ Comparator<? super T> comparator, @Nullable T endpoint, BoundType boundType) {
return new GeneralRange<T>(comparator, false, null, OPEN, true, endpoint, boundType);
}
@@ -82,24 +86,31 @@ final class GeneralRange<T> implements Serializable {
* Returns everything between the endpoints relative to the specified comparator, with the
* specified endpoint behavior.
*/
- static <T> GeneralRange<T> range(Comparator<? super T> comparator, @Nullable T lower,
- BoundType lowerType, @Nullable T upper, BoundType upperType) {
+ static <T> GeneralRange<T> range(
+ Comparator<? super T> comparator,
+ @Nullable T lower,
+ BoundType lowerType,
+ @Nullable T upper,
+ BoundType upperType) {
return new GeneralRange<T>(comparator, true, lower, lowerType, true, upper, upperType);
}
private final Comparator<? super T> comparator;
private final boolean hasLowerBound;
- @Nullable
- private final T lowerEndpoint;
+ @Nullable private final T lowerEndpoint;
private final BoundType lowerBoundType;
private final boolean hasUpperBound;
- @Nullable
- private final T upperEndpoint;
+ @Nullable private final T upperEndpoint;
private final BoundType upperBoundType;
- private GeneralRange(Comparator<? super T> comparator, boolean hasLowerBound,
- @Nullable T lowerEndpoint, BoundType lowerBoundType, boolean hasUpperBound,
- @Nullable T upperEndpoint, BoundType upperBoundType) {
+ private GeneralRange(
+ Comparator<? super T> comparator,
+ boolean hasLowerBound,
+ @Nullable T lowerEndpoint,
+ BoundType lowerBoundType,
+ boolean hasUpperBound,
+ @Nullable T upperEndpoint,
+ BoundType upperBoundType) {
this.comparator = checkNotNull(comparator);
this.hasLowerBound = hasLowerBound;
this.hasUpperBound = hasUpperBound;
@@ -117,8 +128,8 @@ final class GeneralRange<T> implements Serializable {
if (hasLowerBound && hasUpperBound) {
int cmp = comparator.compare(lowerEndpoint, upperEndpoint);
// be consistent with Range
- checkArgument(cmp <= 0, "lowerEndpoint (%s) > upperEndpoint (%s)", lowerEndpoint,
- upperEndpoint);
+ checkArgument(
+ cmp <= 0, "lowerEndpoint (%s) > upperEndpoint (%s)", lowerEndpoint, upperEndpoint);
if (cmp == 0) {
checkArgument(lowerBoundType != OPEN | upperBoundType != OPEN);
}
@@ -172,8 +183,7 @@ final class GeneralRange<T> implements Serializable {
checkArgument(comparator.equals(other.comparator));
boolean hasLowBound = this.hasLowerBound;
- @Nullable
- T lowEnd = getLowerEndpoint();
+ @Nullable T lowEnd = getLowerEndpoint();
BoundType lowType = getLowerBoundType();
if (!hasLowerBound()) {
hasLowBound = other.hasLowerBound;
@@ -188,8 +198,7 @@ final class GeneralRange<T> implements Serializable {
}
boolean hasUpBound = this.hasUpperBound;
- @Nullable
- T upEnd = getUpperEndpoint();
+ @Nullable T upEnd = getUpperEndpoint();
BoundType upType = getUpperBoundType();
if (!hasUpperBound()) {
hasUpBound = other.hasUpperBound;
@@ -220,8 +229,10 @@ final class GeneralRange<T> implements Serializable {
public boolean equals(@Nullable Object obj) {
if (obj instanceof GeneralRange) {
GeneralRange<?> r = (GeneralRange<?>) obj;
- return comparator.equals(r.comparator) && hasLowerBound == r.hasLowerBound
- && hasUpperBound == r.hasUpperBound && getLowerBoundType().equals(r.getLowerBoundType())
+ return comparator.equals(r.comparator)
+ && hasLowerBound == r.hasLowerBound
+ && hasUpperBound == r.hasUpperBound
+ && getLowerBoundType().equals(r.getLowerBoundType())
&& getUpperBoundType().equals(r.getUpperBoundType())
&& Objects.equal(getLowerEndpoint(), r.getLowerEndpoint())
&& Objects.equal(getUpperEndpoint(), r.getUpperEndpoint());
@@ -231,7 +242,11 @@ final class GeneralRange<T> implements Serializable {
@Override
public int hashCode() {
- return Objects.hashCode(comparator, getLowerEndpoint(), getLowerBoundType(), getUpperEndpoint(),
+ return Objects.hashCode(
+ comparator,
+ getLowerEndpoint(),
+ getLowerBoundType(),
+ getUpperEndpoint(),
getUpperBoundType());
}
@@ -244,8 +259,13 @@ final class GeneralRange<T> implements Serializable {
GeneralRange<T> result = reverse;
if (result == null) {
result = new GeneralRange<T>(
- Ordering.from(comparator).reverse(), hasUpperBound, getUpperEndpoint(),
- getUpperBoundType(), hasLowerBound, getLowerEndpoint(), getLowerBoundType());
+ Ordering.from(comparator).reverse(),
+ hasUpperBound,
+ getUpperEndpoint(),
+ getUpperBoundType(),
+ hasLowerBound,
+ getLowerEndpoint(),
+ getLowerBoundType());
result.reverse = this;
return this.reverse = result;
}
diff --git a/guava/src/com/google/common/collect/GenericMapMaker.java b/guava/src/com/google/common/collect/GenericMapMaker.java
index 77ac673..c951c6c 100644
--- a/guava/src/com/google/common/collect/GenericMapMaker.java
+++ b/guava/src/com/google/common/collect/GenericMapMaker.java
@@ -41,7 +41,7 @@ import java.util.concurrent.TimeUnit;
* com.google.common.cache.CacheBuilder}, which is a properly generified class and thus needs no
* "Generic" equivalent; simple use {@code CacheBuilder} naturally. For general migration
* instructions, see the <a
- * href="http://code.google.com/p/guava-libraries/wiki/MapMakerMigration">MapMaker Migration
+ * href="https://github.com/google/guava/wiki/MapMakerMigration">MapMaker Migration
* Guide</a>.
*/
@Beta
@@ -102,12 +102,11 @@ abstract class GenericMapMaker<K0, V0> {
* @deprecated Caching functionality in {@code MapMaker} has been moved to {@link
* com.google.common.cache.CacheBuilder}, with {@link #softValues} being replaced by {@link
* com.google.common.cache.CacheBuilder#softValues}. Note that {@code CacheBuilder} is simply
- * an enhanced API for an implementation which was branched from {@code MapMaker}. <b>This
- * method is scheduled for removal in March 2015.</b>
+ * an enhanced API for an implementation which was branched from {@code MapMaker}.
*/
@Deprecated
@GwtIncompatible("java.lang.ref.SoftReference")
- public abstract GenericMapMaker<K0, V0> softValues();
+ abstract GenericMapMaker<K0, V0> softValues();
/**
* See {@link MapMaker#expireAfterWrite}.
diff --git a/guava/src/com/google/common/collect/GwtTransient.java b/guava/src/com/google/common/collect/GwtTransient.java
index a9a15e9..1719456 100644
--- a/guava/src/com/google/common/collect/GwtTransient.java
+++ b/guava/src/com/google/common/collect/GwtTransient.java
@@ -34,5 +34,4 @@ import java.lang.annotation.Target;
@GwtCompatible
@Retention(RUNTIME)
@Target(FIELD)
- at interface GwtTransient {
-}
+ at interface GwtTransient {}
diff --git a/guava/src/com/google/common/collect/HashBasedTable.java b/guava/src/com/google/common/collect/HashBasedTable.java
index caf213c..b58d600 100644
--- a/guava/src/com/google/common/collect/HashBasedTable.java
+++ b/guava/src/com/google/common/collect/HashBasedTable.java
@@ -44,9 +44,9 @@ import javax.annotation.Nullable;
* <p>Note that this implementation is not synchronized. If multiple threads
* access this table concurrently and one of the threads modifies the table, it
* must be synchronized externally.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#table">
* {@code Table}</a>.
*
* @author Jared Levy
@@ -54,16 +54,18 @@ import javax.annotation.Nullable;
*/
@GwtCompatible(serializable = true)
public class HashBasedTable<R, C, V> extends StandardTable<R, C, V> {
- private static class Factory<C, V>
- implements Supplier<Map<C, V>>, Serializable {
+ private static class Factory<C, V> implements Supplier<Map<C, V>>, Serializable {
final int expectedSize;
+
Factory(int expectedSize) {
this.expectedSize = expectedSize;
}
+
@Override
public Map<C, V> get() {
return Maps.newHashMapWithExpectedSize(expectedSize);
}
+
private static final long serialVersionUID = 0;
}
@@ -71,8 +73,7 @@ public class HashBasedTable<R, C, V> extends StandardTable<R, C, V> {
* Creates an empty {@code HashBasedTable}.
*/
public static <R, C, V> HashBasedTable<R, C, V> create() {
- return new HashBasedTable<R, C, V>(
- new HashMap<R, Map<C, V>>(), new Factory<C, V>(0));
+ return new HashBasedTable<R, C, V>(new HashMap<R, Map<C, V>>(), new Factory<C, V>(0));
}
/**
@@ -87,10 +88,8 @@ public class HashBasedTable<R, C, V> extends StandardTable<R, C, V> {
public static <R, C, V> HashBasedTable<R, C, V> create(
int expectedRows, int expectedCellsPerRow) {
checkNonnegative(expectedCellsPerRow, "expectedCellsPerRow");
- Map<R, Map<C, V>> backingMap =
- Maps.newHashMapWithExpectedSize(expectedRows);
- return new HashBasedTable<R, C, V>(
- backingMap, new Factory<C, V>(expectedCellsPerRow));
+ Map<R, Map<C, V>> backingMap = Maps.newHashMapWithExpectedSize(expectedRows);
+ return new HashBasedTable<R, C, V>(backingMap, new Factory<C, V>(expectedCellsPerRow));
}
/**
@@ -114,33 +113,38 @@ public class HashBasedTable<R, C, V> extends StandardTable<R, C, V> {
// Overriding so NullPointerTester test passes.
- @Override public boolean contains(
- @Nullable Object rowKey, @Nullable Object columnKey) {
+ @Override
+ public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
return super.contains(rowKey, columnKey);
}
- @Override public boolean containsColumn(@Nullable Object columnKey) {
+ @Override
+ public boolean containsColumn(@Nullable Object columnKey) {
return super.containsColumn(columnKey);
}
- @Override public boolean containsRow(@Nullable Object rowKey) {
+ @Override
+ public boolean containsRow(@Nullable Object rowKey) {
return super.containsRow(rowKey);
}
- @Override public boolean containsValue(@Nullable Object value) {
+ @Override
+ public boolean containsValue(@Nullable Object value) {
return super.containsValue(value);
}
- @Override public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
+ @Override
+ public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
return super.get(rowKey, columnKey);
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
return super.equals(obj);
}
- @Override public V remove(
- @Nullable Object rowKey, @Nullable Object columnKey) {
+ @Override
+ public V remove(@Nullable Object rowKey, @Nullable Object columnKey) {
return super.remove(rowKey, columnKey);
}
diff --git a/guava/src/com/google/common/collect/HashBiMap.java b/guava/src/com/google/common/collect/HashBiMap.java
index c597de6..e2738fe 100644
--- a/guava/src/com/google/common/collect/HashBiMap.java
+++ b/guava/src/com/google/common/collect/HashBiMap.java
@@ -17,10 +17,13 @@ package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import static com.google.common.collect.CollectPreconditions.checkRemove;
+import static com.google.common.collect.Hashing.smearedHash;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Objects;
+import com.google.common.collect.Maps.IteratorBasedAbstractMap;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -41,15 +44,16 @@ import javax.annotation.Nullable;
* {@code HashBiMap} and its inverse are both serializable.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap"> {@code BiMap}
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap"> {@code BiMap}
* </a>.
*
* @author Louis Wasserman
* @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
-public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K, V>, Serializable {
+public final class HashBiMap<K, V> extends IteratorBasedAbstractMap<K, V>
+ implements BiMap<K, V>, Serializable {
/**
* Returns a new, empty {@code HashBiMap} with the default initial capacity (16).
@@ -82,11 +86,11 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
final int keyHash;
final int valueHash;
- @Nullable
- BiEntry<K, V> nextInKToVBucket;
+ @Nullable BiEntry<K, V> nextInKToVBucket;
+ @Nullable BiEntry<K, V> nextInVToKBucket;
- @Nullable
- BiEntry<K, V> nextInVToKBucket;
+ @Nullable BiEntry<K, V> nextInKeyInsertionOrder;
+ @Nullable BiEntry<K, V> prevInKeyInsertionOrder;
BiEntry(K key, int keyHash, V value, int valueHash) {
super(key, value);
@@ -96,9 +100,11 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
}
private static final double LOAD_FACTOR = 1.0;
-
+
private transient BiEntry<K, V>[] hashTableKToV;
private transient BiEntry<K, V>[] hashTableVToK;
+ private transient BiEntry<K, V> firstInKeyInsertionOrder;
+ private transient BiEntry<K, V> lastInKeyInsertionOrder;
private transient int size;
private transient int mask;
private transient int modCount;
@@ -112,9 +118,11 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
int tableSize = Hashing.closedTableSize(expectedSize, LOAD_FACTOR);
this.hashTableKToV = createTable(tableSize);
this.hashTableVToK = createTable(tableSize);
+ this.firstInKeyInsertionOrder = null;
+ this.lastInKeyInsertionOrder = null;
+ this.size = 0;
this.mask = tableSize - 1;
this.modCount = 0;
- this.size = 0;
}
/**
@@ -124,7 +132,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
private void delete(BiEntry<K, V> entry) {
int keyBucket = entry.keyHash & mask;
BiEntry<K, V> prevBucketEntry = null;
- for (BiEntry<K, V> bucketEntry = hashTableKToV[keyBucket]; true;
+ for (BiEntry<K, V> bucketEntry = hashTableKToV[keyBucket];
+ true;
bucketEntry = bucketEntry.nextInKToVBucket) {
if (bucketEntry == entry) {
if (prevBucketEntry == null) {
@@ -139,7 +148,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
int valueBucket = entry.valueHash & mask;
prevBucketEntry = null;
- for (BiEntry<K, V> bucketEntry = hashTableVToK[valueBucket];;
+ for (BiEntry<K, V> bucketEntry = hashTableVToK[valueBucket];
+ true;
bucketEntry = bucketEntry.nextInVToKBucket) {
if (bucketEntry == entry) {
if (prevBucketEntry == null) {
@@ -152,11 +162,23 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
prevBucketEntry = bucketEntry;
}
+ if (entry.prevInKeyInsertionOrder == null) {
+ firstInKeyInsertionOrder = entry.nextInKeyInsertionOrder;
+ } else {
+ entry.prevInKeyInsertionOrder.nextInKeyInsertionOrder = entry.nextInKeyInsertionOrder;
+ }
+
+ if (entry.nextInKeyInsertionOrder == null) {
+ lastInKeyInsertionOrder = entry.prevInKeyInsertionOrder;
+ } else {
+ entry.nextInKeyInsertionOrder.prevInKeyInsertionOrder = entry.prevInKeyInsertionOrder;
+ }
+
size--;
modCount++;
}
- private void insert(BiEntry<K, V> entry) {
+ private void insert(BiEntry<K, V> entry, @Nullable BiEntry<K, V> oldEntryForKey) {
int keyBucket = entry.keyHash & mask;
entry.nextInKToVBucket = hashTableKToV[keyBucket];
hashTableKToV[keyBucket] = entry;
@@ -165,16 +187,37 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
entry.nextInVToKBucket = hashTableVToK[valueBucket];
hashTableVToK[valueBucket] = entry;
+ if (oldEntryForKey == null) {
+ entry.prevInKeyInsertionOrder = lastInKeyInsertionOrder;
+ entry.nextInKeyInsertionOrder = null;
+ if (lastInKeyInsertionOrder == null) {
+ firstInKeyInsertionOrder = entry;
+ } else {
+ lastInKeyInsertionOrder.nextInKeyInsertionOrder = entry;
+ }
+ lastInKeyInsertionOrder = entry;
+ } else {
+ entry.prevInKeyInsertionOrder = oldEntryForKey.prevInKeyInsertionOrder;
+ if (entry.prevInKeyInsertionOrder == null) {
+ firstInKeyInsertionOrder = entry;
+ } else {
+ entry.prevInKeyInsertionOrder.nextInKeyInsertionOrder = entry;
+ }
+ entry.nextInKeyInsertionOrder = oldEntryForKey.nextInKeyInsertionOrder;
+ if (entry.nextInKeyInsertionOrder == null) {
+ lastInKeyInsertionOrder = entry;
+ } else {
+ entry.nextInKeyInsertionOrder.prevInKeyInsertionOrder = entry;
+ }
+ }
+
size++;
modCount++;
}
- private static int hash(@Nullable Object o) {
- return Hashing.smear((o == null) ? 0 : o.hashCode());
- }
-
private BiEntry<K, V> seekByKey(@Nullable Object key, int keyHash) {
- for (BiEntry<K, V> entry = hashTableKToV[keyHash & mask]; entry != null;
+ for (BiEntry<K, V> entry = hashTableKToV[keyHash & mask];
+ entry != null;
entry = entry.nextInKToVBucket) {
if (keyHash == entry.keyHash && Objects.equal(key, entry.key)) {
return entry;
@@ -184,7 +227,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
}
private BiEntry<K, V> seekByValue(@Nullable Object value, int valueHash) {
- for (BiEntry<K, V> entry = hashTableVToK[valueHash & mask]; entry != null;
+ for (BiEntry<K, V> entry = hashTableVToK[valueHash & mask];
+ entry != null;
entry = entry.nextInVToKBucket) {
if (valueHash == entry.valueHash && Objects.equal(value, entry.value)) {
return entry;
@@ -195,19 +239,18 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
@Override
public boolean containsKey(@Nullable Object key) {
- return seekByKey(key, hash(key)) != null;
+ return seekByKey(key, smearedHash(key)) != null;
}
@Override
public boolean containsValue(@Nullable Object value) {
- return seekByValue(value, hash(value)) != null;
+ return seekByValue(value, smearedHash(value)) != null;
}
@Nullable
@Override
public V get(@Nullable Object key) {
- BiEntry<K, V> entry = seekByKey(key, hash(key));
- return (entry == null) ? null : entry.value;
+ return Maps.valueOrNull(seekByKey(key, smearedHash(key)));
}
@Override
@@ -221,11 +264,12 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
}
private V put(@Nullable K key, @Nullable V value, boolean force) {
- int keyHash = hash(key);
- int valueHash = hash(value);
+ int keyHash = smearedHash(key);
+ int valueHash = smearedHash(value);
BiEntry<K, V> oldEntryForKey = seekByKey(key, keyHash);
- if (oldEntryForKey != null && valueHash == oldEntryForKey.valueHash
+ if (oldEntryForKey != null
+ && valueHash == oldEntryForKey.valueHash
&& Objects.equal(value, oldEntryForKey.value)) {
return value;
}
@@ -239,22 +283,29 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
}
}
+ BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash);
if (oldEntryForKey != null) {
delete(oldEntryForKey);
+ insert(newEntry, oldEntryForKey);
+ oldEntryForKey.prevInKeyInsertionOrder = null;
+ oldEntryForKey.nextInKeyInsertionOrder = null;
+ rehashIfNecessary();
+ return oldEntryForKey.value;
+ } else {
+ insert(newEntry, null);
+ rehashIfNecessary();
+ return null;
}
- BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash);
- insert(newEntry);
- rehashIfNecessary();
- return (oldEntryForKey == null) ? null : oldEntryForKey.value;
}
@Nullable
private K putInverse(@Nullable V value, @Nullable K key, boolean force) {
- int valueHash = hash(value);
- int keyHash = hash(key);
+ int valueHash = smearedHash(value);
+ int keyHash = smearedHash(key);
BiEntry<K, V> oldEntryForValue = seekByValue(value, valueHash);
- if (oldEntryForValue != null && keyHash == oldEntryForValue.keyHash
+ if (oldEntryForValue != null
+ && keyHash == oldEntryForValue.keyHash
&& Objects.equal(key, oldEntryForValue.key)) {
return key;
}
@@ -272,9 +323,13 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
delete(oldEntryForValue);
}
BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash);
- insert(newEntry);
+ insert(newEntry, oldEntryForKey);
+ if (oldEntryForKey != null) {
+ oldEntryForKey.prevInKeyInsertionOrder = null;
+ oldEntryForKey.nextInKeyInsertionOrder = null;
+ }
rehashIfNecessary();
- return (oldEntryForValue == null) ? null : oldEntryForValue.key;
+ return Maps.keyOrNull(oldEntryForValue);
}
private void rehashIfNecessary() {
@@ -287,13 +342,10 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
this.mask = newTableSize - 1;
this.size = 0;
- for (int bucket = 0; bucket < oldKToV.length; bucket++) {
- BiEntry<K, V> entry = oldKToV[bucket];
- while (entry != null) {
- BiEntry<K, V> nextEntry = entry.nextInKToVBucket;
- insert(entry);
- entry = nextEntry;
- }
+ for (BiEntry<K, V> entry = firstInKeyInsertionOrder;
+ entry != null;
+ entry = entry.nextInKeyInsertionOrder) {
+ insert(entry, entry);
}
this.modCount++;
}
@@ -306,11 +358,13 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
@Override
public V remove(@Nullable Object key) {
- BiEntry<K, V> entry = seekByKey(key, hash(key));
+ BiEntry<K, V> entry = seekByKey(key, smearedHash(key));
if (entry == null) {
return null;
} else {
delete(entry);
+ entry.prevInKeyInsertionOrder = null;
+ entry.nextInKeyInsertionOrder = null;
return entry.value;
}
}
@@ -320,6 +374,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
size = 0;
Arrays.fill(hashTableKToV, null);
Arrays.fill(hashTableVToK, null);
+ firstInKeyInsertionOrder = null;
+ lastInKeyInsertionOrder = null;
modCount++;
}
@@ -329,49 +385,35 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
}
abstract class Itr<T> implements Iterator<T> {
- int nextBucket = 0;
- BiEntry<K, V> next = null;
+ BiEntry<K, V> next = firstInKeyInsertionOrder;
BiEntry<K, V> toRemove = null;
int expectedModCount = modCount;
- private void checkForConcurrentModification() {
- if (modCount != expectedModCount) {
- throw new ConcurrentModificationException();
- }
- }
-
@Override
public boolean hasNext() {
- checkForConcurrentModification();
- if (next != null) {
- return true;
- }
- while (nextBucket < hashTableKToV.length) {
- if (hashTableKToV[nextBucket] != null) {
- next = hashTableKToV[nextBucket++];
- return true;
- }
- nextBucket++;
+ if (modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
}
- return false;
+ return next != null;
}
@Override
public T next() {
- checkForConcurrentModification();
if (!hasNext()) {
throw new NoSuchElementException();
}
BiEntry<K, V> entry = next;
- next = entry.nextInKToVBucket;
+ next = entry.nextInKeyInsertionOrder;
toRemove = entry;
return output(entry);
}
@Override
public void remove() {
- checkForConcurrentModification();
+ if (modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
+ }
checkRemove(toRemove != null);
delete(toRemove);
expectedModCount = modCount;
@@ -386,6 +428,7 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
return new KeySet();
}
+ @WeakOuter
private final class KeySet extends Maps.KeySet<K, V> {
KeySet() {
super(HashBiMap.this);
@@ -403,11 +446,13 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
@Override
public boolean remove(@Nullable Object o) {
- BiEntry<K, V> entry = seekByKey(o, hash(o));
+ BiEntry<K, V> entry = seekByKey(o, smearedHash(o));
if (entry == null) {
return false;
} else {
delete(entry);
+ entry.prevInKeyInsertionOrder = null;
+ entry.nextInKeyInsertionOrder = null;
return true;
}
}
@@ -419,61 +464,53 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
}
@Override
- public Set<Entry<K, V>> entrySet() {
- return new EntrySet();
- }
+ Iterator<Entry<K, V>> entryIterator() {
+ return new Itr<Entry<K, V>>() {
+ @Override
+ Entry<K, V> output(BiEntry<K, V> entry) {
+ return new MapEntry(entry);
+ }
- private final class EntrySet extends Maps.EntrySet<K, V> {
- @Override
- Map<K, V> map() {
- return HashBiMap.this;
- }
+ class MapEntry extends AbstractMapEntry<K, V> {
+ BiEntry<K, V> delegate;
- @Override
- public Iterator<Entry<K, V>> iterator() {
- return new Itr<Entry<K, V>>() {
- @Override
- Entry<K, V> output(BiEntry<K, V> entry) {
- return new MapEntry(entry);
+ MapEntry(BiEntry<K, V> entry) {
+ this.delegate = entry;
}
- class MapEntry extends AbstractMapEntry<K, V> {
- BiEntry<K, V> delegate;
-
- MapEntry(BiEntry<K, V> entry) {
- this.delegate = entry;
- }
+ @Override
+ public K getKey() {
+ return delegate.key;
+ }
- @Override public K getKey() {
- return delegate.key;
- }
+ @Override
+ public V getValue() {
+ return delegate.value;
+ }
- @Override public V getValue() {
- return delegate.value;
+ @Override
+ public V setValue(V value) {
+ V oldValue = delegate.value;
+ int valueHash = smearedHash(value);
+ if (valueHash == delegate.valueHash && Objects.equal(value, oldValue)) {
+ return value;
}
-
- @Override public V setValue(V value) {
- V oldValue = delegate.value;
- int valueHash = hash(value);
- if (valueHash == delegate.valueHash && Objects.equal(value, oldValue)) {
- return value;
- }
- checkArgument(
- seekByValue(value, valueHash) == null, "value already present: %s", value);
- delete(delegate);
- BiEntry<K, V> newEntry =
- new BiEntry<K, V>(delegate.key, delegate.keyHash, value, valueHash);
- insert(newEntry);
- expectedModCount = modCount;
- if (toRemove == delegate) {
- toRemove = newEntry;
- }
- delegate = newEntry;
- return oldValue;
+ checkArgument(seekByValue(value, valueHash) == null, "value already present: %s", value);
+ delete(delegate);
+ BiEntry<K, V> newEntry =
+ new BiEntry<K, V>(delegate.key, delegate.keyHash, value, valueHash);
+ insert(newEntry, delegate);
+ delegate.prevInKeyInsertionOrder = null;
+ delegate.nextInKeyInsertionOrder = null;
+ expectedModCount = modCount;
+ if (toRemove == delegate) {
+ toRemove = newEntry;
}
+ delegate = newEntry;
+ return oldValue;
}
- };
- }
+ }
+ };
}
private transient BiMap<V, K> inverse;
@@ -505,8 +542,7 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
@Override
public K get(@Nullable Object value) {
- BiEntry<K, V> entry = seekByValue(value, hash(value));
- return (entry == null) ? null : entry.key;
+ return Maps.keyOrNull(seekByValue(value, smearedHash(value)));
}
@Override
@@ -521,11 +557,13 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
@Override
public K remove(@Nullable Object value) {
- BiEntry<K, V> entry = seekByValue(value, hash(value));
+ BiEntry<K, V> entry = seekByValue(value, smearedHash(value));
if (entry == null) {
return null;
} else {
delete(entry);
+ entry.prevInKeyInsertionOrder = null;
+ entry.nextInKeyInsertionOrder = null;
return entry.key;
}
}
@@ -540,6 +578,7 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
return new InverseKeySet();
}
+ @WeakOuter
private final class InverseKeySet extends Maps.KeySet<V, K> {
InverseKeySet() {
super(Inverse.this);
@@ -547,7 +586,7 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
@Override
public boolean remove(@Nullable Object o) {
- BiEntry<K, V> entry = seekByValue(o, hash(o));
+ BiEntry<K, V> entry = seekByValue(o, smearedHash(o));
if (entry == null) {
return false;
} else {
@@ -559,7 +598,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
@Override
public Iterator<V> iterator() {
return new Itr<V>() {
- @Override V output(BiEntry<K, V> entry) {
+ @Override
+ V output(BiEntry<K, V> entry) {
return entry.value;
}
};
@@ -608,7 +648,7 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
@Override
public K setValue(K key) {
K oldKey = delegate.key;
- int keyHash = hash(key);
+ int keyHash = smearedHash(key);
if (keyHash == delegate.keyHash && Objects.equal(key, oldKey)) {
return key;
}
@@ -616,7 +656,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
delete(delegate);
BiEntry<K, V> newEntry =
new BiEntry<K, V>(key, keyHash, delegate.value, delegate.valueHash);
- insert(newEntry);
+ delegate = newEntry;
+ insert(newEntry, null);
expectedModCount = modCount;
// This is safe because entries can only get bumped up to earlier in the iteration,
// so they can't get revisited.
@@ -657,8 +698,8 @@ public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K,
@GwtIncompatible("java.io.ObjectInputStream")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
+ init(16);
int size = Serialization.readCount(stream);
- init(size);
Serialization.populateMap(this, stream, size);
}
diff --git a/guava/src/com/google/common/collect/HashMultimap.java b/guava/src/com/google/common/collect/HashMultimap.java
index bab2a05..36dd385 100644
--- a/guava/src/com/google/common/collect/HashMultimap.java
+++ b/guava/src/com/google/common/collect/HashMultimap.java
@@ -44,14 +44,13 @@ import java.util.Set;
* Multimaps#synchronizedSetMultimap}.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
private static final int DEFAULT_VALUES_PER_KEY = 2;
- @VisibleForTesting
- transient int expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
+ @VisibleForTesting transient int expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
/**
* Creates a new, empty {@code HashMultimap} with the default initial
@@ -70,8 +69,7 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
* @throws IllegalArgumentException if {@code expectedKeys} or {@code
* expectedValuesPerKey} is negative
*/
- public static <K, V> HashMultimap<K, V> create(
- int expectedKeys, int expectedValuesPerKey) {
+ public static <K, V> HashMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
return new HashMultimap<K, V>(expectedKeys, expectedValuesPerKey);
}
@@ -82,8 +80,7 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
*
* @param multimap the multimap whose contents are copied to this multimap
*/
- public static <K, V> HashMultimap<K, V> create(
- Multimap<? extends K, ? extends V> multimap) {
+ public static <K, V> HashMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
return new HashMultimap<K, V>(multimap);
}
@@ -98,8 +95,7 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
}
private HashMultimap(Multimap<? extends K, ? extends V> multimap) {
- super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(
- multimap.keySet().size()));
+ super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(multimap.keySet().size()));
putAll(multimap);
}
@@ -110,7 +106,8 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
*
* @return a new {@code HashSet} containing a collection of values for one key
*/
- @Override Set<V> createCollection() {
+ @Override
+ Set<V> createCollection() {
return Sets.<V>newHashSetWithExpectedSize(expectedValuesPerKey);
}
@@ -122,17 +119,15 @@ public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
- stream.writeInt(expectedValuesPerKey);
Serialization.writeMultimap(this, stream);
}
@GwtIncompatible("java.io.ObjectInputStream")
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
- expectedValuesPerKey = stream.readInt();
+ expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
int distinctKeys = Serialization.readCount(stream);
- Map<K, Collection<V>> map = Maps.newHashMapWithExpectedSize(distinctKeys);
+ Map<K, Collection<V>> map = Maps.newHashMap();
setMap(map);
Serialization.populateMultimap(this, stream, distinctKeys);
}
diff --git a/guava/src/com/google/common/collect/HashMultiset.java b/guava/src/com/google/common/collect/HashMultiset.java
index 51cf7fb..c2a79ff 100644
--- a/guava/src/com/google/common/collect/HashMultiset.java
+++ b/guava/src/com/google/common/collect/HashMultiset.java
@@ -29,7 +29,7 @@ import java.util.HashMap;
*
* @author Kevin Bourrillion
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
public final class HashMultiset<E> extends AbstractMapBasedMultiset<E> {
@@ -55,15 +55,14 @@ public final class HashMultiset<E> extends AbstractMapBasedMultiset<E> {
/**
* Creates a new {@code HashMultiset} containing the specified elements.
- *
+ *
* <p>This implementation is highly efficient when {@code elements} is itself
* a {@link Multiset}.
- *
+ *
* @param elements the elements that the multiset should contain
*/
public static <E> HashMultiset<E> create(Iterable<? extends E> elements) {
- HashMultiset<E> multiset =
- create(Multisets.inferDistinctElements(elements));
+ HashMultiset<E> multiset = create(Multisets.inferDistinctElements(elements));
Iterables.addAll(multiset, elements);
return multiset;
}
@@ -87,12 +86,10 @@ public final class HashMultiset<E> extends AbstractMapBasedMultiset<E> {
}
@GwtIncompatible("java.io.ObjectInputStream")
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
int distinctElements = Serialization.readCount(stream);
- setBackingMap(
- Maps.<E, Count>newHashMapWithExpectedSize(distinctElements));
+ setBackingMap(Maps.<E, Count>newHashMap());
Serialization.populateMultiset(this, stream, distinctElements);
}
diff --git a/guava/src/com/google/common/collect/Hashing.java b/guava/src/com/google/common/collect/Hashing.java
index e3957dc..2220007 100644
--- a/guava/src/com/google/common/collect/Hashing.java
+++ b/guava/src/com/google/common/collect/Hashing.java
@@ -46,13 +46,13 @@ final class Hashing {
static int smear(int hashCode) {
return C2 * Integer.rotateLeft(hashCode * C1, 15);
}
-
+
static int smearedHash(@Nullable Object o) {
return smear((o == null) ? 0 : o.hashCode());
}
-
+
private static int MAX_TABLE_SIZE = Ints.MAX_POWER_OF_TWO;
-
+
static int closedTableSize(int expectedEntries, double loadFactor) {
// Get the recommended table size.
// Round down to the nearest power of 2.
@@ -65,7 +65,7 @@ final class Hashing {
}
return tableSize;
}
-
+
static boolean needsResizing(int size, int tableSize, double loadFactor) {
return size > loadFactor * tableSize && tableSize < MAX_TABLE_SIZE;
}
diff --git a/guava/src/com/google/common/collect/ImmutableAsList.java b/guava/src/com/google/common/collect/ImmutableAsList.java
index 249abee..ff123e5 100644
--- a/guava/src/com/google/common/collect/ImmutableAsList.java
+++ b/guava/src/com/google/common/collect/ImmutableAsList.java
@@ -35,7 +35,8 @@ import java.io.Serializable;
abstract class ImmutableAsList<E> extends ImmutableList<E> {
abstract ImmutableCollection<E> delegateCollection();
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// The collection's contains() is at least as fast as ImmutableList's
// and is often faster.
return delegateCollection().contains(target);
@@ -62,23 +63,26 @@ abstract class ImmutableAsList<E> extends ImmutableList<E> {
@GwtIncompatible("serialization")
static class SerializedForm implements Serializable {
final ImmutableCollection<?> collection;
+
SerializedForm(ImmutableCollection<?> collection) {
this.collection = collection;
}
+
Object readResolve() {
return collection.asList();
}
+
private static final long serialVersionUID = 0;
}
@GwtIncompatible("serialization")
- private void readObject(ObjectInputStream stream)
- throws InvalidObjectException {
+ private void readObject(ObjectInputStream stream) throws InvalidObjectException {
throw new InvalidObjectException("Use SerializedForm");
}
@GwtIncompatible("serialization")
- @Override Object writeReplace() {
+ @Override
+ Object writeReplace() {
return new SerializedForm(delegateCollection());
}
}
diff --git a/guava/src/com/google/common/collect/ImmutableBiMap.java b/guava/src/com/google/common/collect/ImmutableBiMap.java
index e3a8a9b..2c531b3 100644
--- a/guava/src/com/google/common/collect/ImmutableBiMap.java
+++ b/guava/src/com/google/common/collect/ImmutableBiMap.java
@@ -16,30 +16,22 @@
package com.google.common.collect;
+import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.Map;
/**
- * An immutable {@link BiMap} with reliable user-specified iteration order. Does
- * not permit null keys or values. An {@code ImmutableBiMap} and its inverse
- * have the same iteration ordering.
- *
- * <p>An instance of {@code ImmutableBiMap} contains its own data and will
- * <i>never</i> change. {@code ImmutableBiMap} is convenient for
- * {@code public static final} maps ("constant maps") and also lets you easily
- * make a "defensive copy" of a bimap provided to your class by a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class are
- * guaranteed to be immutable.
+ * A {@link BiMap} whose contents will never change, with many other important properties detailed
+ * at {@link ImmutableCollection}.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
-public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
- implements BiMap<K, V> {
+public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> implements BiMap<K, V> {
/**
* Returns the empty bimap.
@@ -47,7 +39,7 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
// Casting to any type is safe because the set will never hold any elements.
@SuppressWarnings("unchecked")
public static <K, V> ImmutableBiMap<K, V> of() {
- return (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE;
+ return (ImmutableBiMap<K, V>) RegularImmutableBiMap.EMPTY;
}
/**
@@ -63,7 +55,7 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
* @throws IllegalArgumentException if duplicate keys or values are added
*/
public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) {
- return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2));
+ return RegularImmutableBiMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2));
}
/**
@@ -71,9 +63,8 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
*
* @throws IllegalArgumentException if duplicate keys or values are added
*/
- public static <K, V> ImmutableBiMap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3) {
- return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
+ public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
+ return RegularImmutableBiMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
}
/**
@@ -81,10 +72,9 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
*
* @throws IllegalArgumentException if duplicate keys or values are added
*/
- public static <K, V> ImmutableBiMap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
- return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3),
- entryOf(k4, v4));
+ public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+ return RegularImmutableBiMap.fromEntries(
+ entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4));
}
/**
@@ -94,8 +84,8 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
*/
public static <K, V> ImmutableBiMap<K, V> of(
K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
- return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3),
- entryOf(k4, v4), entryOf(k5, v5));
+ return RegularImmutableBiMap.fromEntries(
+ entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
}
// looking for of() with > 5 entries? Use the builder instead.
@@ -126,7 +116,7 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
* multiple times to build multiple bimaps in series. Each bimap is a superset
* of the bimaps created before it.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> {
@@ -136,40 +126,109 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
*/
public Builder() {}
+ Builder(int size) {
+ super(size);
+ }
+
/**
* Associates {@code key} with {@code value} in the built bimap. Duplicate
* keys or values are not allowed, and will cause {@link #build} to fail.
*/
- @Override public Builder<K, V> put(K key, V value) {
+ @Override
+ public Builder<K, V> put(K key, V value) {
super.put(key, value);
return this;
}
/**
+ * Adds the given {@code entry} to the bimap. Duplicate keys or values
+ * are not allowed, and will cause {@link #build} to fail.
+ *
+ * @since 19.0
+ */
+ @Override
+ public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
+ super.put(entry);
+ return this;
+ }
+
+ /**
* Associates all of the given map's keys and values in the built bimap.
* Duplicate keys or values are not allowed, and will cause {@link #build}
* to fail.
*
* @throws NullPointerException if any key or value in {@code map} is null
*/
- @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
+ @Override
+ public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
super.putAll(map);
return this;
}
/**
+ * Adds all of the given entries to the built bimap. Duplicate keys or
+ * values are not allowed, and will cause {@link #build} to fail.
+ *
+ * @throws NullPointerException if any key, value, or entry is null
+ * @since 19.0
+ */
+ @Beta
+ @Override
+ public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ super.putAll(entries);
+ return this;
+ }
+
+ /**
+ * Configures this {@code Builder} to order entries by value according to the specified
+ * comparator.
+ *
+ * <p>The sort order is stable, that is, if two entries have values that compare
+ * as equivalent, the entry that was inserted first will be first in the built map's
+ * iteration order.
+ *
+ * @throws IllegalStateException if this method was already called
+ * @since 19.0
+ */
+ @Beta
+ @Override
+ public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
+ super.orderEntriesByValue(valueComparator);
+ return this;
+ }
+
+ /**
* Returns a newly-created immutable bimap.
*
* @throws IllegalArgumentException if duplicate keys or values were added
*/
- @Override public ImmutableBiMap<K, V> build() {
+ @Override
+ public ImmutableBiMap<K, V> build() {
switch (size) {
case 0:
return of();
case 1:
return of(entries[0].getKey(), entries[0].getValue());
default:
- return new RegularImmutableBiMap<K, V>(size, entries);
+ /*
+ * If entries is full, then this implementation may end up using the entries array
+ * directly and writing over the entry objects with non-terminal entries, but this is
+ * safe; if this Builder is used further, it will grow the entries array (so it can't
+ * affect the original array), and future build() calls will always copy any entry
+ * objects that cannot be safely reused.
+ */
+ if (valueComparator != null) {
+ if (entriesUsed) {
+ entries = ObjectArrays.arraysCopyOf(entries, size);
+ }
+ Arrays.sort(
+ entries,
+ 0,
+ size,
+ Ordering.from(valueComparator).onResultOf(Maps.<V>valueFunction()));
+ }
+ entriesUsed = size == entries.length;
+ return RegularImmutableBiMap.fromEntryArray(size, entries);
}
}
}
@@ -187,32 +246,47 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
* @throws IllegalArgumentException if two keys have the same value
* @throws NullPointerException if any key or value in {@code map} is null
*/
- public static <K, V> ImmutableBiMap<K, V> copyOf(
- Map<? extends K, ? extends V> map) {
+ public static <K, V> ImmutableBiMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
if (map instanceof ImmutableBiMap) {
@SuppressWarnings("unchecked") // safe since map is not writable
ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map;
- // TODO(user): if we need to make a copy of a BiMap because the
+ // TODO(lowasser): if we need to make a copy of a BiMap because the
// forward map is a view, don't make a copy of the non-view delegate map
if (!bimap.isPartialView()) {
return bimap;
}
}
- Entry<?, ?>[] entries = map.entrySet().toArray(EMPTY_ENTRY_ARRAY);
- switch (entries.length) {
+ return copyOf(map.entrySet());
+ }
+
+ /**
+ * Returns an immutable bimap containing the given entries.
+ *
+ * @throws IllegalArgumentException if two keys have the same value or two
+ * values have the same key
+ * @throws NullPointerException if any key, value, or entry is null
+ * @since 19.0
+ */
+ @Beta
+ public static <K, V> ImmutableBiMap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ @SuppressWarnings("unchecked") // we'll only be using getKey and getValue, which are covariant
+ Entry<K, V>[] entryArray = (Entry<K, V>[]) Iterables.toArray(entries, EMPTY_ENTRY_ARRAY);
+ switch (entryArray.length) {
case 0:
return of();
case 1:
- @SuppressWarnings("unchecked") // safe covariant cast in this context
- Entry<K, V> entry = (Entry<K, V>) entries[0];
+ Entry<K, V> entry = entryArray[0];
return of(entry.getKey(), entry.getValue());
default:
- return new RegularImmutableBiMap<K, V>(entries);
+ /*
+ * The current implementation will end up using entryArray directly, though it will write
+ * over the (arbitrary, potentially mutable) Entry objects actually stored in entryArray.
+ */
+ return RegularImmutableBiMap.fromEntries(entryArray);
}
}
- private static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0];
-
ImmutableBiMap() {}
/**
@@ -228,7 +302,8 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
* Returns an immutable set of the values in this map. The values are in the
* same order as the parameters used to build this map.
*/
- @Override public ImmutableSet<V> values() {
+ @Override
+ public ImmutableSet<V> values() {
return inverse().keySet();
}
@@ -257,14 +332,18 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
SerializedForm(ImmutableBiMap<?, ?> bimap) {
super(bimap);
}
- @Override Object readResolve() {
+
+ @Override
+ Object readResolve() {
Builder<Object, Object> builder = new Builder<Object, Object>();
return createMap(builder);
}
+
private static final long serialVersionUID = 0;
}
- @Override Object writeReplace() {
+ @Override
+ Object writeReplace() {
return new SerializedForm(this);
}
}
diff --git a/guava/src/com/google/common/collect/ImmutableClassToInstanceMap.java b/guava/src/com/google/common/collect/ImmutableClassToInstanceMap.java
index d99cf87..a74ae5f 100644
--- a/guava/src/com/google/common/collect/ImmutableClassToInstanceMap.java
+++ b/guava/src/com/google/common/collect/ImmutableClassToInstanceMap.java
@@ -26,16 +26,38 @@ import java.util.Map;
import javax.annotation.Nullable;
/**
- * A class-to-instance map backed by an {@link ImmutableMap}. See also {@link
- * MutableClassToInstanceMap}.
+ * A {@link ClassToInstanceMap} whose contents will never change, with many
+ * other important properties detailed at {@link ImmutableCollection}.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
-public final class ImmutableClassToInstanceMap<B>
- extends ForwardingMap<Class<? extends B>, B>
+public final class ImmutableClassToInstanceMap<B> extends ForwardingMap<Class<? extends B>, B>
implements ClassToInstanceMap<B>, Serializable {
-
+
+ private static final ImmutableClassToInstanceMap<Object> EMPTY =
+ new ImmutableClassToInstanceMap<Object>(ImmutableMap.<Class<?>, Object>of());
+
+ /**
+ * Returns an empty {@code ImmutableClassToInstanceMap}.
+ *
+ * @since 19.0
+ */
+ @SuppressWarnings("unchecked")
+ public static <B> ImmutableClassToInstanceMap<B> of() {
+ return (ImmutableClassToInstanceMap<B>) EMPTY;
+ }
+
+ /**
+ * Returns an {@code ImmutableClassToInstanceMap} containing a single entry.
+ *
+ * @since 19.0
+ */
+ public static <B, T extends B> ImmutableClassToInstanceMap<B> of(Class<T> type, T value) {
+ ImmutableMap<Class<? extends B>, B> map = ImmutableMap.<Class<? extends B>, B>of(type, value);
+ return new ImmutableClassToInstanceMap<B>(map);
+ }
+
/**
* Returns a new builder. The generated builder is equivalent to the builder
* created by the {@link Builder} constructor.
@@ -59,11 +81,10 @@ public final class ImmutableClassToInstanceMap<B>
* and build again. Thus each map generated by this builder will be a superset
* of any map generated before it.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public static final class Builder<B> {
- private final ImmutableMap.Builder<Class<? extends B>, B> mapBuilder
- = ImmutableMap.builder();
+ private final ImmutableMap.Builder<Class<? extends B>, B> mapBuilder = ImmutableMap.builder();
/**
* Associates {@code key} with {@code value} in the built map. Duplicate
@@ -82,10 +103,8 @@ public final class ImmutableClassToInstanceMap<B>
* @throws ClassCastException if any value is not an instance of the type
* specified by its key
*/
- public <T extends B> Builder<B> putAll(
- Map<? extends Class<? extends T>, ? extends T> map) {
- for (Entry<? extends Class<? extends T>, ? extends T> entry
- : map.entrySet()) {
+ public <T extends B> Builder<B> putAll(Map<? extends Class<? extends T>, ? extends T> map) {
+ for (Entry<? extends Class<? extends T>, ? extends T> entry : map.entrySet()) {
Class<? extends T> type = entry.getKey();
T value = entry.getValue();
mapBuilder.put(type, cast(type, value));
@@ -104,7 +123,12 @@ public final class ImmutableClassToInstanceMap<B>
* @throws IllegalArgumentException if duplicate keys were added
*/
public ImmutableClassToInstanceMap<B> build() {
- return new ImmutableClassToInstanceMap<B>(mapBuilder.build());
+ ImmutableMap<Class<? extends B>, B> map = mapBuilder.build();
+ if (map.isEmpty()) {
+ return of();
+ } else {
+ return new ImmutableClassToInstanceMap<B>(map);
+ }
}
}
@@ -134,12 +158,12 @@ public final class ImmutableClassToInstanceMap<B>
private final ImmutableMap<Class<? extends B>, B> delegate;
- private ImmutableClassToInstanceMap(
- ImmutableMap<Class<? extends B>, B> delegate) {
+ private ImmutableClassToInstanceMap(ImmutableMap<Class<? extends B>, B> delegate) {
this.delegate = delegate;
}
- @Override protected Map<Class<? extends B>, B> delegate() {
+ @Override
+ protected Map<Class<? extends B>, B> delegate() {
return delegate;
}
@@ -161,4 +185,8 @@ public final class ImmutableClassToInstanceMap<B>
public <T extends B> T putInstance(Class<T> type, T value) {
throw new UnsupportedOperationException();
}
+
+ Object readResolve() {
+ return isEmpty() ? of() : this;
+ }
}
diff --git a/guava/src/com/google/common/collect/ImmutableCollection.java b/guava/src/com/google/common/collect/ImmutableCollection.java
index 1e9f629..606629f 100644
--- a/guava/src/com/google/common/collect/ImmutableCollection.java
+++ b/guava/src/com/google/common/collect/ImmutableCollection.java
@@ -24,28 +24,135 @@ import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
import java.util.AbstractCollection;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
+import java.util.List;
import javax.annotation.Nullable;
/**
- * An immutable collection. Does not permit null elements.
+ * A {@link Collection} whose contents will never change, and which offers a few additional
+ * guarantees detailed below.
*
- * <p>In addition to the {@link Collection} methods, this class has an {@link
- * #asList()} method, which returns a list view of the collection's elements.
+ * <p><b>Warning:</b> avoid <i>direct</i> usage of {@link ImmutableCollection} as a type (just as
+ * with {@link Collection} itself). Prefer subtypes such as {@link ImmutableSet} or {@link
+ * ImmutableList}, which have well-defined {@link #equals} semantics, thus avoiding a common source
+ * of bugs and confusion.
*
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed
- * outside of this package as it has no public or protected constructors. Thus,
- * instances of this type are guaranteed to be immutable.
+ * <h3>About <i>all</i> {@code Immutable-} collections</h3>
*
- * @author Jesse Wilson
- * @since 2.0 (imported from Google Collections Library)
+ * <p>The remainder of this documentation applies to every public {@code Immutable-} type in this
+ * package, whether it is a subtype of {@code ImmutableCollection} or not.
+ *
+ * <h4>Guarantees</h4>
+ *
+ * <p>Each makes the following guarantees:
+ *
+ * <ul>
+ * <li><b>Shallow immutability.</b> Elements can never be added, removed or replaced in this
+ * collection. This is a stronger guarantee than that of
+ * {@link Collections#unmodifiableCollection}, whose contents change whenever the wrapped
+ * collection is modified.
+ * <li><b>Null-hostility.</b> This collection will never contain a null element.
+ * <li><b>Deterministic iteration.</b> The iteration order is always well-defined, depending on how
+ * the collection was created (see the appropriate factory method for details). View collections
+ * such as {@link ImmutableMultiset#elementSet} iterate in the same order as the parent, except
+ * as noted.
+ * <li><b>Thread safety.</b> It is safe to access this collection concurrently from multiple
+ * threads.
+ * <li><b>Integrity.</b> This type cannot be subclassed outside this package (which would allow
+ * these guarantees to be violated).
+ * </ul>
+ *
+ * <h4>"Interfaces", not implementations</h4>
+ *
+ * <p>Each public class, such as {@link ImmutableSet}, is a <i>type</i> offering meaningful
+ * behavioral guarantees -- not merely a specific <i>implementation</i> as in the case of, say,
+ * {@link ArrayList}. You should treat them as interfaces in every important sense of the word.
+ *
+ * <p>For field types and method return types, you should generally use the immutable type (such as
+ * {@link ImmutableList}) instead of the general collection interface type (such as {@link List}).
+ * This communicates to your callers all of the semantic guarantees listed above, which is almost
+ * always very useful information.
+ *
+ * <p>On the other hand, a <i>parameter</i> type of {@link ImmutableList} is generally a nuisance to
+ * callers. Instead, accept {@link Iterable} and have your method or constructor body pass it to the
+ * appropriate {@code copyOf} method itself.
+ *
+ * <h4>Creation</h4>
+ *
+ * <p>Except for logically "abstract" types like {@code ImmutableCollection} itself, each {@code
+ * Immutable} type provides the static operations you need to obtain instances of that type. These
+ * usually include:
+ *
+ * <ul>
+ * <li>Static methods named {@code of}, accepting an explicit list of elements or entries.
+ * <li>Static methods named {@code copyOf} (or {@code copyOfSorted}), accepting an existing
+ * collection whose contents should be copied.
+ * <li>A static nested {@code Builder} class which can be used to populate a new immutable instance.
+ * </ul>
+ *
+ * <h4>Warnings</h4>
+ *
+ * <ul>
+ * <li><b>Warning:</b> as with any collection, it is almost always a bad idea to modify an element
+ * (in a way that affects its {@link Object#equals} behavior) while it is contained in a
+ * collection. Undefined behavior and bugs will result. It's generally best to avoid using
+ * mutable objects as elements at all, as many users may expect your "immutable" object to be
+ * <i>deeply</i> immutable.
+ * </ul>
+ *
+ * <h4>Performance notes</h4>
+ *
+ * <ul>
+ * <li>Implementations can be generally assumed to prioritize memory efficiency, then speed of
+ * access, and lastly speed of creation.
+ * <li>The {@code copyOf} methods will sometimes recognize that the actual copy operation is
+ * unnecessary; for example, {@code copyOf(copyOf(anArrayList))} should copy the data only once.
+ * This reduces the expense of habitually making defensive copies at API boundaries. However,
+ * the precise conditions for skipping the copy operation are undefined.
+ * <li><b>Warning:</b> a view collection such as {@link ImmutableMap#keySet} or {@link
+ * ImmutableList#subList} may retain a reference to the entire data set, preventing it from
+ * being garbage collected. If some of the data is no longer reachable through other means, this
+ * constitutes a memory leak. Pass the view collection to the appropriate {@code copyOf} method
+ * to obtain a correctly-sized copy.
+ * <li>The performance of using the associated {@code Builder} class can be assumed to be
+ * no worse, and possibly better, than creating a mutable collection and copying it.
+ * <li>Implementations generally do not cache hash codes. If your element or key type has a slow
+ * {@code hashCode} implementation, it should cache it itself.
+ * </ul>
+ *
+ * <h4>Example usage</h4>
+ *
+ * <pre> {@code
+ *
+ * class Foo {
+ * private static final ImmutableSet<String> RESERVED_CODES =
+ * ImmutableSet.of("AZ", "CQ", "ZX");
+ *
+ * private final ImmutableSet<String> codes;
+ *
+ * public Foo(Iterable<String> codes) {
+ * this.codes = ImmutableSet.copyOf(codes);
+ * checkArgument(Collections.disjoint(this.codes, RESERVED_CODES));
+ * }
+ * }}</pre>
+ *
+ * <h3>See also</h3>
+ *
+ * <p>See the Guava User Guide article on <a href=
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
+ * immutable collections</a>.
+ *
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
-public abstract class ImmutableCollection<E> extends AbstractCollection<E>
- implements Serializable {
+// TODO(kevinb): I think we should push everything down to "BaseImmutableCollection" or something,
+// just to do everything we can to emphasize the "practically an interface" nature of this class.
+public abstract class ImmutableCollection<E> extends AbstractCollection<E> implements Serializable {
ImmutableCollection() {}
@@ -80,9 +187,7 @@ public abstract class ImmutableCollection<E> extends AbstractCollection<E>
}
@Override
- public boolean contains(@Nullable Object object) {
- return object != null && super.contains(object);
- }
+ public abstract boolean contains(@Nullable Object object);
/**
* Guaranteed to throw an exception and leave the collection unmodified.
@@ -163,7 +268,12 @@ public abstract class ImmutableCollection<E> extends AbstractCollection<E>
private transient ImmutableList<E> asList;
/**
- * Returns a list view of the collection.
+ * Returns an {@code ImmutableList} containing the same elements, in the same order, as this
+ * collection.
+ *
+ * <p><b>Performance note:</b> in most cases this method can return quickly without actually
+ * copying anything. The exact circumstances under which the copy is performed are undefined and
+ * subject to change.
*
* @since 2.0
*/
@@ -190,7 +300,7 @@ public abstract class ImmutableCollection<E> extends AbstractCollection<E>
* memory leaks.
*/
abstract boolean isPartialView();
-
+
/**
* Copies the contents of this immutable collection into the specified array at the specified
* offset. Returns {@code offset + size()}.
@@ -231,8 +341,7 @@ public abstract class ImmutableCollection<E> extends AbstractCollection<E>
return newCapacity;
}
- Builder() {
- }
+ Builder() {}
/**
* Adds {@code element} to the {@code ImmutableCollection} being built.
@@ -312,25 +421,26 @@ public abstract class ImmutableCollection<E> extends AbstractCollection<E>
*/
public abstract ImmutableCollection<E> build();
}
-
+
abstract static class ArrayBasedBuilder<E> extends ImmutableCollection.Builder<E> {
Object[] contents;
int size;
-
+
ArrayBasedBuilder(int initialCapacity) {
checkNonnegative(initialCapacity, "initialCapacity");
this.contents = new Object[initialCapacity];
this.size = 0;
}
-
+
/**
* Expand the absolute capacity of the builder so it can accept at least
* the specified number of elements without being resized.
*/
private void ensureCapacity(int minCapacity) {
if (contents.length < minCapacity) {
- this.contents = ObjectArrays.arraysCopyOf(
- this.contents, expandedCapacity(contents.length, minCapacity));
+ this.contents =
+ ObjectArrays.arraysCopyOf(
+ this.contents, expandedCapacity(contents.length, minCapacity));
}
}
diff --git a/guava/src/com/google/common/collect/ImmutableEntry.java b/guava/src/com/google/common/collect/ImmutableEntry.java
index 1d04662..b17d5cb 100644
--- a/guava/src/com/google/common/collect/ImmutableEntry.java
+++ b/guava/src/com/google/common/collect/ImmutableEntry.java
@@ -26,8 +26,7 @@ import javax.annotation.Nullable;
* @see com.google.common.collect.Maps#immutableEntry(Object, Object)
*/
@GwtCompatible(serializable = true)
-class ImmutableEntry<K, V> extends AbstractMapEntry<K, V>
- implements Serializable {
+class ImmutableEntry<K, V> extends AbstractMapEntry<K, V> implements Serializable {
final K key;
final V value;
@@ -36,15 +35,20 @@ class ImmutableEntry<K, V> extends AbstractMapEntry<K, V>
this.value = value;
}
- @Nullable @Override public final K getKey() {
+ @Nullable
+ @Override
+ public final K getKey() {
return key;
}
- @Nullable @Override public final V getValue() {
+ @Nullable
+ @Override
+ public final V getValue() {
return value;
}
- @Override public final V setValue(V value) {
+ @Override
+ public final V setValue(V value) {
throw new UnsupportedOperationException();
}
diff --git a/guava/src/com/google/common/collect/ImmutableEnumMap.java b/guava/src/com/google/common/collect/ImmutableEnumMap.java
index 6738685..c361fa5 100644
--- a/guava/src/com/google/common/collect/ImmutableEnumMap.java
+++ b/guava/src/com/google/common/collect/ImmutableEnumMap.java
@@ -18,10 +18,10 @@ package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.ImmutableMap.IteratorBasedImmutableMap;
import java.io.Serializable;
import java.util.EnumMap;
-import java.util.Iterator;
import javax.annotation.Nullable;
@@ -33,15 +33,14 @@ import javax.annotation.Nullable;
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
-final class ImmutableEnumMap<K extends Enum<K>, V> extends ImmutableMap<K, V> {
+final class ImmutableEnumMap<K extends Enum<K>, V> extends IteratorBasedImmutableMap<K, V> {
static <K extends Enum<K>, V> ImmutableMap<K, V> asImmutable(EnumMap<K, V> map) {
switch (map.size()) {
case 0:
return ImmutableMap.of();
- case 1: {
+ case 1:
Entry<K, V> entry = Iterables.getOnlyElement(map.entrySet());
return ImmutableMap.of(entry.getKey(), entry.getValue());
- }
default:
return new ImmutableEnumMap<K, V>(map);
}
@@ -55,29 +54,8 @@ final class ImmutableEnumMap<K extends Enum<K>, V> extends ImmutableMap<K, V> {
}
@Override
- ImmutableSet<K> createKeySet() {
- return new ImmutableSet<K>() {
-
- @Override
- public boolean contains(Object object) {
- return delegate.containsKey(object);
- }
-
- @Override
- public int size() {
- return ImmutableEnumMap.this.size();
- }
-
- @Override
- public UnmodifiableIterator<K> iterator() {
- return Iterators.unmodifiableIterator(delegate.keySet().iterator());
- }
-
- @Override
- boolean isPartialView() {
- return true;
- }
- };
+ UnmodifiableIterator<K> keyIterator() {
+ return Iterators.unmodifiableIterator(delegate.keySet().iterator());
}
@Override
@@ -96,32 +74,19 @@ final class ImmutableEnumMap<K extends Enum<K>, V> extends ImmutableMap<K, V> {
}
@Override
- ImmutableSet<Entry<K, V>> createEntrySet() {
- return new ImmutableMapEntrySet<K, V>() {
-
- @Override
- ImmutableMap<K, V> map() {
- return ImmutableEnumMap.this;
- }
-
- @Override
- public UnmodifiableIterator<Entry<K, V>> iterator() {
- return new UnmodifiableIterator<Entry<K, V>>() {
- private final Iterator<Entry<K, V>> backingIterator = delegate.entrySet().iterator();
-
- @Override
- public boolean hasNext() {
- return backingIterator.hasNext();
- }
-
- @Override
- public Entry<K, V> next() {
- Entry<K, V> entry = backingIterator.next();
- return Maps.immutableEntry(entry.getKey(), entry.getValue());
- }
- };
- }
- };
+ public boolean equals(Object object) {
+ if (object == this) {
+ return true;
+ }
+ if (object instanceof ImmutableEnumMap) {
+ object = ((ImmutableEnumMap<?, ?>) object).delegate;
+ }
+ return delegate.equals(object);
+ }
+
+ @Override
+ UnmodifiableIterator<Entry<K, V>> entryIterator() {
+ return Maps.unmodifiableEntryIterator(delegate.entrySet().iterator());
}
@Override
@@ -130,22 +95,25 @@ final class ImmutableEnumMap<K extends Enum<K>, V> extends ImmutableMap<K, V> {
}
// All callers of the constructor are restricted to <K extends Enum<K>>.
- @Override Object writeReplace() {
+ @Override
+ Object writeReplace() {
return new EnumSerializedForm<K, V>(delegate);
}
/*
- * This class is used to serialize ImmutableEnumSet instances.
+ * This class is used to serialize ImmutableEnumMap instances.
*/
- private static class EnumSerializedForm<K extends Enum<K>, V>
- implements Serializable {
+ private static class EnumSerializedForm<K extends Enum<K>, V> implements Serializable {
final EnumMap<K, V> delegate;
+
EnumSerializedForm(EnumMap<K, V> delegate) {
this.delegate = delegate;
}
+
Object readResolve() {
return new ImmutableEnumMap<K, V>(delegate);
}
+
private static final long serialVersionUID = 0;
}
}
diff --git a/guava/src/com/google/common/collect/ImmutableEnumSet.java b/guava/src/com/google/common/collect/ImmutableEnumSet.java
index 62e3e04..67e8245 100644
--- a/guava/src/com/google/common/collect/ImmutableEnumSet.java
+++ b/guava/src/com/google/common/collect/ImmutableEnumSet.java
@@ -31,14 +31,15 @@ import java.util.EnumSet;
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
final class ImmutableEnumSet<E extends Enum<E>> extends ImmutableSet<E> {
- static <E extends Enum<E>> ImmutableSet<E> asImmutable(EnumSet<E> set) {
+ @SuppressWarnings("rawtypes") // necessary to compile against Java 8
+ static ImmutableSet asImmutable(EnumSet set) {
switch (set.size()) {
case 0:
return ImmutableSet.of();
case 1:
return ImmutableSet.of(Iterables.getOnlyElement(set));
default:
- return new ImmutableEnumSet<E>(set);
+ return new ImmutableEnumSet(set);
}
}
@@ -56,11 +57,13 @@ final class ImmutableEnumSet<E extends Enum<E>> extends ImmutableSet<E> {
this.delegate = delegate;
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return false;
}
- @Override public UnmodifiableIterator<E> iterator() {
+ @Override
+ public UnmodifiableIterator<E> iterator() {
return Iterators.unmodifiableIterator(delegate.iterator());
}
@@ -69,51 +72,74 @@ final class ImmutableEnumSet<E extends Enum<E>> extends ImmutableSet<E> {
return delegate.size();
}
- @Override public boolean contains(Object object) {
+ @Override
+ public boolean contains(Object object) {
return delegate.contains(object);
}
- @Override public boolean containsAll(Collection<?> collection) {
+ @Override
+ public boolean containsAll(Collection<?> collection) {
+ if (collection instanceof ImmutableEnumSet<?>) {
+ collection = ((ImmutableEnumSet<?>) collection).delegate;
+ }
return delegate.containsAll(collection);
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return delegate.isEmpty();
}
- @Override public boolean equals(Object object) {
- return object == this || delegate.equals(object);
+ @Override
+ public boolean equals(Object object) {
+ if (object == this) {
+ return true;
+ }
+ if (object instanceof ImmutableEnumSet) {
+ object = ((ImmutableEnumSet<?>) object).delegate;
+ }
+ return delegate.equals(object);
+ }
+
+ @Override
+ boolean isHashCodeFast() {
+ return true;
}
private transient int hashCode;
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = hashCode;
return (result == 0) ? hashCode = delegate.hashCode() : result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return delegate.toString();
}
// All callers of the constructor are restricted to <E extends Enum<E>>.
- @Override Object writeReplace() {
+ @Override
+ Object writeReplace() {
return new EnumSerializedForm<E>(delegate);
}
/*
* This class is used to serialize ImmutableEnumSet instances.
*/
- private static class EnumSerializedForm<E extends Enum<E>>
- implements Serializable {
+ private static class EnumSerializedForm<E extends Enum<E>> implements Serializable {
final EnumSet<E> delegate;
+
EnumSerializedForm(EnumSet<E> delegate) {
this.delegate = delegate;
}
+
Object readResolve() {
// EJ2 #76: Write readObject() methods defensively.
return new ImmutableEnumSet<E>(delegate.clone());
}
+
private static final long serialVersionUID = 0;
}
}
diff --git a/guava/src/com/google/common/collect/ImmutableList.java b/guava/src/com/google/common/collect/ImmutableList.java
index 501a41c..273772e 100644
--- a/guava/src/com/google/common/collect/ImmutableList.java
+++ b/guava/src/com/google/common/collect/ImmutableList.java
@@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import static com.google.common.collect.ObjectArrays.arraysCopyOf;
import static com.google.common.collect.ObjectArrays.checkElementsNotNull;
+import static com.google.common.collect.RegularImmutableList.EMPTY;
import com.google.common.annotations.GwtCompatible;
@@ -28,6 +29,7 @@ import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.RandomAccess;
@@ -35,37 +37,22 @@ import java.util.RandomAccess;
import javax.annotation.Nullable;
/**
- * A high-performance, immutable, random-access {@code List} implementation.
- * Does not permit null elements.
- *
- * <p>Unlike {@link Collections#unmodifiableList}, which is a <i>view</i> of a
- * separate collection that can still change, an instance of {@code
- * ImmutableList} contains its own private data and will <i>never</i> change.
- * {@code ImmutableList} is convenient for {@code public static final} lists
- * ("constant lists") and also lets you easily make a "defensive copy" of a list
- * provided to your class by a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this type are
- * guaranteed to be immutable.
+ * A {@link List} whose contents will never change, with many other important properties detailed at
+ * {@link ImmutableCollection}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @see ImmutableMap
* @see ImmutableSet
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
public abstract class ImmutableList<E> extends ImmutableCollection<E>
implements List<E>, RandomAccess {
-
- private static final ImmutableList<Object> EMPTY =
- new RegularImmutableList<Object>(ObjectArrays.EMPTY_ARRAY);
-
/**
* Returns the empty immutable list. This set behaves and performs comparably
* to {@link Collections#emptyList}, and is preferable mainly for consistency
@@ -139,8 +126,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
*
* @throws NullPointerException if any element is null
*/
- public static <E> ImmutableList<E> of(
- E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
+ public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
return construct(e1, e2, e3, e4, e5, e6, e7);
}
@@ -149,8 +135,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
*
* @throws NullPointerException if any element is null
*/
- public static <E> ImmutableList<E> of(
- E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
+ public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
return construct(e1, e2, e3, e4, e5, e6, e7, e8);
}
@@ -159,8 +144,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
*
* @throws NullPointerException if any element is null
*/
- public static <E> ImmutableList<E> of(
- E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
+ public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9);
}
@@ -194,8 +178,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
* @since 3.0 (source-compatible since 2.0)
*/
public static <E> ImmutableList<E> of(
- E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12,
- E... others) {
+ E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, E... others) {
Object[] array = new Object[12 + others.length];
array[0] = e1;
array[1] = e2;
@@ -224,8 +207,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
public static <E> ImmutableList<E> copyOf(Iterable<? extends E> elements) {
checkNotNull(elements); // TODO(kevinb): is this here only for GWT?
return (elements instanceof Collection)
- ? copyOf((Collection<? extends E>) elements)
- : copyOf(elements.iterator());
+ ? copyOf((Collection<? extends E>) elements)
+ : copyOf(elements.iterator());
}
/**
@@ -251,9 +234,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
if (elements instanceof ImmutableCollection) {
@SuppressWarnings("unchecked") // all supported methods are covariant
ImmutableList<E> list = ((ImmutableCollection<E>) elements).asList();
- return list.isPartialView()
- ? ImmutableList.<E>asImmutableList(list.toArray())
- : list;
+ return list.isPartialView() ? ImmutableList.<E>asImmutableList(list.toArray()) : list;
}
return construct(elements.toArray());
}
@@ -272,10 +253,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
if (!elements.hasNext()) {
return of(first);
} else {
- return new ImmutableList.Builder<E>()
- .add(first)
- .addAll(elements)
- .build();
+ return new ImmutableList.Builder<E>().add(first).addAll(elements).build();
}
}
@@ -336,15 +314,18 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
// This declaration is needed to make List.iterator() and
// ImmutableCollection.iterator() consistent.
- @Override public UnmodifiableIterator<E> iterator() {
+ @Override
+ public UnmodifiableIterator<E> iterator() {
return listIterator();
}
- @Override public UnmodifiableListIterator<E> listIterator() {
+ @Override
+ public UnmodifiableListIterator<E> listIterator() {
return listIterator(0);
}
- @Override public UnmodifiableListIterator<E> listIterator(int index) {
+ @Override
+ public UnmodifiableListIterator<E> listIterator(int index) {
return new AbstractIndexedListIterator<E>(size(), index) {
@Override
protected E get(int index) {
@@ -380,6 +361,9 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
public ImmutableList<E> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, size());
int length = toIndex - fromIndex;
+ if (length == size()) {
+ return this;
+ }
switch (length) {
case 0:
return of();
@@ -400,8 +384,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
}
class SubList extends ImmutableList<E> {
- transient final int offset;
- transient final int length;
+ final transient int offset;
+ final transient int length;
SubList(int offset, int length) {
this.offset = offset;
@@ -484,7 +468,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
*
* @since 2.0
*/
- @Override public final ImmutableList<E> asList() {
+ @Override
+ public final ImmutableList<E> asList() {
return this;
}
@@ -507,7 +492,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
* @since 7.0
*/
public ImmutableList<E> reverse() {
- return new ReverseImmutableList<E>(this);
+ return (size() <= 1) ? this : new ReverseImmutableList<E>(this);
}
private static class ReverseImmutableList<E> extends ImmutableList<E> {
@@ -525,49 +510,58 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
return size() - index;
}
- @Override public ImmutableList<E> reverse() {
+ @Override
+ public ImmutableList<E> reverse() {
return forwardList;
}
- @Override public boolean contains(@Nullable Object object) {
+ @Override
+ public boolean contains(@Nullable Object object) {
return forwardList.contains(object);
}
- @Override public int indexOf(@Nullable Object object) {
+ @Override
+ public int indexOf(@Nullable Object object) {
int index = forwardList.lastIndexOf(object);
return (index >= 0) ? reverseIndex(index) : -1;
}
- @Override public int lastIndexOf(@Nullable Object object) {
+ @Override
+ public int lastIndexOf(@Nullable Object object) {
int index = forwardList.indexOf(object);
return (index >= 0) ? reverseIndex(index) : -1;
}
- @Override public ImmutableList<E> subList(int fromIndex, int toIndex) {
+ @Override
+ public ImmutableList<E> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, size());
- return forwardList.subList(
- reversePosition(toIndex), reversePosition(fromIndex)).reverse();
+ return forwardList.subList(reversePosition(toIndex), reversePosition(fromIndex)).reverse();
}
- @Override public E get(int index) {
+ @Override
+ public E get(int index) {
checkElementIndex(index, size());
return forwardList.get(reverseIndex(index));
}
- @Override public int size() {
+ @Override
+ public int size() {
return forwardList.size();
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return forwardList.isPartialView();
}
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
return Lists.equalsImpl(this, obj);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int hashCode = 1;
int n = size();
for (int i = 0; i < n; i++) {
@@ -585,21 +579,24 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
*/
static class SerializedForm implements Serializable {
final Object[] elements;
+
SerializedForm(Object[] elements) {
this.elements = elements;
}
+
Object readResolve() {
return copyOf(elements);
}
+
private static final long serialVersionUID = 0;
}
- private void readObject(ObjectInputStream stream)
- throws InvalidObjectException {
+ private void readObject(ObjectInputStream stream) throws InvalidObjectException {
throw new InvalidObjectException("Use SerializedForm");
}
- @Override Object writeReplace() {
+ @Override
+ Object writeReplace() {
return new SerializedForm(toArray());
}
@@ -625,7 +622,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
* times to build multiple lists in series. Each new list contains all the
* elements of the ones created before it.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public static final class Builder<E> extends ImmutableCollection.ArrayBasedBuilder<E> {
/**
@@ -636,7 +633,7 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
this(DEFAULT_INITIAL_CAPACITY);
}
- // TODO(user): consider exposing this
+ // TODO(lowasser): consider exposing this
Builder(int capacity) {
super(capacity);
}
@@ -648,7 +645,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
* @return this {@code Builder} object
* @throws NullPointerException if {@code element} is null
*/
- @Override public Builder<E> add(E element) {
+ @Override
+ public Builder<E> add(E element) {
super.add(element);
return this;
}
@@ -661,7 +659,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
- @Override public Builder<E> addAll(Iterable<? extends E> elements) {
+ @Override
+ public Builder<E> addAll(Iterable<? extends E> elements) {
super.addAll(elements);
return this;
}
@@ -674,7 +673,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
- @Override public Builder<E> add(E... elements) {
+ @Override
+ public Builder<E> add(E... elements) {
super.add(elements);
return this;
}
@@ -687,7 +687,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
- @Override public Builder<E> addAll(Iterator<? extends E> elements) {
+ @Override
+ public Builder<E> addAll(Iterator<? extends E> elements) {
super.addAll(elements);
return this;
}
@@ -696,7 +697,8 @@ public abstract class ImmutableList<E> extends ImmutableCollection<E>
* Returns a newly-created {@code ImmutableList} based on the contents of
* the {@code Builder}.
*/
- @Override public ImmutableList<E> build() {
+ @Override
+ public ImmutableList<E> build() {
return asImmutableList(contents, size);
}
}
diff --git a/guava/src/com/google/common/collect/ImmutableListMultimap.java b/guava/src/com/google/common/collect/ImmutableListMultimap.java
index 616f4e9..f70cc52 100644
--- a/guava/src/com/google/common/collect/ImmutableListMultimap.java
+++ b/guava/src/com/google/common/collect/ImmutableListMultimap.java
@@ -16,6 +16,7 @@
package com.google.common.collect;
+import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
@@ -30,31 +31,18 @@ import java.util.Map.Entry;
import javax.annotation.Nullable;
/**
- * An immutable {@link ListMultimap} with reliable user-specified key and value
- * iteration order. Does not permit null keys or values.
- *
- * <p>Unlike {@link Multimaps#unmodifiableListMultimap(ListMultimap)}, which is
- * a <i>view</i> of a separate multimap which can still change, an instance of
- * {@code ImmutableListMultimap} contains its own data and will <i>never</i>
- * change. {@code ImmutableListMultimap} is convenient for
- * {@code public static final} multimaps ("constant multimaps") and also lets
- * you easily make a "defensive copy" of a multimap provided to your class by
- * a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class
- * are guaranteed to be immutable.
+ * A {@link ListMultimap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
-public class ImmutableListMultimap<K, V>
- extends ImmutableMultimap<K, V>
+public class ImmutableListMultimap<K, V> extends ImmutableMultimap<K, V>
implements ListMultimap<K, V> {
/** Returns the empty multimap. */
@@ -68,8 +56,7 @@ public class ImmutableListMultimap<K, V>
* Returns an immutable multimap containing a single entry.
*/
public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1) {
- ImmutableListMultimap.Builder<K, V> builder
- = ImmutableListMultimap.builder();
+ ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
builder.put(k1, v1);
return builder.build();
}
@@ -78,8 +65,7 @@ public class ImmutableListMultimap<K, V>
* Returns an immutable multimap containing the given entries, in order.
*/
public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1, K k2, V v2) {
- ImmutableListMultimap.Builder<K, V> builder
- = ImmutableListMultimap.builder();
+ ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
builder.put(k1, v1);
builder.put(k2, v2);
return builder.build();
@@ -88,10 +74,8 @@ public class ImmutableListMultimap<K, V>
/**
* Returns an immutable multimap containing the given entries, in order.
*/
- public static <K, V> ImmutableListMultimap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3) {
- ImmutableListMultimap.Builder<K, V> builder
- = ImmutableListMultimap.builder();
+ public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
+ ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
builder.put(k1, v1);
builder.put(k2, v2);
builder.put(k3, v3);
@@ -103,8 +87,7 @@ public class ImmutableListMultimap<K, V>
*/
public static <K, V> ImmutableListMultimap<K, V> of(
K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
- ImmutableListMultimap.Builder<K, V> builder
- = ImmutableListMultimap.builder();
+ ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
builder.put(k1, v1);
builder.put(k2, v2);
builder.put(k3, v3);
@@ -117,8 +100,7 @@ public class ImmutableListMultimap<K, V>
*/
public static <K, V> ImmutableListMultimap<K, V> of(
K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
- ImmutableListMultimap.Builder<K, V> builder
- = ImmutableListMultimap.builder();
+ ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
builder.put(k1, v1);
builder.put(k2, v2);
builder.put(k3, v3);
@@ -153,17 +135,17 @@ public class ImmutableListMultimap<K, V>
* times to build multiple multimaps in series. Each multimap contains the
* key-value mappings in the previously created multimaps.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
- public static final class Builder<K, V>
- extends ImmutableMultimap.Builder<K, V> {
+ public static final class Builder<K, V> extends ImmutableMultimap.Builder<K, V> {
/**
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link ImmutableListMultimap#builder}.
*/
public Builder() {}
- @Override public Builder<K, V> put(K key, V value) {
+ @Override
+ public Builder<K, V> put(K key, V value) {
super.put(key, value);
return this;
}
@@ -173,24 +155,38 @@ public class ImmutableListMultimap<K, V>
*
* @since 11.0
*/
- @Override public Builder<K, V> put(
- Entry<? extends K, ? extends V> entry) {
+ @Override
+ public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
super.put(entry);
return this;
}
- @Override public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
+ /**
+ * {@inheritDoc}
+ *
+ * @since 19.0
+ */
+ @Beta
+ @Override
+ public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ super.putAll(entries);
+ return this;
+ }
+
+ @Override
+ public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
super.putAll(key, values);
return this;
}
- @Override public Builder<K, V> putAll(K key, V... values) {
+ @Override
+ public Builder<K, V> putAll(K key, V... values) {
super.putAll(key, values);
return this;
}
- @Override public Builder<K, V> putAll(
- Multimap<? extends K, ? extends V> multimap) {
+ @Override
+ public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
super.putAll(multimap);
return this;
}
@@ -220,7 +216,8 @@ public class ImmutableListMultimap<K, V>
/**
* Returns a newly-created immutable list multimap.
*/
- @Override public ImmutableListMultimap<K, V> build() {
+ @Override
+ public ImmutableListMultimap<K, V> build() {
return (ImmutableListMultimap<K, V>) super.build();
}
}
@@ -243,21 +240,21 @@ public class ImmutableListMultimap<K, V>
return of();
}
- // TODO(user): copy ImmutableSetMultimap by using asList() on the sets
+ // TODO(lowasser): copy ImmutableSetMultimap by using asList() on the sets
if (multimap instanceof ImmutableListMultimap) {
@SuppressWarnings("unchecked") // safe since multimap is not writable
- ImmutableListMultimap<K, V> kvMultimap
- = (ImmutableListMultimap<K, V>) multimap;
+ ImmutableListMultimap<K, V> kvMultimap = (ImmutableListMultimap<K, V>) multimap;
if (!kvMultimap.isPartialView()) {
return kvMultimap;
}
}
- ImmutableMap.Builder<K, ImmutableList<V>> builder = ImmutableMap.builder();
+ ImmutableMap.Builder<K, ImmutableList<V>> builder =
+ new ImmutableMap.Builder<K, ImmutableList<V>>(multimap.asMap().size());
int size = 0;
- for (Entry<? extends K, ? extends Collection<? extends V>> entry
- : multimap.asMap().entrySet()) {
+ for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+ multimap.asMap().entrySet()) {
ImmutableList<V> list = ImmutableList.copyOf(entry.getValue());
if (!list.isEmpty()) {
builder.put(entry.getKey(), list);
@@ -268,6 +265,21 @@ public class ImmutableListMultimap<K, V>
return new ImmutableListMultimap<K, V>(builder.build(), size);
}
+ /**
+ * Returns an immutable multimap containing the specified entries. The
+ * returned multimap iterates over keys in the order they were first
+ * encountered in the input, and the values for each key are iterated in the
+ * order they were encountered.
+ *
+ * @throws NullPointerException if any key, value, or entry is null
+ * @since 19.0
+ */
+ @Beta
+ public static <K, V> ImmutableListMultimap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ return new Builder<K, V>().putAll(entries).build();
+ }
+
ImmutableListMultimap(ImmutableMap<K, ImmutableList<V>> map, int size) {
super(map, size);
}
@@ -280,7 +292,8 @@ public class ImmutableListMultimap<K, V>
* returned. The values are in the same order as the parameters used to build
* this multimap.
*/
- @Override public ImmutableList<V> get(@Nullable K key) {
+ @Override
+ public ImmutableList<V> get(@Nullable K key) {
// This cast is safe as its type is known in constructor.
ImmutableList<V> list = (ImmutableList<V>) map.get(key);
return (list == null) ? ImmutableList.<V>of() : list;
@@ -320,7 +333,9 @@ public class ImmutableListMultimap<K, V>
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public ImmutableList<V> removeAll(Object key) {
+ @Deprecated
+ @Override
+ public ImmutableList<V> removeAll(Object key) {
throw new UnsupportedOperationException();
}
@@ -330,8 +345,9 @@ public class ImmutableListMultimap<K, V>
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public ImmutableList<V> replaceValues(
- K key, Iterable<? extends V> values) {
+ @Deprecated
+ @Override
+ public ImmutableList<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
@@ -346,15 +362,13 @@ public class ImmutableListMultimap<K, V>
}
@GwtIncompatible("java.io.ObjectInputStream")
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
int keyCount = stream.readInt();
if (keyCount < 0) {
throw new InvalidObjectException("Invalid key count " + keyCount);
}
- ImmutableMap.Builder<Object, ImmutableList<Object>> builder
- = ImmutableMap.builder();
+ ImmutableMap.Builder<Object, ImmutableList<Object>> builder = ImmutableMap.builder();
int tmpSize = 0;
for (int i = 0; i < keyCount; i++) {
@@ -364,11 +378,11 @@ public class ImmutableListMultimap<K, V>
throw new InvalidObjectException("Invalid value count " + valueCount);
}
- Object[] array = new Object[valueCount];
+ ImmutableList.Builder<Object> valuesBuilder = ImmutableList.builder();
for (int j = 0; j < valueCount; j++) {
- array[j] = stream.readObject();
+ valuesBuilder.add(stream.readObject());
}
- builder.put(key, ImmutableList.copyOf(array));
+ builder.put(key, valuesBuilder.build());
tmpSize += valueCount;
}
@@ -376,8 +390,7 @@ public class ImmutableListMultimap<K, V>
try {
tmpMap = builder.build();
} catch (IllegalArgumentException e) {
- throw (InvalidObjectException)
- new InvalidObjectException(e.getMessage()).initCause(e);
+ throw (InvalidObjectException) new InvalidObjectException(e.getMessage()).initCause(e);
}
FieldSettersHolder.MAP_FIELD_SETTER.set(this, tmpMap);
diff --git a/guava/src/com/google/common/collect/ImmutableMap.java b/guava/src/com/google/common/collect/ImmutableMap.java
index 959858b..3fe475c 100644
--- a/guava/src/com/google/common/collect/ImmutableMap.java
+++ b/guava/src/com/google/common/collect/ImmutableMap.java
@@ -17,45 +17,35 @@
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.ImmutableMapEntry.TerminalEntry;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.EnumMap;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.annotation.Nullable;
/**
- * An immutable, hash-based {@link Map} with reliable user-specified iteration
- * order. Does not permit null keys or values.
- *
- * <p>Unlike {@link Collections#unmodifiableMap}, which is a <i>view</i> of a
- * separate map which can still change, an instance of {@code ImmutableMap}
- * contains its own data and will <i>never</i> change. {@code ImmutableMap} is
- * convenient for {@code public static final} maps ("constant maps") and also
- * lets you easily make a "defensive copy" of a map provided to your class by a
- * caller.
- *
- * <p><i>Performance notes:</i> unlike {@link HashMap}, {@code ImmutableMap} is
- * not optimized for element types that have slow {@link Object#equals} or
- * {@link Object#hashCode} implementations. You can get better performance by
- * having your element type cache its own hash codes, and by making use of the
- * cached values to short-circuit a slow {@code equals} algorithm.
+ * A {@link Map} whose contents will never change, with many other important properties detailed at
+ * {@link ImmutableCollection}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Jesse Wilson
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
@@ -86,7 +76,7 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
* @throws IllegalArgumentException if duplicate keys are provided
*/
public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2) {
- return new RegularImmutableMap<K, V>(entryOf(k1, v1), entryOf(k2, v2));
+ return RegularImmutableMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2));
}
/**
@@ -94,10 +84,8 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
*
* @throws IllegalArgumentException if duplicate keys are provided
*/
- public static <K, V> ImmutableMap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3) {
- return new RegularImmutableMap<K, V>(
- entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
+ public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
+ return RegularImmutableMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
}
/**
@@ -105,9 +93,8 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
*
* @throws IllegalArgumentException if duplicate keys are provided
*/
- public static <K, V> ImmutableMap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
- return new RegularImmutableMap<K, V>(
+ public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+ return RegularImmutableMap.fromEntries(
entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4));
}
@@ -118,8 +105,8 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
*/
public static <K, V> ImmutableMap<K, V> of(
K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
- return new RegularImmutableMap<K, V>(entryOf(k1, v1),
- entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
+ return RegularImmutableMap.fromEntries(
+ entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
}
// looking for of() with > 5 entries? Use the builder instead.
@@ -131,9 +118,8 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
* <p>A call to {@link Map.Entry#setValue} on the returned entry will always
* throw {@link UnsupportedOperationException}.
*/
- static <K, V> TerminalEntry<K, V> entryOf(K key, V value) {
- checkEntryNotNull(key, value);
- return new TerminalEntry<K, V>(key, value);
+ static <K, V> ImmutableMapEntry<K, V> entryOf(K key, V value) {
+ return new ImmutableMapEntry<K, V>(key, value);
}
/**
@@ -144,8 +130,8 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
return new Builder<K, V>();
}
- static void checkNoConflict(boolean safe, String conflictDescription,
- Entry<?, ?> entry1, Entry<?, ?> entry2) {
+ static void checkNoConflict(
+ boolean safe, String conflictDescription, Entry<?, ?> entry1, Entry<?, ?> entry2) {
if (!safe) {
throw new IllegalArgumentException(
"Multiple entries with same " + conflictDescription + ": " + entry1 + " and " + entry2);
@@ -170,11 +156,13 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
* multiple times to build multiple maps in series. Each map is a superset of
* the maps created before it.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public static class Builder<K, V> {
- TerminalEntry<K, V>[] entries;
+ Comparator<? super V> valueComparator;
+ ImmutableMapEntry<K, V>[] entries;
int size;
+ boolean entriesUsed;
/**
* Creates a new builder. The returned builder is equivalent to the builder
@@ -186,14 +174,17 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
@SuppressWarnings("unchecked")
Builder(int initialCapacity) {
- this.entries = new TerminalEntry[initialCapacity];
+ this.entries = new ImmutableMapEntry[initialCapacity];
this.size = 0;
+ this.entriesUsed = false;
}
private void ensureCapacity(int minCapacity) {
if (minCapacity > entries.length) {
- entries = ObjectArrays.arraysCopyOf(
- entries, ImmutableCollection.Builder.expandedCapacity(entries.length, minCapacity));
+ entries =
+ ObjectArrays.arraysCopyOf(
+ entries, ImmutableCollection.Builder.expandedCapacity(entries.length, minCapacity));
+ entriesUsed = false;
}
}
@@ -203,7 +194,7 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
*/
public Builder<K, V> put(K key, V value) {
ensureCapacity(size + 1);
- TerminalEntry<K, V> entry = entryOf(key, value);
+ ImmutableMapEntry<K, V> entry = entryOf(key, value);
// don't inline this: we want to fail atomically if key or value is null
entries[size++] = entry;
return this;
@@ -227,13 +218,45 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
* @throws NullPointerException if any key or value in {@code map} is null
*/
public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
- ensureCapacity(size + map.size());
- for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
+ return putAll(map.entrySet());
+ }
+
+ /**
+ * Adds all of the given entries to the built map. Duplicate keys are not
+ * allowed, and will cause {@link #build} to fail.
+ *
+ * @throws NullPointerException if any key, value, or entry is null
+ * @since 19.0
+ */
+ @Beta
+ public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ if (entries instanceof Collection) {
+ ensureCapacity(size + ((Collection<?>) entries).size());
+ }
+ for (Entry<? extends K, ? extends V> entry : entries) {
put(entry);
}
return this;
}
+ /**
+ * Configures this {@code Builder} to order entries by value according to the specified
+ * comparator.
+ *
+ * <p>The sort order is stable, that is, if two entries have values that compare
+ * as equivalent, the entry that was inserted first will be first in the built map's
+ * iteration order.
+ *
+ * @throws IllegalStateException if this method was already called
+ * @since 19.0
+ */
+ @Beta
+ public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
+ checkState(this.valueComparator == null, "valueComparator was already set");
+ this.valueComparator = checkNotNull(valueComparator, "valueComparator");
+ return this;
+ }
+
/*
* TODO(kevinb): Should build() and the ImmutableBiMap & ImmutableSortedMap
* versions throw an IllegalStateException instead?
@@ -251,7 +274,25 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
case 1:
return of(entries[0].getKey(), entries[0].getValue());
default:
- return new RegularImmutableMap<K, V>(size, entries);
+ /*
+ * If entries is full, then this implementation may end up using the entries array
+ * directly and writing over the entry objects with non-terminal entries, but this is
+ * safe; if this Builder is used further, it will grow the entries array (so it can't
+ * affect the original array), and future build() calls will always copy any entry
+ * objects that cannot be safely reused.
+ */
+ if (valueComparator != null) {
+ if (entriesUsed) {
+ entries = ObjectArrays.arraysCopyOf(entries, size);
+ }
+ Arrays.sort(
+ entries,
+ 0,
+ size,
+ Ordering.from(valueComparator).onResultOf(Maps.<V>valueFunction()));
+ }
+ entriesUsed = size == entries.length;
+ return RegularImmutableMap.fromEntryArray(size, entries);
}
}
}
@@ -268,10 +309,9 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
*
* @throws NullPointerException if any key or value in {@code map} is null
*/
- public static <K, V> ImmutableMap<K, V> copyOf(
- Map<? extends K, ? extends V> map) {
+ public static <K, V> ImmutableMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
if ((map instanceof ImmutableMap) && !(map instanceof ImmutableSortedMap)) {
- // TODO(user): Make ImmutableMap.copyOf(immutableBiMap) call copyOf()
+ // TODO(lowasser): Make ImmutableMap.copyOf(immutableBiMap) call copyOf()
// on the ImmutableMap delegate(), rather than the bimap itself
@SuppressWarnings("unchecked") // safe since map is not writable
@@ -280,29 +320,43 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
return kvMap;
}
} else if (map instanceof EnumMap) {
- return copyOfEnumMapUnsafe(map);
+ @SuppressWarnings("unchecked") // safe since map is not writable
+ ImmutableMap<K, V> kvMap = (ImmutableMap<K, V>) copyOfEnumMap((EnumMap<?, ?>) map);
+ return kvMap;
}
- Entry<?, ?>[] entries = map.entrySet().toArray(EMPTY_ENTRY_ARRAY);
- switch (entries.length) {
+ return copyOf(map.entrySet());
+ }
+
+ /**
+ * Returns an immutable map containing the specified entries. The returned
+ * map iterates over entries in the same order as the original iterable.
+ *
+ * @throws NullPointerException if any key, value, or entry is null
+ * @throws IllegalArgumentException if two entries have the same key
+ * @since 19.0
+ */
+ @Beta
+ public static <K, V> ImmutableMap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ @SuppressWarnings("unchecked") // we'll only be using getKey and getValue, which are covariant
+ Entry<K, V>[] entryArray = (Entry<K, V>[]) Iterables.toArray(entries, EMPTY_ENTRY_ARRAY);
+ switch (entryArray.length) {
case 0:
return of();
case 1:
- @SuppressWarnings("unchecked") // all entries will be Entry<K, V>'s
- Entry<K, V> onlyEntry = (Entry<K, V>) entries[0];
+ Entry<K, V> onlyEntry = entryArray[0];
return of(onlyEntry.getKey(), onlyEntry.getValue());
default:
- return new RegularImmutableMap<K, V>(entries);
+ /*
+ * The current implementation will end up using entryArray directly, though it will write
+ * over the (arbitrary, potentially mutable) Entry objects actually stored in entryArray.
+ */
+ return RegularImmutableMap.fromEntries(entryArray);
}
}
- // If the map is an EnumMap, it must have key type K for some <K extends Enum<K>>.
- @SuppressWarnings({"unchecked", "rawtypes"})
- private static <K, V> ImmutableMap<K, V> copyOfEnumMapUnsafe(Map<? extends K, ? extends V> map) {
- return copyOfEnumMap((EnumMap) map);
- }
-
private static <K extends Enum<K>, V> ImmutableMap<K, V> copyOfEnumMap(
- Map<K, ? extends V> original) {
+ EnumMap<K, ? extends V> original) {
EnumMap<K, V> copy = new EnumMap<K, V>(original);
for (Map.Entry<?, ?> entry : copy.entrySet()) {
checkEntryNotNull(entry.getKey(), entry.getValue());
@@ -310,7 +364,28 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
return ImmutableEnumMap.asImmutable(copy);
}
- private static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0];
+ static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0];
+
+ abstract static class IteratorBasedImmutableMap<K, V> extends ImmutableMap<K, V> {
+ abstract UnmodifiableIterator<Entry<K, V>> entryIterator();
+
+ @Override
+ ImmutableSet<Entry<K, V>> createEntrySet() {
+ @WeakOuter
+ class EntrySetImpl extends ImmutableMapEntrySet<K, V> {
+ @Override
+ ImmutableMap<K, V> map() {
+ return IteratorBasedImmutableMap.this;
+ }
+
+ @Override
+ public UnmodifiableIterator<Entry<K, V>> iterator() {
+ return entryIterator();
+ }
+ }
+ return new EntrySetImpl();
+ }
+ }
ImmutableMap() {}
@@ -408,7 +483,22 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
}
ImmutableSet<K> createKeySet() {
- return new ImmutableMapKeySet<K, V>(this);
+ return isEmpty() ? ImmutableSet.<K>of() : new ImmutableMapKeySet<K, V>(this);
+ }
+
+ UnmodifiableIterator<K> keyIterator() {
+ final UnmodifiableIterator<Entry<K, V>> entryIterator = entrySet().iterator();
+ return new UnmodifiableIterator<K>() {
+ @Override
+ public boolean hasNext() {
+ return entryIterator.hasNext();
+ }
+
+ @Override
+ public K next() {
+ return entryIterator.next().getKey();
+ }
+ };
}
private transient ImmutableCollection<V> values;
@@ -433,69 +523,78 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
*/
@Beta
public ImmutableSetMultimap<K, V> asMultimap() {
+ if (isEmpty()) {
+ return ImmutableSetMultimap.of();
+ }
ImmutableSetMultimap<K, V> result = multimapView;
- return (result == null) ? (multimapView = createMultimapView()) : result;
+ return (result == null)
+ ? (multimapView =
+ new ImmutableSetMultimap<K, V>(new MapViewOfValuesAsSingletonSets(), size(), null))
+ : result;
}
- private ImmutableSetMultimap<K, V> createMultimapView() {
- ImmutableMap<K, ImmutableSet<V>> map = viewMapValuesAsSingletonSets();
- return new ImmutableSetMultimap<K, V>(map, map.size(), null);
- }
+ @WeakOuter
+ private final class MapViewOfValuesAsSingletonSets
+ extends IteratorBasedImmutableMap<K, ImmutableSet<V>> {
- private ImmutableMap<K, ImmutableSet<V>> viewMapValuesAsSingletonSets() {
- return new MapViewOfValuesAsSingletonSets<K, V>(this);
- }
+ @Override
+ public int size() {
+ return ImmutableMap.this.size();
+ }
- private static final class MapViewOfValuesAsSingletonSets<K, V>
- extends ImmutableMap<K, ImmutableSet<V>> {
- private final ImmutableMap<K, V> delegate;
+ @Override
+ public ImmutableSet<K> keySet() {
+ return ImmutableMap.this.keySet();
+ }
- MapViewOfValuesAsSingletonSets(ImmutableMap<K, V> delegate) {
- this.delegate = checkNotNull(delegate);
+ @Override
+ public boolean containsKey(@Nullable Object key) {
+ return ImmutableMap.this.containsKey(key);
}
- @Override public int size() {
- return delegate.size();
+ @Override
+ public ImmutableSet<V> get(@Nullable Object key) {
+ V outerValue = ImmutableMap.this.get(key);
+ return (outerValue == null) ? null : ImmutableSet.of(outerValue);
}
- @Override public boolean containsKey(@Nullable Object key) {
- return delegate.containsKey(key);
+ @Override
+ boolean isPartialView() {
+ return ImmutableMap.this.isPartialView();
}
- @Override public ImmutableSet<V> get(@Nullable Object key) {
- V outerValue = delegate.get(key);
- return (outerValue == null) ? null : ImmutableSet.of(outerValue);
+ @Override
+ public int hashCode() {
+ // ImmutableSet.of(value).hashCode() == value.hashCode(), so the hashes are the same
+ return ImmutableMap.this.hashCode();
}
- @Override boolean isPartialView() {
- return false;
+ @Override
+ boolean isHashCodeFast() {
+ return ImmutableMap.this.isHashCodeFast();
}
- @Override ImmutableSet<Entry<K, ImmutableSet<V>>> createEntrySet() {
- return new ImmutableMapEntrySet<K, ImmutableSet<V>>() {
- @Override ImmutableMap<K, ImmutableSet<V>> map() {
- return MapViewOfValuesAsSingletonSets.this;
+ @Override
+ UnmodifiableIterator<Entry<K, ImmutableSet<V>>> entryIterator() {
+ final Iterator<Entry<K, V>> backingIterator = ImmutableMap.this.entrySet().iterator();
+ return new UnmodifiableIterator<Entry<K, ImmutableSet<V>>>() {
+ @Override
+ public boolean hasNext() {
+ return backingIterator.hasNext();
}
@Override
- public UnmodifiableIterator<Entry<K, ImmutableSet<V>>> iterator() {
- final Iterator<Entry<K, V>> backingIterator = delegate.entrySet().iterator();
- return new UnmodifiableIterator<Entry<K, ImmutableSet<V>>>() {
- @Override public boolean hasNext() {
- return backingIterator.hasNext();
+ public Entry<K, ImmutableSet<V>> next() {
+ final Entry<K, V> backingEntry = backingIterator.next();
+ return new AbstractMapEntry<K, ImmutableSet<V>>() {
+ @Override
+ public K getKey() {
+ return backingEntry.getKey();
}
- @Override public Entry<K, ImmutableSet<V>> next() {
- final Entry<K, V> backingEntry = backingIterator.next();
- return new AbstractMapEntry<K, ImmutableSet<V>>() {
- @Override public K getKey() {
- return backingEntry.getKey();
- }
-
- @Override public ImmutableSet<V> getValue() {
- return ImmutableSet.of(backingEntry.getValue());
- }
- };
+ @Override
+ public ImmutableSet<V> getValue() {
+ return ImmutableSet.of(backingEntry.getValue());
}
};
}
@@ -503,19 +602,24 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
}
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return Maps.equalsImpl(this, object);
}
abstract boolean isPartialView();
- @Override public int hashCode() {
- // not caching hash code since it could change if map values are mutable
- // in a way that modifies their hash codes
- return entrySet().hashCode();
+ @Override
+ public int hashCode() {
+ return Sets.hashCodeImpl(entrySet());
}
- @Override public String toString() {
+ boolean isHashCodeFast() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
return Maps.toStringImpl(this);
}
@@ -527,6 +631,7 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
static class SerializedForm implements Serializable {
private final Object[] keys;
private final Object[] values;
+
SerializedForm(ImmutableMap<?, ?> map) {
keys = new Object[map.size()];
values = new Object[map.size()];
@@ -537,16 +642,19 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
i++;
}
}
+
Object readResolve() {
- Builder<Object, Object> builder = new Builder<Object, Object>();
+ Builder<Object, Object> builder = new Builder<Object, Object>(keys.length);
return createMap(builder);
}
+
Object createMap(Builder<Object, Object> builder) {
for (int i = 0; i < keys.length; i++) {
builder.put(keys[i], values[i]);
}
return builder.build();
}
+
private static final long serialVersionUID = 0;
}
diff --git a/guava/src/com/google/common/collect/ImmutableMapEntry.java b/guava/src/com/google/common/collect/ImmutableMapEntry.java
index 6d2aa94..6487aee 100644
--- a/guava/src/com/google/common/collect/ImmutableMapEntry.java
+++ b/guava/src/com/google/common/collect/ImmutableMapEntry.java
@@ -28,10 +28,23 @@ import javax.annotation.Nullable;
* {@link RegularImmutableBiMap}, which don't have to recopy the entries created by their
* {@code Builder} implementations.
*
+ * <p>This base implementation has no key or value pointers, so instances of ImmutableMapEntry
+ * (but not its subclasses) can be reused when copied from one ImmutableMap to another.
+ *
* @author Louis Wasserman
*/
@GwtIncompatible("unnecessary")
-abstract class ImmutableMapEntry<K, V> extends ImmutableEntry<K, V> {
+class ImmutableMapEntry<K, V> extends ImmutableEntry<K, V> {
+ /**
+ * Creates an {@code ImmutableMapEntry} array to hold parameterized entries. The
+ * result must never be upcast back to ImmutableMapEntry[] (or Object[], etc.), or
+ * allowed to escape the class.
+ */
+ @SuppressWarnings("unchecked") // Safe as long as the javadocs are followed
+ static <K, V> ImmutableMapEntry<K, V>[] createEntryArray(int size) {
+ return new ImmutableMapEntry[size];
+ }
+
ImmutableMapEntry(K key, V value) {
super(key, value);
checkEntryNotNull(key, value);
@@ -43,30 +56,60 @@ abstract class ImmutableMapEntry<K, V> extends ImmutableEntry<K, V> {
}
@Nullable
- abstract ImmutableMapEntry<K, V> getNextInKeyBucket();
+ ImmutableMapEntry<K, V> getNextInKeyBucket() {
+ return null;
+ }
@Nullable
- abstract ImmutableMapEntry<K, V> getNextInValueBucket();
+ ImmutableMapEntry<K, V> getNextInValueBucket() {
+ return null;
+ }
- static final class TerminalEntry<K, V> extends ImmutableMapEntry<K, V> {
- TerminalEntry(ImmutableMapEntry<K, V> contents) {
- super(contents);
- }
+ /**
+ * Returns true if this entry has no bucket links and can safely be reused as a terminal
+ * entry in a bucket in another map.
+ */
+ boolean isReusable() {
+ return true;
+ }
+
+ static class NonTerminalImmutableMapEntry<K, V> extends ImmutableMapEntry<K, V> {
+ private final transient ImmutableMapEntry<K, V> nextInKeyBucket;
- TerminalEntry(K key, V value) {
+ NonTerminalImmutableMapEntry(K key, V value, ImmutableMapEntry<K, V> nextInKeyBucket) {
super(key, value);
+ this.nextInKeyBucket = nextInKeyBucket;
}
@Override
@Nullable
- ImmutableMapEntry<K, V> getNextInKeyBucket() {
- return null;
+ final ImmutableMapEntry<K, V> getNextInKeyBucket() {
+ return nextInKeyBucket;
+ }
+
+ @Override
+ final boolean isReusable() {
+ return false;
+ }
+ }
+
+ static final class NonTerminalImmutableBiMapEntry<K, V>
+ extends NonTerminalImmutableMapEntry<K, V> {
+ private final transient ImmutableMapEntry<K, V> nextInValueBucket;
+
+ NonTerminalImmutableBiMapEntry(
+ K key,
+ V value,
+ ImmutableMapEntry<K, V> nextInKeyBucket,
+ ImmutableMapEntry<K, V> nextInValueBucket) {
+ super(key, value, nextInKeyBucket);
+ this.nextInValueBucket = nextInValueBucket;
}
@Override
@Nullable
ImmutableMapEntry<K, V> getNextInValueBucket() {
- return null;
+ return nextInValueBucket;
}
}
}
diff --git a/guava/src/com/google/common/collect/ImmutableMapEntrySet.java b/guava/src/com/google/common/collect/ImmutableMapEntrySet.java
index a6aa6e0..0329c05 100644
--- a/guava/src/com/google/common/collect/ImmutableMapEntrySet.java
+++ b/guava/src/com/google/common/collect/ImmutableMapEntrySet.java
@@ -18,6 +18,7 @@ package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.Weak;
import java.io.Serializable;
import java.util.Map.Entry;
@@ -32,6 +33,31 @@ import javax.annotation.Nullable;
*/
@GwtCompatible(emulated = true)
abstract class ImmutableMapEntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
+ static final class RegularEntrySet<K, V> extends ImmutableMapEntrySet<K, V> {
+ @Weak private final transient ImmutableMap<K, V> map;
+ private final transient Entry<K, V>[] entries;
+
+ RegularEntrySet(ImmutableMap<K, V> map, Entry<K, V>[] entries) {
+ this.map = map;
+ this.entries = entries;
+ }
+
+ @Override
+ ImmutableMap<K, V> map() {
+ return map;
+ }
+
+ @Override
+ public UnmodifiableIterator<Entry<K, V>> iterator() {
+ return asList().iterator();
+ }
+
+ @Override
+ ImmutableList<Entry<K, V>> createAsList() {
+ return new RegularImmutableAsList<Entry<K, V>>(this, entries);
+ }
+ }
+
ImmutableMapEntrySet() {}
abstract ImmutableMap<K, V> map();
@@ -56,6 +82,17 @@ abstract class ImmutableMapEntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
return map().isPartialView();
}
+ @Override
+ @GwtIncompatible("not used in GWT")
+ boolean isHashCodeFast() {
+ return map().isHashCodeFast();
+ }
+
+ @Override
+ public int hashCode() {
+ return map().hashCode();
+ }
+
@GwtIncompatible("serialization")
@Override
Object writeReplace() {
@@ -65,12 +102,15 @@ abstract class ImmutableMapEntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
@GwtIncompatible("serialization")
private static class EntrySetSerializedForm<K, V> implements Serializable {
final ImmutableMap<K, V> map;
+
EntrySetSerializedForm(ImmutableMap<K, V> map) {
this.map = map;
}
+
Object readResolve() {
return map.entrySet();
}
+
private static final long serialVersionUID = 0;
}
}
diff --git a/guava/src/com/google/common/collect/ImmutableMapKeySet.java b/guava/src/com/google/common/collect/ImmutableMapKeySet.java
index fbb59d8..b97560b 100644
--- a/guava/src/com/google/common/collect/ImmutableMapKeySet.java
+++ b/guava/src/com/google/common/collect/ImmutableMapKeySet.java
@@ -18,9 +18,9 @@ package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.Weak;
import java.io.Serializable;
-import java.util.Map.Entry;
import javax.annotation.Nullable;
@@ -31,8 +31,8 @@ import javax.annotation.Nullable;
* @author Kevin Bourrillion
*/
@GwtCompatible(emulated = true)
-final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
- private final ImmutableMap<K, V> map;
+final class ImmutableMapKeySet<K, V> extends ImmutableSet.Indexed<K> {
+ @Weak private final ImmutableMap<K, V> map;
ImmutableMapKeySet(ImmutableMap<K, V> map) {
this.map = map;
@@ -45,7 +45,7 @@ final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
@Override
public UnmodifiableIterator<K> iterator() {
- return asList().iterator();
+ return map.keyIterator();
}
@Override
@@ -54,21 +54,8 @@ final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
}
@Override
- ImmutableList<K> createAsList() {
- final ImmutableList<Entry<K, V>> entryList = map.entrySet().asList();
- return new ImmutableAsList<K>() {
-
- @Override
- public K get(int index) {
- return entryList.get(index).getKey();
- }
-
- @Override
- ImmutableCollection<K> delegateCollection() {
- return ImmutableMapKeySet.this;
- }
-
- };
+ K get(int index) {
+ return map.entrySet().asList().get(index).getKey();
}
@Override
@@ -77,19 +64,23 @@ final class ImmutableMapKeySet<K, V> extends ImmutableSet<K> {
}
@GwtIncompatible("serialization")
- @Override Object writeReplace() {
+ @Override
+ Object writeReplace() {
return new KeySetSerializedForm<K>(map);
}
@GwtIncompatible("serialization")
private static class KeySetSerializedForm<K> implements Serializable {
final ImmutableMap<K, ?> map;
+
KeySetSerializedForm(ImmutableMap<K, ?> map) {
this.map = map;
}
+
Object readResolve() {
return map.keySet();
}
+
private static final long serialVersionUID = 0;
}
}
diff --git a/guava/src/com/google/common/collect/ImmutableMapValues.java b/guava/src/com/google/common/collect/ImmutableMapValues.java
index 379b14d..be291fb 100644
--- a/guava/src/com/google/common/collect/ImmutableMapValues.java
+++ b/guava/src/com/google/common/collect/ImmutableMapValues.java
@@ -18,6 +18,7 @@ package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.Weak;
import java.io.Serializable;
import java.util.Map.Entry;
@@ -32,8 +33,8 @@ import javax.annotation.Nullable;
*/
@GwtCompatible(emulated = true)
final class ImmutableMapValues<K, V> extends ImmutableCollection<V> {
- private final ImmutableMap<K, V> map;
-
+ @Weak private final ImmutableMap<K, V> map;
+
ImmutableMapValues(ImmutableMap<K, V> map) {
this.map = map;
}
@@ -45,7 +46,19 @@ final class ImmutableMapValues<K, V> extends ImmutableCollection<V> {
@Override
public UnmodifiableIterator<V> iterator() {
- return Maps.valueIterator(map.entrySet().iterator());
+ return new UnmodifiableIterator<V>() {
+ final UnmodifiableIterator<Entry<K, V>> entryItr = map.entrySet().iterator();
+
+ @Override
+ public boolean hasNext() {
+ return entryItr.hasNext();
+ }
+
+ @Override
+ public V next() {
+ return entryItr.next().getValue();
+ }
+ };
}
@Override
@@ -75,19 +88,23 @@ final class ImmutableMapValues<K, V> extends ImmutableCollection<V> {
}
@GwtIncompatible("serialization")
- @Override Object writeReplace() {
+ @Override
+ Object writeReplace() {
return new SerializedForm<V>(map);
}
@GwtIncompatible("serialization")
private static class SerializedForm<V> implements Serializable {
final ImmutableMap<?, V> map;
+
SerializedForm(ImmutableMap<?, V> map) {
this.map = map;
}
+
Object readResolve() {
return map.values();
}
+
private static final long serialVersionUID = 0;
}
}
diff --git a/guava/src/com/google/common/collect/ImmutableMultimap.java b/guava/src/com/google/common/collect/ImmutableMultimap.java
index 32bf988..5790218 100644
--- a/guava/src/com/google/common/collect/ImmutableMultimap.java
+++ b/guava/src/com/google/common/collect/ImmutableMultimap.java
@@ -19,8 +19,11 @@ package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
+import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.Arrays;
@@ -28,7 +31,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -37,29 +39,30 @@ import java.util.Set;
import javax.annotation.Nullable;
/**
- * An immutable {@link Multimap}. Does not permit null keys or values.
+ * A {@link Multimap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
- * <p>Unlike {@link Multimaps#unmodifiableMultimap(Multimap)}, which is
- * a <i>view</i> of a separate multimap which can still change, an instance of
- * {@code ImmutableMultimap} contains its own data and will <i>never</i>
- * change. {@code ImmutableMultimap} is convenient for
- * {@code public static final} multimaps ("constant multimaps") and also lets
- * you easily make a "defensive copy" of a multimap provided to your class by
- * a caller.
+ * <p><b>Warning:</b> avoid <i>direct</i> usage of {@link ImmutableMultimap} as a type (as with
+ * {@link Multimap} itself). Prefer subtypes such as {@link ImmutableSetMultimap} or {@link
+ * ImmutableListMultimap}, which have well-defined {@link #equals} semantics, thus avoiding a common
+ * source of bugs and confusion.
*
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class
- * are guaranteed to be immutable.
+ * <p><b>Note:</b> every {@link ImmutableMultimap} offers an {@link #inverse} view, so there is no
+ * need for a distinct {@code ImmutableBiMultimap} type.
*
- * <p>In addition to methods defined by {@link Multimap}, an {@link #inverse}
- * method is also supported.
+ * <a name="iteration"></a>
+ * <p><b>Key-grouped iteration.</b> All view collections follow the same iteration order. In all
+ * current implementations, the iteration order always keeps multiple entries with the same key
+ * together. Any creation method that would customarily respect insertion order (such as {@link
+ * #copyOf(Multimap)}) instead preserves key-grouped order by inserting entries for an existing key
+ * immediately after the last entry having that key.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
@@ -85,23 +88,27 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
}
/**
- * Returns an immutable multimap containing the given entries, in order.
+ * Returns an immutable multimap containing the given entries, in the
+ * "key-grouped" insertion order described in the
+ * <a href="#iteration">class documentation</a>.
*/
- public static <K, V> ImmutableMultimap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3) {
+ public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3);
}
/**
- * Returns an immutable multimap containing the given entries, in order.
+ * Returns an immutable multimap containing the given entries, in the
+ * "key-grouped" insertion order described in the
+ * <a href="#iteration">class documentation</a>.
*/
- public static <K, V> ImmutableMultimap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+ public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4);
}
/**
- * Returns an immutable multimap containing the given entries, in order.
+ * Returns an immutable multimap containing the given entries, in the
+ * "key-grouped" insertion order described in the
+ * <a href="#iteration">class documentation</a>.
*/
public static <K, V> ImmutableMultimap<K, V> of(
K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
@@ -119,21 +126,6 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
}
/**
- * Multimap for {@link ImmutableMultimap.Builder} that maintains key and
- * value orderings, allows duplicate values, and performs better than
- * {@link LinkedListMultimap}.
- */
- private static class BuilderMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
- BuilderMultimap() {
- super(new LinkedHashMap<K, Collection<V>>());
- }
- @Override Collection<V> createCollection() {
- return Lists.newArrayList();
- }
- private static final long serialVersionUID = 0;
- }
-
- /**
* A builder for creating immutable multimap instances, especially
* {@code public static final} multimaps ("constant multimaps"). Example:
* <pre> {@code
@@ -149,10 +141,10 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
* times to build multiple multimaps in series. Each multimap contains the
* key-value mappings in the previously created multimaps.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public static class Builder<K, V> {
- Multimap<K, V> builderMultimap = new BuilderMultimap<K, V>();
+ Multimap<K, V> builderMultimap;
Comparator<? super K> keyComparator;
Comparator<? super V> valueComparator;
@@ -160,7 +152,13 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link ImmutableMultimap#builder}.
*/
- public Builder() {}
+ public Builder() {
+ this(MultimapBuilder.linkedHashKeys().arrayListValues().<K, V>build());
+ }
+
+ Builder(Multimap<K, V> builderMultimap) {
+ this.builderMultimap = builderMultimap;
+ }
/**
* Adds a key-value mapping to the built multimap.
@@ -181,6 +179,19 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
}
/**
+ * Adds entries to the built multimap.
+ *
+ * @since 19.0
+ */
+ @Beta
+ public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ for (Entry<? extends K, ? extends V> entry : entries) {
+ put(entry);
+ }
+ return this;
+ }
+
+ /**
* Stores a collection of values with the same key in the built multimap.
*
* @throws NullPointerException if {@code key}, {@code values}, or any
@@ -189,8 +200,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
*/
public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
if (key == null) {
- throw new NullPointerException(
- "null key in entry: null=" + Iterables.toString(values));
+ throw new NullPointerException("null key in entry: null=" + Iterables.toString(values));
}
Collection<V> valueList = builderMultimap.get(key);
for (V value : values) {
@@ -220,8 +230,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
* null. The builder is left in an invalid state.
*/
public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
- for (Entry<? extends K, ? extends Collection<? extends V>> entry
- : multimap.asMap().entrySet()) {
+ for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+ multimap.asMap().entrySet()) {
putAll(entry.getKey(), entry.getValue());
}
return this;
@@ -253,17 +263,17 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
public ImmutableMultimap<K, V> build() {
if (valueComparator != null) {
for (Collection<V> values : builderMultimap.asMap().values()) {
- List<V> list = (List <V>) values;
+ List<V> list = (List<V>) values;
Collections.sort(list, valueComparator);
}
}
if (keyComparator != null) {
- Multimap<K, V> sortedCopy = new BuilderMultimap<K, V>();
- List<Map.Entry<K, Collection<V>>> entries = Lists.newArrayList(
- builderMultimap.asMap().entrySet());
- Collections.sort(
- entries,
- Ordering.from(keyComparator).<K>onKeys());
+ Multimap<K, V> sortedCopy =
+ MultimapBuilder.linkedHashKeys().arrayListValues().<K, V>build();
+ List<Map.Entry<K, Collection<V>>> entries =
+ Ordering.from(keyComparator)
+ .<K>onKeys()
+ .immutableSortedCopy(builderMultimap.asMap().entrySet());
for (Map.Entry<K, Collection<V>> entry : entries) {
sortedCopy.putAll(entry.getKey(), entry.getValue());
}
@@ -275,8 +285,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
/**
* Returns an immutable multimap containing the same mappings as {@code
- * multimap}. The generated multimap's key and value orderings correspond to
- * the iteration ordering of the {@code multimap.asMap()} view.
+ * multimap}, in the "key-grouped" iteration order described in the class
+ * documentation.
*
* <p>Despite the method name, this method attempts to avoid actually copying
* the data when it is safe to do so. The exact circumstances under which a
@@ -285,12 +295,10 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
* @throws NullPointerException if any key or value in {@code multimap} is
* null
*/
- public static <K, V> ImmutableMultimap<K, V> copyOf(
- Multimap<? extends K, ? extends V> multimap) {
+ public static <K, V> ImmutableMultimap<K, V> copyOf(Multimap<? extends K, ? extends V> multimap) {
if (multimap instanceof ImmutableMultimap) {
@SuppressWarnings("unchecked") // safe since multimap is not writable
- ImmutableMultimap<K, V> kvMultimap
- = (ImmutableMultimap<K, V>) multimap;
+ ImmutableMultimap<K, V> kvMultimap = (ImmutableMultimap<K, V>) multimap;
if (!kvMultimap.isPartialView()) {
return kvMultimap;
}
@@ -298,6 +306,21 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
return ImmutableListMultimap.copyOf(multimap);
}
+ /**
+ * Returns an immutable multimap containing the specified entries. The
+ * returned multimap iterates over keys in the order they were first
+ * encountered in the input, and the values for each key are iterated in the
+ * order they were encountered.
+ *
+ * @throws NullPointerException if any key, value, or entry is null
+ * @since 19.0
+ */
+ @Beta
+ public static <K, V> ImmutableMultimap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ return ImmutableListMultimap.copyOf(entries);
+ }
+
final transient ImmutableMap<K, ? extends ImmutableCollection<V>> map;
final transient int size;
@@ -306,19 +329,15 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
// deserialized.
@GwtIncompatible("java serialization is not supported")
static class FieldSettersHolder {
- static final Serialization.FieldSetter<ImmutableMultimap>
- MAP_FIELD_SETTER = Serialization.getFieldSetter(
- ImmutableMultimap.class, "map");
- static final Serialization.FieldSetter<ImmutableMultimap>
- SIZE_FIELD_SETTER = Serialization.getFieldSetter(
- ImmutableMultimap.class, "size");
- static final Serialization.FieldSetter<ImmutableSetMultimap>
- EMPTY_SET_FIELD_SETTER = Serialization.getFieldSetter(
- ImmutableSetMultimap.class, "emptySet");
- }
-
- ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map,
- int size) {
+ static final Serialization.FieldSetter<ImmutableMultimap> MAP_FIELD_SETTER =
+ Serialization.getFieldSetter(ImmutableMultimap.class, "map");
+ static final Serialization.FieldSetter<ImmutableMultimap> SIZE_FIELD_SETTER =
+ Serialization.getFieldSetter(ImmutableMultimap.class, "size");
+ static final Serialization.FieldSetter<ImmutableSetMultimap> EMPTY_SET_FIELD_SETTER =
+ Serialization.getFieldSetter(ImmutableSetMultimap.class, "emptySet");
+ }
+
+ ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map, int size) {
this.map = map;
this.size = size;
}
@@ -345,8 +364,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
*/
@Deprecated
@Override
- public ImmutableCollection<V> replaceValues(K key,
- Iterable<? extends V> values) {
+ public ImmutableCollection<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
@@ -427,7 +445,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
}
-
+
/**
* Returns {@code true} if this immutable multimap's implementation contains references to
* user-created objects that aren't accessible via this multimap's methods. This is generally
@@ -449,7 +467,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
public boolean containsValue(@Nullable Object value) {
return value != null && super.containsValue(value);
}
-
+
@Override
public int size() {
return size;
@@ -458,9 +476,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
// views
/**
- * Returns an immutable set of the distinct keys in this multimap. These keys
- * are ordered according to when they first appeared during the construction
- * of this multimap.
+ * Returns an immutable set of the distinct keys in this multimap, in the same
+ * order as they appear in this multimap.
*/
@Override
public ImmutableSet<K> keySet() {
@@ -469,47 +486,47 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
/**
* Returns an immutable map that associates each key with its corresponding
- * values in the multimap.
+ * values in the multimap. Keys and values appear in the same order as in this
+ * multimap.
*/
@Override
@SuppressWarnings("unchecked") // a widening cast
public ImmutableMap<K, Collection<V>> asMap() {
return (ImmutableMap) map;
}
-
+
@Override
Map<K, Collection<V>> createAsMap() {
throw new AssertionError("should never be called");
}
/**
- * Returns an immutable collection of all key-value pairs in the multimap. Its
- * iterator traverses the values for the first key, the values for the second
- * key, and so on.
+ * Returns an immutable collection of all key-value pairs in the multimap.
*/
@Override
public ImmutableCollection<Entry<K, V>> entries() {
return (ImmutableCollection<Entry<K, V>>) super.entries();
}
-
+
@Override
ImmutableCollection<Entry<K, V>> createEntries() {
return new EntryCollection<K, V>(this);
}
- private static class EntryCollection<K, V>
- extends ImmutableCollection<Entry<K, V>> {
- final ImmutableMultimap<K, V> multimap;
+ private static class EntryCollection<K, V> extends ImmutableCollection<Entry<K, V>> {
+ @Weak final ImmutableMultimap<K, V> multimap;
EntryCollection(ImmutableMultimap<K, V> multimap) {
this.multimap = multimap;
}
- @Override public UnmodifiableIterator<Entry<K, V>> iterator() {
+ @Override
+ public UnmodifiableIterator<Entry<K, V>> iterator() {
return multimap.entryIterator();
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return multimap.isPartialView();
}
@@ -518,7 +535,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
return multimap.size();
}
- @Override public boolean contains(Object object) {
+ @Override
+ public boolean contains(Object object) {
if (object instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) object;
return multimap.containsEntry(entry.getKey(), entry.getValue());
@@ -528,12 +546,12 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
private static final long serialVersionUID = 0;
}
-
+
private abstract class Itr<T> extends UnmodifiableIterator<T> {
final Iterator<Entry<K, Collection<V>>> mapIterator = asMap().entrySet().iterator();
K key = null;
Iterator<V> valueIterator = Iterators.emptyIterator();
-
+
abstract T output(K key, V value);
@Override
@@ -551,7 +569,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
return output(key, valueIterator.next());
}
}
-
+
@Override
UnmodifiableIterator<Entry<K, V>> entryIterator() {
return new Itr<Entry<K, V>>() {
@@ -563,10 +581,9 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
}
/**
- * Returns a collection, which may contain duplicates, of all keys. The number
- * of times a key appears in the returned multiset equals the number of
- * mappings the key has in the multimap. Duplicate keys appear consecutively
- * in the multiset's iteration order.
+ * Returns an immutable multiset containing all the keys in this multimap, in
+ * the same order and with the same frequencies as they appear in this
+ * multimap; to get only a single occurrence of each key, use {@link #keySet}.
*/
@Override
public ImmutableMultiset<K> keys() {
@@ -579,6 +596,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
}
@SuppressWarnings("serial") // Uses writeReplace, not default serialization
+ @WeakOuter
class Keys extends ImmutableMultiset<K> {
@Override
public boolean contains(@Nullable Object object) {
@@ -600,7 +618,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
public int size() {
return ImmutableMultimap.this.size();
}
-
+
@Override
Multiset.Entry<K> getEntry(int index) {
Map.Entry<K, ? extends Collection<V>> entry = map.entrySet().asList().get(index);
@@ -622,7 +640,7 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
public ImmutableCollection<V> values() {
return (ImmutableCollection<V>) super.values();
}
-
+
@Override
ImmutableCollection<V> createValues() {
return new Values<K, V>(this);
@@ -639,8 +657,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
}
private static final class Values<K, V> extends ImmutableCollection<V> {
- private transient final ImmutableMultimap<K, V> multimap;
-
+ @Weak private final transient ImmutableMultimap<K, V> multimap;
+
Values(ImmutableMultimap<K, V> multimap) {
this.multimap = multimap;
}
@@ -649,8 +667,9 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
public boolean contains(@Nullable Object object) {
return multimap.containsValue(object);
}
-
- @Override public UnmodifiableIterator<V> iterator() {
+
+ @Override
+ public UnmodifiableIterator<V> iterator() {
return multimap.valueIterator();
}
@@ -668,7 +687,8 @@ public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
return multimap.size();
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return true;
}
diff --git a/guava/src/com/google/common/collect/ImmutableMultiset.java b/guava/src/com/google/common/collect/ImmutableMultiset.java
index 1b060f6..02c51ca 100644
--- a/guava/src/com/google/common/collect/ImmutableMultiset.java
+++ b/guava/src/com/google/common/collect/ImmutableMultiset.java
@@ -21,46 +21,42 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.Multiset.Entry;
-import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import javax.annotation.Nullable;
/**
- * An immutable hash-based multiset. Does not permit null elements.
+ * A {@link Multiset} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
- * <p>Its iterator orders elements according to the first appearance of the
- * element among the items passed to the factory method or builder. When the
- * multiset contains multiple instances of an element, those instances are
- * consecutive in the iteration order.
+ * <p><b>Grouped iteration.</b> In all current implementations, duplicate elements always appear
+ * consecutively when iterating. Elements iterate in order by the <i>first</i> appearance of
+ * that element when the multiset was created.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Jared Levy
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
-// TODO(user): write an efficient asList() implementation
-public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
- implements Multiset<E> {
-
- private static final ImmutableMultiset<Object> EMPTY =
- new RegularImmutableMultiset<Object>(ImmutableMap.<Object, Integer>of(), 0);
-
+// TODO(lowasser): write an efficient asList() implementation
+public abstract class ImmutableMultiset<E> extends ImmutableCollection<E> implements Multiset<E> {
/**
* Returns the empty immutable multiset.
*/
@SuppressWarnings("unchecked") // all supported methods are covariant
public static <E> ImmutableMultiset<E> of() {
- return (ImmutableMultiset<E>) EMPTY;
+ return (ImmutableMultiset<E>) RegularImmutableMultiset.EMPTY;
}
/**
@@ -71,7 +67,7 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
*/
@SuppressWarnings("unchecked") // generic array created but never written
public static <E> ImmutableMultiset<E> of(E element) {
- return copyOfInternal(element);
+ return copyFromElements(element);
}
/**
@@ -82,51 +78,54 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
*/
@SuppressWarnings("unchecked") //
public static <E> ImmutableMultiset<E> of(E e1, E e2) {
- return copyOfInternal(e1, e2);
+ return copyFromElements(e1, e2);
}
/**
- * Returns an immutable multiset containing the given elements, in order.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any element is null
* @since 6.0 (source-compatible since 2.0)
*/
@SuppressWarnings("unchecked") //
public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3) {
- return copyOfInternal(e1, e2, e3);
+ return copyFromElements(e1, e2, e3);
}
/**
- * Returns an immutable multiset containing the given elements, in order.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any element is null
* @since 6.0 (source-compatible since 2.0)
*/
@SuppressWarnings("unchecked") //
public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4) {
- return copyOfInternal(e1, e2, e3, e4);
+ return copyFromElements(e1, e2, e3, e4);
}
/**
- * Returns an immutable multiset containing the given elements, in order.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any element is null
* @since 6.0 (source-compatible since 2.0)
*/
@SuppressWarnings("unchecked") //
public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4, E e5) {
- return copyOfInternal(e1, e2, e3, e4, e5);
+ return copyFromElements(e1, e2, e3, e4, e5);
}
/**
- * Returns an immutable multiset containing the given elements, in order.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any element is null
* @since 6.0 (source-compatible since 2.0)
*/
@SuppressWarnings("unchecked") //
- public static <E> ImmutableMultiset<E> of(
- E e1, E e2, E e3, E e4, E e5, E e6, E... others) {
+ public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) {
return new Builder<E>()
.add(e1)
.add(e2)
@@ -139,38 +138,23 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
}
/**
- * Returns an immutable multiset containing the given elements.
- *
- * <p>The multiset is ordered by the first occurrence of each element. For
- * example, {@code ImmutableMultiset.copyOf([2, 3, 1, 3])} yields a multiset
- * with elements in the order {@code 2, 3, 3, 1}.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any of {@code elements} is null
* @since 6.0
*/
public static <E> ImmutableMultiset<E> copyOf(E[] elements) {
- return copyOf(Arrays.asList(elements));
+ return copyFromElements(elements);
}
/**
- * Returns an immutable multiset containing the given elements.
- *
- * <p>The multiset is ordered by the first occurrence of each element. For
- * example, {@code ImmutableMultiset.copyOf(Arrays.asList(2, 3, 1, 3))} yields
- * a multiset with elements in the order {@code 2, 3, 3, 1}.
- *
- * <p>Despite the method name, this method attempts to avoid actually copying
- * the data when it is safe to do so. The exact circumstances under which a
- * copy will or will not be performed are undocumented and subject to change.
- *
- * <p><b>Note:</b> Despite what the method name suggests, if {@code elements}
- * is an {@code ImmutableMultiset}, no copy will actually be performed, and
- * the given multiset itself will be returned.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any of {@code elements} is null
*/
- public static <E> ImmutableMultiset<E> copyOf(
- Iterable<? extends E> elements) {
+ public static <E> ImmutableMultiset<E> copyOf(Iterable<? extends E> elements) {
if (elements instanceof ImmutableMultiset) {
@SuppressWarnings("unchecked") // all supported methods are covariant
ImmutableMultiset<E> result = (ImmutableMultiset<E>) elements;
@@ -179,63 +163,45 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
}
}
- Multiset<? extends E> multiset = (elements instanceof Multiset)
- ? Multisets.cast(elements)
- : LinkedHashMultiset.create(elements);
+ Multiset<? extends E> multiset =
+ (elements instanceof Multiset)
+ ? Multisets.cast(elements)
+ : LinkedHashMultiset.create(elements);
- return copyOfInternal(multiset);
- }
-
- private static <E> ImmutableMultiset<E> copyOfInternal(E... elements) {
- return copyOf(Arrays.asList(elements));
+ return copyFromEntries(multiset.entrySet());
}
- private static <E> ImmutableMultiset<E> copyOfInternal(
- Multiset<? extends E> multiset) {
+ private static <E> ImmutableMultiset<E> copyFromElements(E... elements) {
+ Multiset<E> multiset = LinkedHashMultiset.create();
+ Collections.addAll(multiset, elements);
return copyFromEntries(multiset.entrySet());
}
static <E> ImmutableMultiset<E> copyFromEntries(
Collection<? extends Entry<? extends E>> entries) {
- long size = 0;
- ImmutableMap.Builder<E, Integer> builder = ImmutableMap.builder();
- for (Entry<? extends E> entry : entries) {
- int count = entry.getCount();
- if (count > 0) {
- // Since ImmutableMap.Builder throws an NPE if an element is null, no
- // other null checks are needed.
- builder.put(entry.getElement(), count);
- size += count;
- }
- }
-
- if (size == 0) {
+ if (entries.isEmpty()) {
return of();
+ } else {
+ return new RegularImmutableMultiset<E>(entries);
}
- return new RegularImmutableMultiset<E>(
- builder.build(), Ints.saturatedCast(size));
}
/**
- * Returns an immutable multiset containing the given elements.
- *
- * <p>The multiset is ordered by the first occurrence of each element. For
- * example,
- * {@code ImmutableMultiset.copyOf(Arrays.asList(2, 3, 1, 3).iterator())}
- * yields a multiset with elements in the order {@code 2, 3, 3, 1}.
+ * Returns an immutable multiset containing the given elements, in the "grouped iteration order"
+ * described in the class documentation.
*
* @throws NullPointerException if any of {@code elements} is null
*/
- public static <E> ImmutableMultiset<E> copyOf(
- Iterator<? extends E> elements) {
+ public static <E> ImmutableMultiset<E> copyOf(Iterator<? extends E> elements) {
Multiset<E> multiset = LinkedHashMultiset.create();
Iterators.addAll(multiset, elements);
- return copyOfInternal(multiset);
+ return copyFromEntries(multiset.entrySet());
}
ImmutableMultiset() {}
- @Override public UnmodifiableIterator<E> iterator() {
+ @Override
+ public UnmodifiableIterator<E> iterator() {
final Iterator<Entry<E>> entryIterator = entrySet().iterator();
return new UnmodifiableIterator<E>() {
int remaining;
@@ -264,11 +230,6 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
return count(object) > 0;
}
- @Override
- public boolean containsAll(Collection<?> targets) {
- return elementSet().containsAll(targets);
- }
-
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
@@ -327,15 +288,18 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
return offset;
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return Multisets.equalsImpl(this, object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Sets.hashCodeImpl(entrySet());
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return entrySet().toString();
}
@@ -353,30 +317,16 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
abstract Entry<E> getEntry(int index);
- private final class EntrySet extends ImmutableSet<Entry<E>> {
+ @WeakOuter
+ private final class EntrySet extends ImmutableSet.Indexed<Entry<E>> {
@Override
boolean isPartialView() {
return ImmutableMultiset.this.isPartialView();
}
@Override
- public UnmodifiableIterator<Entry<E>> iterator() {
- return asList().iterator();
- }
-
- @Override
- ImmutableList<Entry<E>> createAsList() {
- return new ImmutableAsList<Entry<E>>() {
- @Override
- public Entry<E> get(int index) {
- return getEntry(index);
- }
-
- @Override
- ImmutableCollection<Entry<E>> delegateCollection() {
- return EntrySet.this;
- }
- };
+ Entry<E> get(int index) {
+ return getEntry(index);
}
@Override
@@ -441,8 +391,7 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
}
Object readResolve() {
- LinkedHashMultiset<Object> multiset =
- LinkedHashMultiset.create(elements.length);
+ LinkedHashMultiset<Object> multiset = LinkedHashMultiset.create(elements.length);
for (int i = 0; i < elements.length; i++) {
multiset.add(elements[i], counts[i]);
}
@@ -482,7 +431,7 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
* <p>Builder instances can be reused; it is safe to call {@link #build} multiple
* times to build multiple multisets in series.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public static class Builder<E> extends ImmutableCollection.Builder<E> {
final Multiset<E> contents;
@@ -506,7 +455,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
* @return this {@code Builder} object
* @throws NullPointerException if {@code element} is null
*/
- @Override public Builder<E> add(E element) {
+ @Override
+ public Builder<E> add(E element) {
contents.add(checkNotNull(element));
return this;
}
@@ -552,7 +502,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
- @Override public Builder<E> add(E... elements) {
+ @Override
+ public Builder<E> add(E... elements) {
super.add(elements);
return this;
}
@@ -566,7 +517,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
- @Override public Builder<E> addAll(Iterable<? extends E> elements) {
+ @Override
+ public Builder<E> addAll(Iterable<? extends E> elements) {
if (elements instanceof Multiset) {
Multiset<? extends E> multiset = Multisets.cast(elements);
for (Entry<? extends E> entry : multiset.entrySet()) {
@@ -586,7 +538,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
- @Override public Builder<E> addAll(Iterator<? extends E> elements) {
+ @Override
+ public Builder<E> addAll(Iterator<? extends E> elements) {
super.addAll(elements);
return this;
}
@@ -595,7 +548,8 @@ public abstract class ImmutableMultiset<E> extends ImmutableCollection<E>
* Returns a newly-created {@code ImmutableMultiset} based on the contents
* of the {@code Builder}.
*/
- @Override public ImmutableMultiset<E> build() {
+ @Override
+ public ImmutableMultiset<E> build() {
return copyOf(contents);
}
}
diff --git a/guava/src/com/google/common/collect/ImmutableRangeMap.java b/guava/src/com/google/common/collect/ImmutableRangeMap.java
index 49b3989..a96b857 100644
--- a/guava/src/com/google/common/collect/ImmutableRangeMap.java
+++ b/guava/src/com/google/common/collect/ImmutableRangeMap.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.SortedLists.KeyAbsentBehavior;
import com.google.common.collect.SortedLists.KeyPresentBehavior;
+import java.io.Serializable;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
@@ -30,16 +31,15 @@ import java.util.NoSuchElementException;
import javax.annotation.Nullable;
/**
- * An immutable implementation of {@code RangeMap}, supporting all query operations efficiently.
- *
- * <p>Like all {@code RangeMap} implementations, this supports neither null keys nor null values.
+ * A {@link RangeMap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
* @author Louis Wasserman
* @since 14.0
*/
@Beta
@GwtIncompatible("NavigableMap")
-public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K, V> {
+public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K, V>, Serializable {
private static final ImmutableRangeMap<Comparable<?>, Object> EMPTY =
new ImmutableRangeMap<Comparable<?>, Object>(
@@ -56,8 +56,7 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
/**
* Returns an immutable range map mapping a single range to a single value.
*/
- public static <K extends Comparable<?>, V> ImmutableRangeMap<K, V> of(
- Range<K> range, V value) {
+ public static <K extends Comparable<?>, V> ImmutableRangeMap<K, V> of(Range<K> range, V value) {
return new ImmutableRangeMap<K, V>(ImmutableList.of(range), ImmutableList.of(value));
}
@@ -151,8 +150,8 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
}
}
- private final ImmutableList<Range<K>> ranges;
- private final ImmutableList<V> values;
+ private final transient ImmutableList<Range<K>> ranges;
+ private final transient ImmutableList<V> values;
ImmutableRangeMap(ImmutableList<Range<K>> ranges, ImmutableList<V> values) {
this.ranges = ranges;
@@ -162,8 +161,13 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
@Override
@Nullable
public V get(K key) {
- int index = SortedLists.binarySearch(ranges, Range.<K>lowerBoundFn(),
- Cut.belowValue(key), KeyPresentBehavior.ANY_PRESENT, KeyAbsentBehavior.NEXT_LOWER);
+ int index =
+ SortedLists.binarySearch(
+ ranges,
+ Range.<K>lowerBoundFn(),
+ Cut.belowValue(key),
+ KeyPresentBehavior.ANY_PRESENT,
+ KeyAbsentBehavior.NEXT_LOWER);
if (index == -1) {
return null;
} else {
@@ -175,8 +179,13 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
@Override
@Nullable
public Map.Entry<Range<K>, V> getEntry(K key) {
- int index = SortedLists.binarySearch(ranges, Range.<K>lowerBoundFn(),
- Cut.belowValue(key), KeyPresentBehavior.ANY_PRESENT, KeyAbsentBehavior.NEXT_LOWER);
+ int index =
+ SortedLists.binarySearch(
+ ranges,
+ Range.<K>lowerBoundFn(),
+ Cut.belowValue(key),
+ KeyPresentBehavior.ANY_PRESENT,
+ KeyAbsentBehavior.NEXT_LOWER);
if (index == -1) {
return null;
} else {
@@ -222,9 +231,20 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
}
RegularImmutableSortedSet<Range<K>> rangeSet =
new RegularImmutableSortedSet<Range<K>>(ranges, Range.RANGE_LEX_ORDERING);
- return new RegularImmutableSortedMap<Range<K>, V>(rangeSet, values);
+ return new ImmutableSortedMap<Range<K>, V>(rangeSet, values);
+ }
+
+ @Override
+ public ImmutableMap<Range<K>, V> asDescendingMapOfRanges() {
+ if (ranges.isEmpty()) {
+ return ImmutableMap.of();
+ }
+ RegularImmutableSortedSet<Range<K>> rangeSet =
+ new RegularImmutableSortedSet<Range<K>>(
+ ranges.reverse(), Range.RANGE_LEX_ORDERING.reverse());
+ return new ImmutableSortedMap<Range<K>, V>(rangeSet, values.reverse());
}
-
+
@Override
public ImmutableRangeMap<K, V> subRangeMap(final Range<K> range) {
if (checkNotNull(range).isEmpty()) {
@@ -232,49 +252,57 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
} else if (ranges.isEmpty() || range.encloses(span())) {
return this;
}
- int lowerIndex = SortedLists.binarySearch(
- ranges, Range.<K>upperBoundFn(), range.lowerBound,
- KeyPresentBehavior.FIRST_AFTER, KeyAbsentBehavior.NEXT_HIGHER);
- int upperIndex = SortedLists.binarySearch(ranges,
- Range.<K>lowerBoundFn(), range.upperBound,
- KeyPresentBehavior.ANY_PRESENT, KeyAbsentBehavior.NEXT_HIGHER);
+ int lowerIndex =
+ SortedLists.binarySearch(
+ ranges,
+ Range.<K>upperBoundFn(),
+ range.lowerBound,
+ KeyPresentBehavior.FIRST_AFTER,
+ KeyAbsentBehavior.NEXT_HIGHER);
+ int upperIndex =
+ SortedLists.binarySearch(
+ ranges,
+ Range.<K>lowerBoundFn(),
+ range.upperBound,
+ KeyPresentBehavior.ANY_PRESENT,
+ KeyAbsentBehavior.NEXT_HIGHER);
if (lowerIndex >= upperIndex) {
return ImmutableRangeMap.of();
}
final int off = lowerIndex;
final int len = upperIndex - lowerIndex;
- ImmutableList<Range<K>> subRanges = new ImmutableList<Range<K>>() {
- @Override
- public int size() {
- return len;
- }
-
- @Override
- public Range<K> get(int index) {
- checkElementIndex(index, len);
- if (index == 0 || index == len - 1) {
- return ranges.get(index + off).intersection(range);
- } else {
- return ranges.get(index + off);
- }
- }
+ ImmutableList<Range<K>> subRanges =
+ new ImmutableList<Range<K>>() {
+ @Override
+ public int size() {
+ return len;
+ }
- @Override
- boolean isPartialView() {
- return true;
- }
- };
- final ImmutableRangeMap<K, V> outer = this;
- return new ImmutableRangeMap<K, V>(
- subRanges, values.subList(lowerIndex, upperIndex)) {
@Override
- public ImmutableRangeMap<K, V> subRangeMap(Range<K> subRange) {
- if (range.isConnected(subRange)) {
- return outer.subRangeMap(subRange.intersection(range));
+ public Range<K> get(int index) {
+ checkElementIndex(index, len);
+ if (index == 0 || index == len - 1) {
+ return ranges.get(index + off).intersection(range);
} else {
- return ImmutableRangeMap.of();
+ return ranges.get(index + off);
}
}
+
+ @Override
+ boolean isPartialView() {
+ return true;
+ }
+ };
+ final ImmutableRangeMap<K, V> outer = this;
+ return new ImmutableRangeMap<K, V>(subRanges, values.subList(lowerIndex, upperIndex)) {
+ @Override
+ public ImmutableRangeMap<K, V> subRangeMap(Range<K> subRange) {
+ if (range.isConnected(subRange)) {
+ return outer.subRangeMap(subRange.intersection(range));
+ } else {
+ return ImmutableRangeMap.of();
+ }
+ }
};
}
@@ -296,4 +324,41 @@ public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K
public String toString() {
return asMapOfRanges().toString();
}
+
+ /**
+ * This class is used to serialize ImmutableRangeMap instances.
+ * Serializes the {@link #asMapOfRanges()} form.
+ */
+ private static class SerializedForm<K extends Comparable<?>, V> implements Serializable {
+
+ private final ImmutableMap<Range<K>, V> mapOfRanges;
+
+ SerializedForm(ImmutableMap<Range<K>, V> mapOfRanges) {
+ this.mapOfRanges = mapOfRanges;
+ }
+
+ Object readResolve() {
+ if (mapOfRanges.isEmpty()) {
+ return of();
+ } else {
+ return createRangeMap();
+ }
+ }
+
+ Object createRangeMap() {
+ Builder<K, V> builder = new Builder<K, V>();
+ for (Entry<Range<K>, V> entry : mapOfRanges.entrySet()) {
+ builder.put(entry.getKey(), entry.getValue());
+ }
+ return builder.build();
+ }
+
+ private static final long serialVersionUID = 0;
+ }
+
+ Object writeReplace() {
+ return new SerializedForm<K, V>(asMapOfRanges());
+ }
+
+ private static final long serialVersionUID = 0;
}
diff --git a/guava/src/com/google/common/collect/ImmutableRangeSet.java b/guava/src/com/google/common/collect/ImmutableRangeSet.java
index 9e72b97..6345e93 100644
--- a/guava/src/com/google/common/collect/ImmutableRangeSet.java
+++ b/guava/src/com/google/common/collect/ImmutableRangeSet.java
@@ -34,7 +34,8 @@ import java.util.Set;
import javax.annotation.Nullable;
/**
- * An efficient immutable implementation of a {@link RangeSet}.
+ * A {@link RangeSet} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
* @author Louis Wasserman
* @since 14.0
@@ -113,23 +114,27 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
@Override
public boolean encloses(Range<C> otherRange) {
- int index = SortedLists.binarySearch(ranges,
- Range.<C>lowerBoundFn(),
- otherRange.lowerBound,
- Ordering.natural(),
- ANY_PRESENT,
- NEXT_LOWER);
+ int index =
+ SortedLists.binarySearch(
+ ranges,
+ Range.<C>lowerBoundFn(),
+ otherRange.lowerBound,
+ Ordering.natural(),
+ ANY_PRESENT,
+ NEXT_LOWER);
return index != -1 && ranges.get(index).encloses(otherRange);
}
@Override
public Range<C> rangeContaining(C value) {
- int index = SortedLists.binarySearch(ranges,
- Range.<C>lowerBoundFn(),
- Cut.belowValue(value),
- Ordering.natural(),
- ANY_PRESENT,
- NEXT_LOWER);
+ int index =
+ SortedLists.binarySearch(
+ ranges,
+ Range.<C>lowerBoundFn(),
+ Cut.belowValue(value),
+ Ordering.natural(),
+ ANY_PRESENT,
+ NEXT_LOWER);
if (index != -1) {
Range<C> range = ranges.get(index);
return range.contains(value) ? range : null;
@@ -142,9 +147,7 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
if (ranges.isEmpty()) {
throw new NoSuchElementException();
}
- return Range.create(
- ranges.get(0).lowerBound,
- ranges.get(ranges.size() - 1).upperBound);
+ return Range.create(ranges.get(0).lowerBound, ranges.get(ranges.size() - 1).upperBound);
}
@Override
@@ -180,6 +183,15 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
return new RegularImmutableSortedSet<Range<C>>(ranges, Range.RANGE_LEX_ORDERING);
}
+ @Override
+ public ImmutableSet<Range<C>> asDescendingSetOfRanges() {
+ if (ranges.isEmpty()) {
+ return ImmutableSet.of();
+ }
+ return new RegularImmutableSortedSet<Range<C>>(
+ ranges.reverse(), Range.RANGE_LEX_ORDERING.reverse());
+ }
+
private transient ImmutableRangeSet<C> complement;
private final class ComplementRanges extends ImmutableList<Range<C>> {
@@ -266,18 +278,26 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
final int fromIndex;
if (range.hasLowerBound()) {
- fromIndex = SortedLists.binarySearch(
- ranges, Range.<C>upperBoundFn(), range.lowerBound, KeyPresentBehavior.FIRST_AFTER,
- KeyAbsentBehavior.NEXT_HIGHER);
+ fromIndex =
+ SortedLists.binarySearch(
+ ranges,
+ Range.<C>upperBoundFn(),
+ range.lowerBound,
+ KeyPresentBehavior.FIRST_AFTER,
+ KeyAbsentBehavior.NEXT_HIGHER);
} else {
fromIndex = 0;
}
int toIndex;
if (range.hasUpperBound()) {
- toIndex = SortedLists.binarySearch(
- ranges, Range.<C>lowerBoundFn(), range.upperBound, KeyPresentBehavior.FIRST_PRESENT,
- KeyAbsentBehavior.NEXT_HIGHER);
+ toIndex =
+ SortedLists.binarySearch(
+ ranges,
+ Range.<C>lowerBoundFn(),
+ range.upperBound,
+ KeyPresentBehavior.FIRST_PRESENT,
+ KeyAbsentBehavior.NEXT_HIGHER);
} else {
toIndex = ranges.size();
}
@@ -308,7 +328,7 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
};
}
}
-
+
/**
* Returns a view of the intersection of this range set with the given range.
*/
@@ -450,9 +470,10 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
if (!fromInclusive && !toInclusive && Range.compareOrThrow(fromElement, toElement) == 0) {
return ImmutableSortedSet.of();
}
- return subSet(Range.range(
- fromElement, BoundType.forBoolean(fromInclusive),
- toElement, BoundType.forBoolean(toInclusive)));
+ return subSet(
+ Range.range(
+ fromElement, BoundType.forBoolean(fromInclusive),
+ toElement, BoundType.forBoolean(toInclusive)));
}
@Override
@@ -563,7 +584,9 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange
for (Range<C> currentRange : rangeSet.asRanges()) {
checkArgument(
!currentRange.isConnected(range) || currentRange.intersection(range).isEmpty(),
- "Ranges may not overlap, but received %s and %s", currentRange, range);
+ "Ranges may not overlap, but received %s and %s",
+ currentRange,
+ range);
}
throw new AssertionError("should have thrown an IAE above");
}
diff --git a/guava/src/com/google/common/collect/ImmutableSet.java b/guava/src/com/google/common/collect/ImmutableSet.java
index c236182..ea5b691 100644
--- a/guava/src/com/google/common/collect/ImmutableSet.java
+++ b/guava/src/com/google/common/collect/ImmutableSet.java
@@ -28,126 +28,82 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.annotation.Nullable;
/**
- * A high-performance, immutable {@code Set} with reliable, user-specified
- * iteration order. Does not permit null elements.
+ * A {@link Set} whose contents will never change, with many other important properties detailed at
+ * {@link ImmutableCollection}.
*
- * <p>Unlike {@link Collections#unmodifiableSet}, which is a <i>view</i> of a
- * separate collection that can still change, an instance of this class contains
- * its own private data and will <i>never</i> change. This class is convenient
- * for {@code public static final} sets ("constant sets") and also lets you
- * easily make a "defensive copy" of a set provided to your class by a caller.
- *
- * <p><b>Warning:</b> Like most sets, an {@code ImmutableSet} will not function
- * correctly if an element is modified after being placed in the set. For this
- * reason, and to avoid general confusion, it is strongly recommended to place
- * only immutable objects into this collection.
- *
- * <p>This class has been observed to perform significantly better than {@link
- * HashSet} for objects with very fast {@link Object#hashCode} implementations
- * (as a well-behaved immutable object should). While this class's factory
- * methods create hash-based instances, the {@link ImmutableSortedSet} subclass
- * performs binary searches instead.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed
- * outside its package as it has no public or protected constructors. Thus,
- * instances of this type are guaranteed to be immutable.
- *
- * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
- * immutable collections</a>.
- *
- * @see ImmutableList
- * @see ImmutableMap
- * @author Kevin Bourrillion
- * @author Nick Kralevich
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
-public abstract class ImmutableSet<E> extends ImmutableCollection<E>
- implements Set<E> {
+public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements Set<E> {
/**
- * Returns the empty immutable set. This set behaves and performs comparably
- * to {@link Collections#emptySet}, and is preferable mainly for consistency
- * and maintainability of your code.
+ * Returns the empty immutable set. Preferred over {@link Collections#emptySet} for code
+ * consistency, and because the return type conveys the immutability guarantee.
*/
- // Casting to any type is safe because the set will never hold any elements.
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({"unchecked"}) // fully variant implementation (never actually produces any Es)
public static <E> ImmutableSet<E> of() {
- return (ImmutableSet<E>) EmptyImmutableSet.INSTANCE;
+ return (ImmutableSet<E>) RegularImmutableSet.EMPTY;
}
/**
- * Returns an immutable set containing a single element. This set behaves and
- * performs comparably to {@link Collections#singleton}, but will not accept
- * a null element. It is preferable mainly for consistency and
- * maintainability of your code.
+ * Returns an immutable set containing {@code element}. Preferred over {@link
+ * Collections#singleton} for code consistency, {@code null} rejection, and because the return
+ * type conveys the immutability guarantee.
*/
public static <E> ImmutableSet<E> of(E element) {
return new SingletonImmutableSet<E>(element);
}
/**
- * Returns an immutable set containing the given elements, in order. Repeated
- * occurrences of an element (according to {@link Object#equals}) after the
- * first are ignored.
- *
- * @throws NullPointerException if any element is null
+ * Returns an immutable set containing the given elements, minus duplicates, in the order each was
+ * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except
+ * the first are ignored.
*/
public static <E> ImmutableSet<E> of(E e1, E e2) {
return construct(2, e1, e2);
}
/**
- * Returns an immutable set containing the given elements, in order. Repeated
- * occurrences of an element (according to {@link Object#equals}) after the
- * first are ignored.
- *
- * @throws NullPointerException if any element is null
+ * Returns an immutable set containing the given elements, minus duplicates, in the order each was
+ * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except
+ * the first are ignored.
*/
public static <E> ImmutableSet<E> of(E e1, E e2, E e3) {
return construct(3, e1, e2, e3);
}
/**
- * Returns an immutable set containing the given elements, in order. Repeated
- * occurrences of an element (according to {@link Object#equals}) after the
- * first are ignored.
- *
- * @throws NullPointerException if any element is null
+ * Returns an immutable set containing the given elements, minus duplicates, in the order each was
+ * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except
+ * the first are ignored.
*/
public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4) {
return construct(4, e1, e2, e3, e4);
}
/**
- * Returns an immutable set containing the given elements, in order. Repeated
- * occurrences of an element (according to {@link Object#equals}) after the
- * first are ignored.
- *
- * @throws NullPointerException if any element is null
+ * Returns an immutable set containing the given elements, minus duplicates, in the order each was
+ * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except
+ * the first are ignored.
*/
public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5) {
return construct(5, e1, e2, e3, e4, e5);
}
/**
- * Returns an immutable set containing the given elements, in order. Repeated
- * occurrences of an element (according to {@link Object#equals}) after the
- * first are ignored.
+ * Returns an immutable set containing the given elements, minus duplicates, in the order each was
+ * first specified. That is, if multiple elements are {@linkplain Object#equals equal}, all except
+ * the first are ignored.
*
- * @throws NullPointerException if any element is null
* @since 3.0 (source-compatible since 2.0)
*/
- public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6,
- E... others) {
+ public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) {
final int paramCount = 6;
Object[] elements = new Object[paramCount + others.length];
elements[0] = e1;
@@ -219,9 +175,10 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
// when this happens, we have already made a copy
return construct(uniques, elements);
} else {
- Object[] uniqueElements = (uniques < elements.length)
- ? ObjectArrays.arraysCopyOf(elements, uniques)
- : elements;
+ Object[] uniqueElements =
+ (uniques < elements.length)
+ ? ObjectArrays.arraysCopyOf(elements, uniques)
+ : elements;
return new RegularImmutableSet<E>(uniqueElements, hashCode, table, mask);
}
}
@@ -233,8 +190,7 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
private static final double DESIRED_LOAD_FACTOR = 0.7;
// If the set has this many elements, it will "max out" the table size
- private static final int CUTOFF =
- (int) (MAX_TABLE_SIZE * DESIRED_LOAD_FACTOR);
+ private static final int CUTOFF = (int) (MAX_TABLE_SIZE * DESIRED_LOAD_FACTOR);
/**
* Returns an array size suitable for the backing array of a hash table that
@@ -244,7 +200,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
*
* <p>Do not call this method with setSize < 2.
*/
- @VisibleForTesting static int chooseTableSize(int setSize) {
+ @VisibleForTesting
+ static int chooseTableSize(int setSize) {
// Correct the size for open addressing to match desired load factor.
if (setSize < CUTOFF) {
// Round up to the next highest power of 2.
@@ -261,38 +218,44 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
}
/**
- * Returns an immutable set containing the given elements, in order. Repeated
- * occurrences of an element (according to {@link Object#equals}) after the
- * first are ignored.
+ * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order
+ * each appears first in the source collection.
+ *
+ * <p><b>Performance note:</b> This method will sometimes recognize that the actual copy operation
+ * is unnecessary; for example, {@code copyOf(copyOf(anArrayList))} will copy the data only once.
+ * This reduces the expense of habitually making defensive copies at API boundaries. However, the
+ * the precise conditions for skipping the copy operation are undefined.
*
* @throws NullPointerException if any of {@code elements} is null
- * @since 3.0
+ * @since 7.0 (source-compatible since 2.0)
*/
- public static <E> ImmutableSet<E> copyOf(E[] elements) {
- switch (elements.length) {
- case 0:
- return of();
- case 1:
- return of(elements[0]);
- default:
- return construct(elements.length, elements.clone());
+ public static <E> ImmutableSet<E> copyOf(Collection<? extends E> elements) {
+ /*
+ * TODO(lowasser): consider checking for ImmutableAsList here
+ * TODO(lowasser): consider checking for Multiset here
+ */
+ if (elements instanceof ImmutableSet && !(elements instanceof ImmutableSortedSet)) {
+ @SuppressWarnings("unchecked") // all supported methods are covariant
+ ImmutableSet<E> set = (ImmutableSet<E>) elements;
+ if (!set.isPartialView()) {
+ return set;
+ }
+ } else if (elements instanceof EnumSet) {
+ return copyOfEnumSet((EnumSet) elements);
}
+ Object[] array = elements.toArray();
+ return construct(array.length, array);
}
/**
- * Returns an immutable set containing the given elements, in order. Repeated
- * occurrences of an element (according to {@link Object#equals}) after the
- * first are ignored. This method iterates over {@code elements} at most once.
- *
- * <p>Note that if {@code s} is a {@code Set<String>}, then {@code
- * ImmutableSet.copyOf(s)} returns an {@code ImmutableSet<String>} containing
- * each of the strings in {@code s}, while {@code ImmutableSet.of(s)} returns
- * a {@code ImmutableSet<Set<String>>} containing one element (the given set
- * itself).
+ * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order
+ * each appears first in the source iterable. This method iterates over {@code elements} only
+ * once.
*
- * <p>Despite the method name, this method attempts to avoid actually copying
- * the data when it is safe to do so. The exact circumstances under which a
- * copy will or will not be performed are undocumented and subject to change.
+ * <p><b>Performance note:</b> This method will sometimes recognize that the actual copy operation
+ * is unnecessary; for example, {@code copyOf(copyOf(anArrayList))} should copy the data only
+ * once. This reduces the expense of habitually making defensive copies at API boundaries.
+ * However, the precise conditions for skipping the copy operation are undefined.
*
* @throws NullPointerException if any of {@code elements} is null
*/
@@ -303,9 +266,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
}
/**
- * Returns an immutable set containing the given elements, in order. Repeated
- * occurrences of an element (according to {@link Object#equals}) after the
- * first are ignored.
+ * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order
+ * each appears first in the source iterator.
*
* @throws NullPointerException if any of {@code elements} is null
*/
@@ -326,57 +288,25 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
}
/**
- * Returns an immutable set containing the given elements, in order. Repeated
- * occurrences of an element (according to {@link Object#equals}) after the
- * first are ignored. This method iterates over {@code elements} at most
- * once.
- *
- * <p>Note that if {@code s} is a {@code Set<String>}, then {@code
- * ImmutableSet.copyOf(s)} returns an {@code ImmutableSet<String>} containing
- * each of the strings in {@code s}, while {@code ImmutableSet.of(s)} returns
- * a {@code ImmutableSet<Set<String>>} containing one element (the given set
- * itself).
- *
- * <p><b>Note:</b> Despite what the method name suggests, {@code copyOf} will
- * return constant-space views, rather than linear-space copies, of some
- * inputs known to be immutable. For some other immutable inputs, such as key
- * sets of an {@code ImmutableMap}, it still performs a copy in order to avoid
- * holding references to the values of the map. The heuristics used in this
- * decision are undocumented and subject to change except that:
- * <ul>
- * <li>A full copy will be done of any {@code ImmutableSortedSet}.</li>
- * <li>{@code ImmutableSet.copyOf()} is idempotent with respect to pointer
- * equality.</li>
- * </ul>
- *
- * <p>This method is safe to use even when {@code elements} is a synchronized
- * or concurrent collection that is currently being modified by another
- * thread.
+ * Returns an immutable set containing each of {@code elements}, minus duplicates, in the order
+ * each appears first in the source array.
*
* @throws NullPointerException if any of {@code elements} is null
- * @since 7.0 (source-compatible since 2.0)
+ * @since 3.0
*/
- public static <E> ImmutableSet<E> copyOf(Collection<? extends E> elements) {
- /*
- * TODO(user): consider checking for ImmutableAsList here
- * TODO(user): consider checking for Multiset here
- */
- if (elements instanceof ImmutableSet
- && !(elements instanceof ImmutableSortedSet)) {
- @SuppressWarnings("unchecked") // all supported methods are covariant
- ImmutableSet<E> set = (ImmutableSet<E>) elements;
- if (!set.isPartialView()) {
- return set;
- }
- } else if (elements instanceof EnumSet) {
- return copyOfEnumSet((EnumSet) elements);
+ public static <E> ImmutableSet<E> copyOf(E[] elements) {
+ switch (elements.length) {
+ case 0:
+ return of();
+ case 1:
+ return of(elements[0]);
+ default:
+ return construct(elements.length, elements.clone());
}
- Object[] array = elements.toArray();
- return construct(array.length, array);
}
- private static <E extends Enum<E>> ImmutableSet<E> copyOfEnumSet(
- EnumSet<E> enumSet) {
+ @SuppressWarnings("rawtypes") // necessary to compile against Java 8
+ private static ImmutableSet copyOfEnumSet(EnumSet enumSet) {
return ImmutableEnumSet.asImmutable(EnumSet.copyOf(enumSet));
}
@@ -387,7 +317,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
return false;
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
} else if (object instanceof ImmutableSet
@@ -399,13 +330,39 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
return Sets.equalsImpl(this, object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Sets.hashCodeImpl(this);
}
// This declaration is needed to make Set.iterator() and
// ImmutableCollection.iterator() consistent.
- @Override public abstract UnmodifiableIterator<E> iterator();
+ @Override
+ public abstract UnmodifiableIterator<E> iterator();
+
+ abstract static class Indexed<E> extends ImmutableSet<E> {
+ abstract E get(int index);
+
+ @Override
+ public UnmodifiableIterator<E> iterator() {
+ return asList().iterator();
+ }
+
+ @Override
+ ImmutableList<E> createAsList() {
+ return new ImmutableAsList<E>() {
+ @Override
+ public E get(int index) {
+ return Indexed.this.get(index);
+ }
+
+ @Override
+ Indexed<E> delegateCollection() {
+ return Indexed.this;
+ }
+ };
+ }
+ }
/*
* This class is used to serialize all ImmutableSet instances, except for
@@ -416,16 +373,20 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
*/
private static class SerializedForm implements Serializable {
final Object[] elements;
+
SerializedForm(Object[] elements) {
this.elements = elements;
}
+
Object readResolve() {
return copyOf(elements);
}
+
private static final long serialVersionUID = 0;
}
- @Override Object writeReplace() {
+ @Override
+ Object writeReplace() {
return new SerializedForm(toArray());
}
@@ -438,20 +399,18 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
}
/**
- * A builder for creating immutable set instances, especially {@code public
- * static final} sets ("constant sets"). Example: <pre> {@code
+ * A builder for creating {@code ImmutableSet} instances. Example: <pre> {@code
*
- * public static final ImmutableSet<Color> GOOGLE_COLORS =
- * new ImmutableSet.Builder<Color>()
+ * static final ImmutableSet<Color> GOOGLE_COLORS =
+ * ImmutableSet.<Color>builder()
* .addAll(WEBSAFE_COLORS)
* .add(new Color(0, 191, 255))
* .build();}</pre>
*
- * <p>Builder instances can be reused; it is safe to call {@link #build} multiple
- * times to build multiple sets in series. Each set is a superset of the set
- * created before it.
+ * <p>Building does not change the state of the builder, so it is still possible to add more
+ * elements and to build again.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public static class Builder<E> extends ImmutableCollection.ArrayBasedBuilder<E> {
@@ -476,7 +435,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
* @return this {@code Builder} object
* @throws NullPointerException if {@code element} is null
*/
- @Override public Builder<E> add(E element) {
+ @Override
+ public Builder<E> add(E element) {
super.add(element);
return this;
}
@@ -490,7 +450,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
- @Override public Builder<E> add(E... elements) {
+ @Override
+ public Builder<E> add(E... elements) {
super.add(elements);
return this;
}
@@ -504,7 +465,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
- @Override public Builder<E> addAll(Iterable<? extends E> elements) {
+ @Override
+ public Builder<E> addAll(Iterable<? extends E> elements) {
super.addAll(elements);
return this;
}
@@ -518,7 +480,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
* @throws NullPointerException if {@code elements} is null or contains a
* null element
*/
- @Override public Builder<E> addAll(Iterator<? extends E> elements) {
+ @Override
+ public Builder<E> addAll(Iterator<? extends E> elements) {
super.addAll(elements);
return this;
}
@@ -527,7 +490,8 @@ public abstract class ImmutableSet<E> extends ImmutableCollection<E>
* Returns a newly-created {@code ImmutableSet} based on the contents of
* the {@code Builder}.
*/
- @Override public ImmutableSet<E> build() {
+ @Override
+ public ImmutableSet<E> build() {
ImmutableSet<E> result = construct(size, contents);
// construct has the side effect of deduping contents, so we update size
// accordingly.
diff --git a/guava/src/com/google/common/collect/ImmutableSetMultimap.java b/guava/src/com/google/common/collect/ImmutableSetMultimap.java
index ce24af2..5cad010 100644
--- a/guava/src/com/google/common/collect/ImmutableSetMultimap.java
+++ b/guava/src/com/google/common/collect/ImmutableSetMultimap.java
@@ -17,11 +17,12 @@
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
-import static java.util.Arrays.asList;
+import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.MoreObjects;
+import com.google.j2objc.annotations.Weak;
import java.io.IOException;
import java.io.InvalidObjectException;
@@ -29,9 +30,7 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.Comparator;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -39,31 +38,18 @@ import java.util.Map.Entry;
import javax.annotation.Nullable;
/**
- * An immutable {@link SetMultimap} with reliable user-specified key and value
- * iteration order. Does not permit null keys or values.
- *
- * <p>Unlike {@link Multimaps#unmodifiableSetMultimap(SetMultimap)}, which is
- * a <i>view</i> of a separate multimap which can still change, an instance of
- * {@code ImmutableSetMultimap} contains its own data and will <i>never</i>
- * change. {@code ImmutableSetMultimap} is convenient for
- * {@code public static final} multimaps ("constant multimaps") and also lets
- * you easily make a "defensive copy" of a multimap provided to your class by
- * a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class
- * are guaranteed to be immutable.
+ * A {@link SetMultimap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Mike Ward
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
-public class ImmutableSetMultimap<K, V>
- extends ImmutableMultimap<K, V>
+public class ImmutableSetMultimap<K, V> extends ImmutableMultimap<K, V>
implements SetMultimap<K, V> {
/** Returns the empty multimap. */
@@ -99,8 +85,7 @@ public class ImmutableSetMultimap<K, V>
* Repeated occurrences of an entry (according to {@link Object#equals}) after
* the first are ignored.
*/
- public static <K, V> ImmutableSetMultimap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3) {
+ public static <K, V> ImmutableSetMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
ImmutableSetMultimap.Builder<K, V> builder = ImmutableSetMultimap.builder();
builder.put(k1, v1);
builder.put(k2, v2);
@@ -149,20 +134,6 @@ public class ImmutableSetMultimap<K, V>
}
/**
- * Multimap for {@link ImmutableSetMultimap.Builder} that maintains key
- * and value orderings and performs better than {@link LinkedHashMultimap}.
- */
- private static class BuilderMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
- BuilderMultimap() {
- super(new LinkedHashMap<K, Collection<V>>());
- }
- @Override Collection<V> createCollection() {
- return Sets.newLinkedHashSet();
- }
- private static final long serialVersionUID = 0;
- }
-
- /**
* A builder for creating immutable {@code SetMultimap} instances, especially
* {@code public static final} multimaps ("constant multimaps"). Example:
* <pre> {@code
@@ -178,23 +149,23 @@ public class ImmutableSetMultimap<K, V>
* times to build multiple multimaps in series. Each multimap contains the
* key-value mappings in the previously created multimaps.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
- public static final class Builder<K, V>
- extends ImmutableMultimap.Builder<K, V> {
+ public static final class Builder<K, V> extends ImmutableMultimap.Builder<K, V> {
/**
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link ImmutableSetMultimap#builder}.
*/
public Builder() {
- builderMultimap = new BuilderMultimap<K, V>();
+ super(MultimapBuilder.linkedHashKeys().linkedHashSetValues().<K, V>build());
}
/**
* Adds a key-value mapping to the built multimap if it is not already
* present.
*/
- @Override public Builder<K, V> put(K key, V value) {
+ @Override
+ public Builder<K, V> put(K key, V value) {
builderMultimap.put(checkNotNull(key), checkNotNull(value));
return this;
}
@@ -204,13 +175,26 @@ public class ImmutableSetMultimap<K, V>
*
* @since 11.0
*/
- @Override public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
- builderMultimap.put(
- checkNotNull(entry.getKey()), checkNotNull(entry.getValue()));
+ @Override
+ public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
+ builderMultimap.put(checkNotNull(entry.getKey()), checkNotNull(entry.getValue()));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 19.0
+ */
+ @Beta
+ @Override
+ public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ super.putAll(entries);
return this;
}
- @Override public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
+ @Override
+ public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
Collection<V> collection = builderMultimap.get(checkNotNull(key));
for (V value : values) {
collection.add(checkNotNull(value));
@@ -218,14 +202,15 @@ public class ImmutableSetMultimap<K, V>
return this;
}
- @Override public Builder<K, V> putAll(K key, V... values) {
+ @Override
+ public Builder<K, V> putAll(K key, V... values) {
return putAll(key, Arrays.asList(values));
}
- @Override public Builder<K, V> putAll(
- Multimap<? extends K, ? extends V> multimap) {
- for (Entry<? extends K, ? extends Collection<? extends V>> entry
- : multimap.asMap().entrySet()) {
+ @Override
+ public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
+ for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+ multimap.asMap().entrySet()) {
putAll(entry.getKey(), entry.getValue());
}
return this;
@@ -263,14 +248,15 @@ public class ImmutableSetMultimap<K, V>
/**
* Returns a newly-created immutable set multimap.
*/
- @Override public ImmutableSetMultimap<K, V> build() {
+ @Override
+ public ImmutableSetMultimap<K, V> build() {
if (keyComparator != null) {
- Multimap<K, V> sortedCopy = new BuilderMultimap<K, V>();
- List<Map.Entry<K, Collection<V>>> entries = Lists.newArrayList(
- builderMultimap.asMap().entrySet());
- Collections.sort(
- entries,
- Ordering.from(keyComparator).<K>onKeys());
+ Multimap<K, V> sortedCopy =
+ MultimapBuilder.linkedHashKeys().linkedHashSetValues().<K, V>build();
+ List<Map.Entry<K, Collection<V>>> entries =
+ Ordering.from(keyComparator)
+ .<K>onKeys()
+ .immutableSortedCopy(builderMultimap.asMap().entrySet());
for (Map.Entry<K, Collection<V>> entry : entries) {
sortedCopy.putAll(entry.getKey(), entry.getValue());
}
@@ -300,8 +286,7 @@ public class ImmutableSetMultimap<K, V>
}
private static <K, V> ImmutableSetMultimap<K, V> copyOf(
- Multimap<? extends K, ? extends V> multimap,
- Comparator<? super V> valueComparator) {
+ Multimap<? extends K, ? extends V> multimap, Comparator<? super V> valueComparator) {
checkNotNull(multimap); // eager for GWT
if (multimap.isEmpty() && valueComparator == null) {
return of();
@@ -309,18 +294,18 @@ public class ImmutableSetMultimap<K, V>
if (multimap instanceof ImmutableSetMultimap) {
@SuppressWarnings("unchecked") // safe since multimap is not writable
- ImmutableSetMultimap<K, V> kvMultimap
- = (ImmutableSetMultimap<K, V>) multimap;
+ ImmutableSetMultimap<K, V> kvMultimap = (ImmutableSetMultimap<K, V>) multimap;
if (!kvMultimap.isPartialView()) {
return kvMultimap;
}
}
- ImmutableMap.Builder<K, ImmutableSet<V>> builder = ImmutableMap.builder();
+ ImmutableMap.Builder<K, ImmutableSet<V>> builder =
+ new ImmutableMap.Builder<K, ImmutableSet<V>>(multimap.asMap().size());
int size = 0;
- for (Entry<? extends K, ? extends Collection<? extends V>> entry
- : multimap.asMap().entrySet()) {
+ for (Entry<? extends K, ? extends Collection<? extends V>> entry :
+ multimap.asMap().entrySet()) {
K key = entry.getKey();
Collection<? extends V> values = entry.getValue();
ImmutableSet<V> set = valueSet(valueComparator, values);
@@ -330,8 +315,23 @@ public class ImmutableSetMultimap<K, V>
}
}
- return new ImmutableSetMultimap<K, V>(
- builder.build(), size, valueComparator);
+ return new ImmutableSetMultimap<K, V>(builder.build(), size, valueComparator);
+ }
+
+ /**
+ * Returns an immutable multimap containing the specified entries. The
+ * returned multimap iterates over keys in the order they were first
+ * encountered in the input, and the values for each key are iterated in the
+ * order they were encountered. If two values for the same key are
+ * {@linkplain Object#equals equal}, the first value encountered is used.
+ *
+ * @throws NullPointerException if any key, value, or entry is null
+ * @since 19.0
+ */
+ @Beta
+ public static <K, V> ImmutableSetMultimap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ return new Builder<K, V>().putAll(entries).build();
}
/**
@@ -340,7 +340,9 @@ public class ImmutableSetMultimap<K, V>
*/
private final transient ImmutableSet<V> emptySet;
- ImmutableSetMultimap(ImmutableMap<K, ImmutableSet<V>> map, int size,
+ ImmutableSetMultimap(
+ ImmutableMap<K, ImmutableSet<V>> map,
+ int size,
@Nullable Comparator<? super V> valueComparator) {
super(map, size);
this.emptySet = emptySet(valueComparator);
@@ -354,7 +356,8 @@ public class ImmutableSetMultimap<K, V>
* The values are in the same order as the parameters used to build this
* multimap.
*/
- @Override public ImmutableSet<V> get(@Nullable K key) {
+ @Override
+ public ImmutableSet<V> get(@Nullable K key) {
// This cast is safe as its type is known in constructor.
ImmutableSet<V> set = (ImmutableSet<V>) map.get(key);
return MoreObjects.firstNonNull(set, emptySet);
@@ -393,7 +396,9 @@ public class ImmutableSetMultimap<K, V>
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public ImmutableSet<V> removeAll(Object key) {
+ @Deprecated
+ @Override
+ public ImmutableSet<V> removeAll(Object key) {
throw new UnsupportedOperationException();
}
@@ -403,8 +408,9 @@ public class ImmutableSetMultimap<K, V>
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public ImmutableSet<V> replaceValues(
- K key, Iterable<? extends V> values) {
+ @Deprecated
+ @Override
+ public ImmutableSet<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
@@ -415,16 +421,17 @@ public class ImmutableSetMultimap<K, V>
* Its iterator traverses the values for the first key, the values for the
* second key, and so on.
*/
- @Override public ImmutableSet<Entry<K, V>> entries() {
+ @Override
+ public ImmutableSet<Entry<K, V>> entries() {
ImmutableSet<Entry<K, V>> result = entries;
- return (result == null)
+ return result == null
? (entries = new EntrySet<K, V>(this))
: result;
}
-
+
private static final class EntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
- private transient final ImmutableSetMultimap<K, V> multimap;
-
+ @Weak private final transient ImmutableSetMultimap<K, V> multimap;
+
EntrySet(ImmutableSetMultimap<K, V> multimap) {
this.multimap = multimap;
}
@@ -451,24 +458,29 @@ public class ImmutableSetMultimap<K, V>
@Override
boolean isPartialView() {
return false;
- }
+ }
}
private static <V> ImmutableSet<V> valueSet(
- @Nullable Comparator<? super V> valueComparator,
- Collection<? extends V> values) {
+ @Nullable Comparator<? super V> valueComparator, Collection<? extends V> values) {
return (valueComparator == null)
? ImmutableSet.copyOf(values)
: ImmutableSortedSet.copyOf(valueComparator, values);
}
- private static <V> ImmutableSet<V> emptySet(
- @Nullable Comparator<? super V> valueComparator) {
+ private static <V> ImmutableSet<V> emptySet(@Nullable Comparator<? super V> valueComparator) {
return (valueComparator == null)
? ImmutableSet.<V>of()
: ImmutableSortedSet.<V>emptySet(valueComparator);
}
+ private static <V> ImmutableSet.Builder<V> valuesBuilder(
+ @Nullable Comparator<? super V> valueComparator) {
+ return (valueComparator == null)
+ ? new ImmutableSet.Builder<V>()
+ : new ImmutableSortedSet.Builder<V>(valueComparator);
+ }
+
/**
* @serialData number of distinct keys, and then for each distinct key: the
* key, the number of values for that key, and the key's values
@@ -480,7 +492,8 @@ public class ImmutableSetMultimap<K, V>
Serialization.writeMultimap(this, stream);
}
- @Nullable Comparator<? super V> valueComparator() {
+ @Nullable
+ Comparator<? super V> valueComparator() {
return emptySet instanceof ImmutableSortedSet
? ((ImmutableSortedSet<V>) emptySet).comparator()
: null;
@@ -489,17 +502,14 @@ public class ImmutableSetMultimap<K, V>
@GwtIncompatible("java.io.ObjectInputStream")
// Serialization type safety is at the caller's mercy.
@SuppressWarnings("unchecked")
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
- Comparator<Object> valueComparator =
- (Comparator<Object>) stream.readObject();
+ Comparator<Object> valueComparator = (Comparator<Object>) stream.readObject();
int keyCount = stream.readInt();
if (keyCount < 0) {
throw new InvalidObjectException("Invalid key count " + keyCount);
}
- ImmutableMap.Builder<Object, ImmutableSet<Object>> builder
- = ImmutableMap.builder();
+ ImmutableMap.Builder<Object, ImmutableSet<Object>> builder = ImmutableMap.builder();
int tmpSize = 0;
for (int i = 0; i < keyCount; i++) {
@@ -509,14 +519,13 @@ public class ImmutableSetMultimap<K, V>
throw new InvalidObjectException("Invalid value count " + valueCount);
}
- Object[] array = new Object[valueCount];
+ ImmutableSet.Builder<Object> valuesBuilder = valuesBuilder(valueComparator);
for (int j = 0; j < valueCount; j++) {
- array[j] = stream.readObject();
+ valuesBuilder.add(stream.readObject());
}
- ImmutableSet<Object> valueSet = valueSet(valueComparator, asList(array));
- if (valueSet.size() != array.length) {
- throw new InvalidObjectException(
- "Duplicate key-value pairs exist for key " + key);
+ ImmutableSet<Object> valueSet = valuesBuilder.build();
+ if (valueSet.size() != valueCount) {
+ throw new InvalidObjectException("Duplicate key-value pairs exist for key " + key);
}
builder.put(key, valueSet);
tmpSize += valueCount;
@@ -526,14 +535,12 @@ public class ImmutableSetMultimap<K, V>
try {
tmpMap = builder.build();
} catch (IllegalArgumentException e) {
- throw (InvalidObjectException)
- new InvalidObjectException(e.getMessage()).initCause(e);
+ throw (InvalidObjectException) new InvalidObjectException(e.getMessage()).initCause(e);
}
FieldSettersHolder.MAP_FIELD_SETTER.set(this, tmpMap);
FieldSettersHolder.SIZE_FIELD_SETTER.set(this, tmpSize);
- FieldSettersHolder.EMPTY_SET_FIELD_SETTER.set(
- this, emptySet(valueComparator));
+ FieldSettersHolder.EMPTY_SET_FIELD_SETTER.set(this, emptySet(valueComparator));
}
@GwtIncompatible("not needed in emulated source.")
diff --git a/guava/src/com/google/common/collect/ImmutableSortedAsList.java b/guava/src/com/google/common/collect/ImmutableSortedAsList.java
index 98aab41..43aa976 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedAsList.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedAsList.java
@@ -31,8 +31,7 @@ import javax.annotation.Nullable;
@SuppressWarnings("serial")
final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
implements SortedIterable<E> {
- ImmutableSortedAsList(
- ImmutableSortedSet<E> backingSet, ImmutableList<E> backingList) {
+ ImmutableSortedAsList(ImmutableSortedSet<E> backingSet, ImmutableList<E> backingList) {
super(backingSet, backingList);
}
@@ -41,7 +40,8 @@ final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
return (ImmutableSortedSet<E>) super.delegateCollection();
}
- @Override public Comparator<? super E> comparator() {
+ @Override
+ public Comparator<? super E> comparator() {
return delegateCollection().comparator();
}
@@ -49,7 +49,8 @@ final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
@GwtIncompatible("ImmutableSortedSet.indexOf")
// TODO(cpovirk): consider manual binary search under GWT to preserve O(log N) lookup
- @Override public int indexOf(@Nullable Object target) {
+ @Override
+ public int indexOf(@Nullable Object target) {
int index = delegateCollection().indexOf(target);
// TODO(kevinb): reconsider if it's really worth making feeble attempts at
@@ -61,7 +62,8 @@ final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
}
@GwtIncompatible("ImmutableSortedSet.indexOf")
- @Override public int lastIndexOf(@Nullable Object target) {
+ @Override
+ public int lastIndexOf(@Nullable Object target) {
return indexOf(target);
}
@@ -79,8 +81,7 @@ final class ImmutableSortedAsList<E> extends RegularImmutableAsList<E>
*/
@Override
ImmutableList<E> subListUnchecked(int fromIndex, int toIndex) {
- return new RegularImmutableSortedSet<E>(
- super.subListUnchecked(fromIndex, toIndex), comparator())
- .asList();
+ ImmutableList<E> parentSubList = super.subListUnchecked(fromIndex, toIndex);
+ return new RegularImmutableSortedSet<E>(parentSubList, comparator()).asList();
}
}
diff --git a/guava/src/com/google/common/collect/ImmutableSortedMap.java b/guava/src/com/google/common/collect/ImmutableSortedMap.java
index e796a5d..ed07437 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedMap.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedMap.java
@@ -18,12 +18,15 @@ package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
import static com.google.common.collect.Maps.keyOrNull;
+import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.NavigableMap;
@@ -33,31 +36,27 @@ import java.util.TreeMap;
import javax.annotation.Nullable;
/**
- * An immutable {@link SortedMap}. Does not permit null keys or values.
+ * A {@link NavigableMap} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
- * <p>Unlike {@link Collections#unmodifiableSortedMap}, which is a <i>view</i>
- * of a separate map which can still change, an instance of {@code
- * ImmutableSortedMap} contains its own data and will <i>never</i> change.
- * {@code ImmutableSortedMap} is convenient for {@code public static final} maps
- * ("constant maps") and also lets you easily make a "defensive copy" of a map
- * provided to your class by a caller.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class are
- * guaranteed to be immutable.
+ * <p><b>Warning:</b> as with any sorted collection, you are strongly advised not to use a {@link
+ * Comparator} or {@link Comparable} type whose comparison behavior is <i>inconsistent with
+ * equals</i>. That is, {@code a.compareTo(b)} or {@code comparator.compare(a, b)} should equal zero
+ * <i>if and only if</i> {@code a.equals(b)}. If this advice is not followed, the resulting map will
+ * not correctly obey its specification.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Jared Levy
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library; implements {@code
- * NavigableMap} since 12.0)
+ * @since 2.0 (implements {@code NavigableMap} since 12.0)
*/
@GwtCompatible(serializable = true, emulated = true)
-public abstract class ImmutableSortedMap<K, V>
- extends ImmutableSortedMapFauxverideShim<K, V> implements NavigableMap<K, V> {
+public final class ImmutableSortedMap<K, V> extends ImmutableSortedMapFauxverideShim<K, V>
+ implements NavigableMap<K, V> {
+
/*
* TODO(kevinb): Confirm that ImmutableSortedMap is faster to construct and
* uses less memory than TreeMap; then say so in the class Javadoc.
@@ -65,45 +64,15 @@ public abstract class ImmutableSortedMap<K, V>
private static final Comparator<Comparable> NATURAL_ORDER = Ordering.natural();
private static final ImmutableSortedMap<Comparable, Object> NATURAL_EMPTY_MAP =
- new EmptyImmutableSortedMap<Comparable, Object>(NATURAL_ORDER);
+ new ImmutableSortedMap<Comparable, Object>(
+ ImmutableSortedSet.emptySet(Ordering.natural()), ImmutableList.<Object>of());
static <K, V> ImmutableSortedMap<K, V> emptyMap(Comparator<? super K> comparator) {
if (Ordering.natural().equals(comparator)) {
return of();
} else {
- return new EmptyImmutableSortedMap<K, V>(comparator);
- }
- }
-
- static <K, V> ImmutableSortedMap<K, V> fromSortedEntries(
- Comparator<? super K> comparator,
- int size,
- Entry<K, V>[] entries) {
- if (size == 0) {
- return emptyMap(comparator);
- }
-
- ImmutableList.Builder<K> keyBuilder = ImmutableList.builder();
- ImmutableList.Builder<V> valueBuilder = ImmutableList.builder();
- for (int i = 0; i < size; i++) {
- Entry<K, V> entry = entries[i];
- keyBuilder.add(entry.getKey());
- valueBuilder.add(entry.getValue());
- }
-
- return new RegularImmutableSortedMap<K, V>(
- new RegularImmutableSortedSet<K>(keyBuilder.build(), comparator),
- valueBuilder.build());
- }
-
- static <K, V> ImmutableSortedMap<K, V> from(
- ImmutableSortedSet<K> keySet, ImmutableList<V> valueList) {
- if (keySet.isEmpty()) {
- return emptyMap(keySet.comparator());
- } else {
- return new RegularImmutableSortedMap<K, V>(
- (RegularImmutableSortedSet<K>) keySet,
- valueList);
+ return new ImmutableSortedMap<K, V>(
+ ImmutableSortedSet.emptySet(comparator), ImmutableList.<V>of());
}
}
@@ -120,9 +89,22 @@ public abstract class ImmutableSortedMap<K, V>
/**
* Returns an immutable map containing a single entry.
*/
- public static <K extends Comparable<? super K>, V>
- ImmutableSortedMap<K, V> of(K k1, V v1) {
- return from(ImmutableSortedSet.of(k1), ImmutableList.of(v1));
+ public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(K k1, V v1) {
+ return of(Ordering.natural(), k1, v1);
+ }
+
+ /**
+ * Returns an immutable map containing a single entry.
+ */
+ private static <K, V> ImmutableSortedMap<K, V> of(Comparator<? super K> comparator, K k1, V v1) {
+ return new ImmutableSortedMap<K, V>(
+ new RegularImmutableSortedSet<K>(ImmutableList.of(k1), checkNotNull(comparator)),
+ ImmutableList.of(v1));
+ }
+
+ private static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> ofEntries(
+ ImmutableMapEntry<K, V>... entries) {
+ return fromEntries(Ordering.natural(), false, entries, entries.length);
}
/**
@@ -133,9 +115,9 @@ public abstract class ImmutableSortedMap<K, V>
* their natural ordering
*/
@SuppressWarnings("unchecked")
- public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
- of(K k1, V v1, K k2, V v2) {
- return fromEntries(Ordering.natural(), false, 2, entryOf(k1, v1), entryOf(k2, v2));
+ public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(
+ K k1, V v1, K k2, V v2) {
+ return ofEntries(entryOf(k1, v1), entryOf(k2, v2));
}
/**
@@ -146,10 +128,9 @@ public abstract class ImmutableSortedMap<K, V>
* their natural ordering
*/
@SuppressWarnings("unchecked")
- public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
- of(K k1, V v1, K k2, V v2, K k3, V v3) {
- return fromEntries(Ordering.natural(), false, 3, entryOf(k1, v1), entryOf(k2, v2),
- entryOf(k3, v3));
+ public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(
+ K k1, V v1, K k2, V v2, K k3, V v3) {
+ return ofEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
}
/**
@@ -160,10 +141,9 @@ public abstract class ImmutableSortedMap<K, V>
* their natural ordering
*/
@SuppressWarnings("unchecked")
- public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
- of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
- return fromEntries(Ordering.natural(), false, 4, entryOf(k1, v1), entryOf(k2, v2),
- entryOf(k3, v3), entryOf(k4, v4));
+ public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(
+ K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+ return ofEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4));
}
/**
@@ -174,10 +154,10 @@ public abstract class ImmutableSortedMap<K, V>
* their natural ordering
*/
@SuppressWarnings("unchecked")
- public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
- of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
- return fromEntries(Ordering.natural(), false, 5, entryOf(k1, v1), entryOf(k2, v2),
- entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
+ public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(
+ K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
+ return ofEntries(
+ entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
}
/**
@@ -197,12 +177,11 @@ public abstract class ImmutableSortedMap<K, V>
* @throws IllegalArgumentException if any two keys are equal according to
* their natural ordering
*/
- public static <K, V> ImmutableSortedMap<K, V> copyOf(
- Map<? extends K, ? extends V> map) {
+ public static <K, V> ImmutableSortedMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
// Hack around K not being a subtype of Comparable.
// Unsafe, see ImmutableSortedSetFauxverideShim.
@SuppressWarnings("unchecked")
- Ordering<K> naturalOrder = (Ordering<K>) Ordering.<Comparable>natural();
+ Ordering<K> naturalOrder = (Ordering<K>) NATURAL_ORDER;
return copyOfInternal(map, naturalOrder);
}
@@ -224,6 +203,44 @@ public abstract class ImmutableSortedMap<K, V>
}
/**
+ * Returns an immutable map containing the given entries, with keys sorted
+ * by the provided comparator.
+ *
+ * <p>This method is not type-safe, as it may be called on a map with keys
+ * that are not mutually comparable.
+ *
+ * @throws NullPointerException if any key or value in {@code map} is null
+ * @throws IllegalArgumentException if any two keys are equal according to the
+ * comparator
+ * @since 19.0
+ */
+ @Beta
+ public static <K, V> ImmutableSortedMap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ // Hack around K not being a subtype of Comparable.
+ // Unsafe, see ImmutableSortedSetFauxverideShim.
+ @SuppressWarnings("unchecked")
+ Ordering<K> naturalOrder = (Ordering<K>) NATURAL_ORDER;
+ return copyOf(entries, naturalOrder);
+ }
+
+ /**
+ * Returns an immutable map containing the given entries, with keys sorted
+ * by the provided comparator.
+ *
+ * @throws NullPointerException if any key or value in {@code map} is null
+ * @throws IllegalArgumentException if any two keys are equal according to the
+ * comparator
+ * @since 19.0
+ */
+ @Beta
+ public static <K, V> ImmutableSortedMap<K, V> copyOf(
+ Iterable<? extends Entry<? extends K, ? extends V>> entries,
+ Comparator<? super K> comparator) {
+ return fromEntries(checkNotNull(comparator), false, entries);
+ }
+
+ /**
* Returns an immutable map containing the same entries as the provided sorted
* map, with the same ordering.
*
@@ -234,15 +251,23 @@ public abstract class ImmutableSortedMap<K, V>
* @throws NullPointerException if any key or value in {@code map} is null
*/
@SuppressWarnings("unchecked")
- public static <K, V> ImmutableSortedMap<K, V> copyOfSorted(
- SortedMap<K, ? extends V> map) {
+ public static <K, V> ImmutableSortedMap<K, V> copyOfSorted(SortedMap<K, ? extends V> map) {
Comparator<? super K> comparator = map.comparator();
if (comparator == null) {
// If map has a null comparator, the keys should have a natural ordering,
// even though K doesn't explicitly implement Comparable.
comparator = (Comparator<? super K>) NATURAL_ORDER;
}
- return copyOfInternal(map, comparator);
+ if (map instanceof ImmutableSortedMap) {
+ // TODO(kevinb): Prove that this cast is safe, even though
+ // Collections.unmodifiableSortedMap requires the same key type.
+ @SuppressWarnings("unchecked")
+ ImmutableSortedMap<K, V> kvMap = (ImmutableSortedMap<K, V>) map;
+ if (!kvMap.isPartialView()) {
+ return kvMap;
+ }
+ }
+ return fromEntries(comparator, true, map.entrySet());
}
private static <K, V> ImmutableSortedMap<K, V> copyOfInternal(
@@ -251,9 +276,10 @@ public abstract class ImmutableSortedMap<K, V>
if (map instanceof SortedMap) {
SortedMap<?, ?> sortedMap = (SortedMap<?, ?>) map;
Comparator<?> comparator2 = sortedMap.comparator();
- sameComparator = (comparator2 == null)
- ? comparator == NATURAL_ORDER
- : comparator.equals(comparator2);
+ sameComparator =
+ (comparator2 == null)
+ ? comparator == NATURAL_ORDER
+ : comparator.equals(comparator2);
}
if (sameComparator && (map instanceof ImmutableSortedMap)) {
@@ -265,40 +291,68 @@ public abstract class ImmutableSortedMap<K, V>
return kvMap;
}
}
+ return fromEntries(comparator, sameComparator, map.entrySet());
+ }
+ /**
+ * Accepts a collection of possibly-null entries. If {@code sameComparator}, then it is assumed
+ * that they do not need to be sorted or checked for dupes.
+ */
+ private static <K, V> ImmutableSortedMap<K, V> fromEntries(
+ Comparator<? super K> comparator,
+ boolean sameComparator,
+ Iterable<? extends Entry<? extends K, ? extends V>> entries) {
// "adding" type params to an array of a raw type should be safe as
// long as no one can ever cast that same array instance back to a
// raw type.
@SuppressWarnings("unchecked")
- Entry<K, V>[] entries = map.entrySet().toArray(new Entry[0]);
-
- return fromEntries(comparator, sameComparator, entries.length, entries);
- }
-
- static <K, V> ImmutableSortedMap<K, V> fromEntries(
- Comparator<? super K> comparator, boolean sameComparator, int size, Entry<K, V>... entries) {
- for (int i = 0; i < size; i++) {
- Entry<K, V> entry = entries[i];
- entries[i] = entryOf(entry.getKey(), entry.getValue());
- }
- if (!sameComparator) {
- sortEntries(comparator, size, entries);
- validateEntries(size, entries, comparator);
- }
-
- return fromSortedEntries(comparator, size, entries);
+ Entry<K, V>[] entryArray = (Entry[]) Iterables.toArray(entries, EMPTY_ENTRY_ARRAY);
+ return fromEntries(comparator, sameComparator, entryArray, entryArray.length);
}
- private static <K, V> void sortEntries(
- final Comparator<? super K> comparator, int size, Entry<K, V>[] entries) {
- Arrays.sort(entries, 0, size, Ordering.from(comparator).<K>onKeys());
- }
-
- private static <K, V> void validateEntries(int size, Entry<K, V>[] entries,
- Comparator<? super K> comparator) {
- for (int i = 1; i < size; i++) {
- checkNoConflict(comparator.compare(entries[i - 1].getKey(), entries[i].getKey()) != 0, "key",
- entries[i - 1], entries[i]);
+ private static <K, V> ImmutableSortedMap<K, V> fromEntries(
+ Comparator<? super K> comparator,
+ boolean sameComparator,
+ Entry<K, V>[] entryArray,
+ int size) {
+ switch (size) {
+ case 0:
+ return emptyMap(comparator);
+ case 1:
+ return ImmutableSortedMap.<K, V>of(
+ comparator, entryArray[0].getKey(), entryArray[0].getValue());
+ default:
+ Object[] keys = new Object[size];
+ Object[] values = new Object[size];
+ if (sameComparator) {
+ // Need to check for nulls, but don't need to sort or validate.
+ for (int i = 0; i < size; i++) {
+ Object key = entryArray[i].getKey();
+ Object value = entryArray[i].getValue();
+ checkEntryNotNull(key, value);
+ keys[i] = key;
+ values[i] = value;
+ }
+ } else {
+ // Need to sort and check for nulls and dupes.
+ Arrays.sort(entryArray, 0, size, Ordering.from(comparator).<K>onKeys());
+ K prevKey = entryArray[0].getKey();
+ keys[0] = prevKey;
+ values[0] = entryArray[0].getValue();
+ for (int i = 1; i < size; i++) {
+ K key = entryArray[i].getKey();
+ V value = entryArray[i].getValue();
+ checkEntryNotNull(key, value);
+ keys[i] = key;
+ values[i] = value;
+ checkNoConflict(
+ comparator.compare(prevKey, key) != 0, "key", entryArray[i - 1], entryArray[i]);
+ prevKey = key;
+ }
+ }
+ return new ImmutableSortedMap<K, V>(
+ new RegularImmutableSortedSet<K>(new RegularImmutableList<K>(keys), comparator),
+ new RegularImmutableList<V>(values));
}
}
@@ -349,7 +403,7 @@ public abstract class ImmutableSortedMap<K, V>
* multiple times to build multiple maps in series. Each map is a superset of
* the maps created before it.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public static class Builder<K, V> extends ImmutableMap.Builder<K, V> {
private final Comparator<? super K> comparator;
@@ -368,7 +422,8 @@ public abstract class ImmutableSortedMap<K, V>
* keys, according to the comparator (which might be the keys' natural
* order), are not allowed, and will cause {@link #build} to fail.
*/
- @Override public Builder<K, V> put(K key, V value) {
+ @Override
+ public Builder<K, V> put(K key, V value) {
super.put(key, value);
return this;
}
@@ -381,7 +436,8 @@ public abstract class ImmutableSortedMap<K, V>
*
* @since 11.0
*/
- @Override public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
+ @Override
+ public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
super.put(entry);
return this;
}
@@ -393,60 +449,149 @@ public abstract class ImmutableSortedMap<K, V>
*
* @throws NullPointerException if any key or value in {@code map} is null
*/
- @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
+ @Override
+ public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
super.putAll(map);
return this;
}
/**
+ * Adds all the given entries to the built map. Duplicate keys, according
+ * to the comparator (which might be the keys' natural order), are not
+ * allowed, and will cause {@link #build} to fail.
+ *
+ * @throws NullPointerException if any key, value, or entry is null
+ * @since 19.0
+ */
+ @Beta
+ @Override
+ public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
+ super.putAll(entries);
+ return this;
+ }
+
+ /**
+ * Throws an {@code UnsupportedOperationException}.
+ *
+ * @since 19.0
+ * @deprecated Unsupported by ImmutableSortedMap.Builder.
+ */
+ @Beta
+ @Override
+ @Deprecated
+ public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
+ throw new UnsupportedOperationException("Not available on ImmutableSortedMap.Builder");
+ }
+
+ /**
* Returns a newly-created immutable sorted map.
*
* @throws IllegalArgumentException if any two keys are equal according to
* the comparator (which might be the keys' natural order)
*/
- @Override public ImmutableSortedMap<K, V> build() {
- return fromEntries(comparator, false, size, entries);
+ @Override
+ public ImmutableSortedMap<K, V> build() {
+ switch (size) {
+ case 0:
+ return emptyMap(comparator);
+ case 1:
+ return of(comparator, entries[0].getKey(), entries[0].getValue());
+ default:
+ return fromEntries(comparator, false, entries, size);
+ }
}
}
- ImmutableSortedMap() {
+ private final transient RegularImmutableSortedSet<K> keySet;
+ private final transient ImmutableList<V> valueList;
+ private transient ImmutableSortedMap<K, V> descendingMap;
+
+ ImmutableSortedMap(RegularImmutableSortedSet<K> keySet, ImmutableList<V> valueList) {
+ this(keySet, valueList, null);
}
- ImmutableSortedMap(ImmutableSortedMap<K, V> descendingMap) {
+ ImmutableSortedMap(
+ RegularImmutableSortedSet<K> keySet,
+ ImmutableList<V> valueList,
+ ImmutableSortedMap<K, V> descendingMap) {
+ this.keySet = keySet;
+ this.valueList = valueList;
this.descendingMap = descendingMap;
}
@Override
public int size() {
- return values().size();
+ return valueList.size();
}
- @Override public boolean containsValue(@Nullable Object value) {
- return values().contains(value);
+ @Override
+ public V get(@Nullable Object key) {
+ int index = keySet.indexOf(key);
+ return (index == -1) ? null : valueList.get(index);
}
- @Override boolean isPartialView() {
- return keySet().isPartialView() || values().isPartialView();
+ @Override
+ boolean isPartialView() {
+ return keySet.isPartialView() || valueList.isPartialView();
}
/**
* Returns an immutable set of the mappings in this map, sorted by the key
* ordering.
*/
- @Override public ImmutableSet<Entry<K, V>> entrySet() {
+ @Override
+ public ImmutableSet<Entry<K, V>> entrySet() {
return super.entrySet();
}
+ @Override
+ ImmutableSet<Entry<K, V>> createEntrySet() {
+ @WeakOuter
+ class EntrySet extends ImmutableMapEntrySet<K, V> {
+ @Override
+ public UnmodifiableIterator<Entry<K, V>> iterator() {
+ return asList().iterator();
+ }
+
+ @Override
+ ImmutableList<Entry<K, V>> createAsList() {
+ return new ImmutableAsList<Entry<K, V>>() {
+ @Override
+ public Entry<K, V> get(int index) {
+ return Maps.immutableEntry(keySet.asList().get(index), valueList.get(index));
+ }
+
+ @Override
+ ImmutableCollection<Entry<K, V>> delegateCollection() {
+ return EntrySet.this;
+ }
+ };
+ }
+
+ @Override
+ ImmutableMap<K, V> map() {
+ return ImmutableSortedMap.this;
+ }
+ }
+ return isEmpty() ? ImmutableSet.<Entry<K, V>>of() : new EntrySet();
+ }
+
/**
* Returns an immutable sorted set of the keys in this map.
*/
- @Override public abstract ImmutableSortedSet<K> keySet();
+ @Override
+ public ImmutableSortedSet<K> keySet() {
+ return keySet;
+ }
/**
* Returns an immutable collection of the values in this map, sorted by the
* ordering of the corresponding keys.
*/
- @Override public abstract ImmutableCollection<V> values();
+ @Override
+ public ImmutableCollection<V> values() {
+ return valueList;
+ }
/**
* Returns the comparator that orders the keys, which is
@@ -469,6 +614,17 @@ public abstract class ImmutableSortedMap<K, V>
return keySet().last();
}
+ private ImmutableSortedMap<K, V> getSubMap(int fromIndex, int toIndex) {
+ if (fromIndex == 0 && toIndex == size()) {
+ return this;
+ } else if (fromIndex == toIndex) {
+ return emptyMap(comparator());
+ } else {
+ return new ImmutableSortedMap<K, V>(
+ keySet.getSubSet(fromIndex, toIndex), valueList.subList(fromIndex, toIndex));
+ }
+ }
+
/**
* This method returns a {@code ImmutableSortedMap}, consisting of the entries
* whose keys are less than {@code toKey}.
@@ -497,7 +653,9 @@ public abstract class ImmutableSortedMap<K, V>
* @since 12.0
*/
@Override
- public abstract ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive);
+ public ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive) {
+ return getSubMap(0, keySet.headIndex(checkNotNull(toKey), inclusive));
+ }
/**
* This method returns a {@code ImmutableSortedMap}, consisting of the entries
@@ -533,12 +691,15 @@ public abstract class ImmutableSortedMap<K, V>
* @since 12.0
*/
@Override
- public ImmutableSortedMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey,
- boolean toInclusive) {
+ public ImmutableSortedMap<K, V> subMap(
+ K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
checkNotNull(fromKey);
checkNotNull(toKey);
- checkArgument(comparator().compare(fromKey, toKey) <= 0,
- "expected fromKey <= toKey but %s > %s", fromKey, toKey);
+ checkArgument(
+ comparator().compare(fromKey, toKey) <= 0,
+ "expected fromKey <= toKey but %s > %s",
+ fromKey,
+ toKey);
return headMap(toKey, toInclusive).tailMap(fromKey, fromInclusive);
}
@@ -571,7 +732,9 @@ public abstract class ImmutableSortedMap<K, V>
* @since 12.0
*/
@Override
- public abstract ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive);
+ public ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive) {
+ return getSubMap(keySet.tailIndex(checkNotNull(fromKey), inclusive), size());
+ }
@Override
public Entry<K, V> lowerEntry(K key) {
@@ -647,27 +810,31 @@ public abstract class ImmutableSortedMap<K, V>
throw new UnsupportedOperationException();
}
- private transient ImmutableSortedMap<K, V> descendingMap;
-
@Override
public ImmutableSortedMap<K, V> descendingMap() {
+ // TODO(kevinb): the descendingMap is never actually cached at all. Either it should be or the
+ // code below simplified.
ImmutableSortedMap<K, V> result = descendingMap;
if (result == null) {
- result = descendingMap = createDescendingMap();
+ if (isEmpty()) {
+ return result = emptyMap(Ordering.from(comparator()).reverse());
+ } else {
+ return result =
+ new ImmutableSortedMap<K, V>(
+ (RegularImmutableSortedSet<K>) keySet.descendingSet(), valueList.reverse(), this);
+ }
}
return result;
}
- abstract ImmutableSortedMap<K, V> createDescendingMap();
-
@Override
public ImmutableSortedSet<K> navigableKeySet() {
- return keySet();
+ return keySet;
}
@Override
public ImmutableSortedSet<K> descendingKeySet() {
- return keySet().descendingSet();
+ return keySet.descendingSet();
}
/**
@@ -678,19 +845,24 @@ public abstract class ImmutableSortedMap<K, V>
*/
private static class SerializedForm extends ImmutableMap.SerializedForm {
private final Comparator<Object> comparator;
+
@SuppressWarnings("unchecked")
SerializedForm(ImmutableSortedMap<?, ?> sortedMap) {
super(sortedMap);
comparator = (Comparator<Object>) sortedMap.comparator();
}
- @Override Object readResolve() {
+
+ @Override
+ Object readResolve() {
Builder<Object, Object> builder = new Builder<Object, Object>(comparator);
return createMap(builder);
}
+
private static final long serialVersionUID = 0;
}
- @Override Object writeReplace() {
+ @Override
+ Object writeReplace() {
return new SerializedForm(this);
}
diff --git a/guava/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java b/guava/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java
index 7c38d00..13ce60d 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java
@@ -23,8 +23,7 @@ package com.google.common.collect;
*
* @author Chris Povirk
*/
-abstract class ImmutableSortedMapFauxverideShim<K, V>
- extends ImmutableMap<K, V> {
+abstract class ImmutableSortedMapFauxverideShim<K, V> extends ImmutableMap<K, V> {
/**
* Not supported. Use {@link ImmutableSortedMap#naturalOrder}, which offers
* better type-safety, instead. This method exists only to hide
@@ -34,7 +33,8 @@ abstract class ImmutableSortedMapFauxverideShim<K, V>
* @deprecated Use {@link ImmutableSortedMap#naturalOrder}, which offers
* better type-safety.
*/
- @Deprecated public static <K, V> ImmutableSortedMap.Builder<K, V> builder() {
+ @Deprecated
+ public static <K, V> ImmutableSortedMap.Builder<K, V> builder() {
throw new UnsupportedOperationException();
}
@@ -47,7 +47,8 @@ abstract class ImmutableSortedMapFauxverideShim<K, V>
* @deprecated <b>Pass a key of type {@code Comparable} to use {@link
* ImmutableSortedMap#of(Comparable, Object)}.</b>
*/
- @Deprecated public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1) {
+ @Deprecated
+ public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1) {
throw new UnsupportedOperationException();
}
@@ -60,8 +61,8 @@ abstract class ImmutableSortedMapFauxverideShim<K, V>
* @deprecated <b>Pass keys of type {@code Comparable} to use {@link
* ImmutableSortedMap#of(Comparable, Object, Comparable, Object)}.</b>
*/
- @Deprecated public static <K, V> ImmutableSortedMap<K, V> of(
- K k1, V v1, K k2, V v2) {
+ @Deprecated
+ public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2) {
throw new UnsupportedOperationException();
}
@@ -75,8 +76,8 @@ abstract class ImmutableSortedMapFauxverideShim<K, V>
* ImmutableSortedMap#of(Comparable, Object, Comparable, Object,
* Comparable, Object)}.</b>
*/
- @Deprecated public static <K, V> ImmutableSortedMap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3) {
+ @Deprecated
+ public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
throw new UnsupportedOperationException();
}
@@ -90,8 +91,8 @@ abstract class ImmutableSortedMapFauxverideShim<K, V>
* ImmutableSortedMap#of(Comparable, Object, Comparable, Object,
* Comparable, Object, Comparable, Object)}.</b>
*/
- @Deprecated public static <K, V> ImmutableSortedMap<K, V> of(
- K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+ @Deprecated
+ public static <K, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
throw new UnsupportedOperationException();
}
@@ -105,7 +106,8 @@ abstract class ImmutableSortedMapFauxverideShim<K, V>
* ImmutableSortedMap#of(Comparable, Object, Comparable, Object,
* Comparable, Object, Comparable, Object, Comparable, Object)}.</b>
*/
- @Deprecated public static <K, V> ImmutableSortedMap<K, V> of(
+ @Deprecated
+ public static <K, V> ImmutableSortedMap<K, V> of(
K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
throw new UnsupportedOperationException();
}
diff --git a/guava/src/com/google/common/collect/ImmutableSortedMultiset.java b/guava/src/com/google/common/collect/ImmutableSortedMultiset.java
index 24970fa..6d6bb5f 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedMultiset.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedMultiset.java
@@ -29,49 +29,17 @@ import java.util.Iterator;
import java.util.List;
/**
- * An immutable {@code SortedMultiset} that stores its elements in a sorted array. Some instances
- * are ordered by an explicit comparator, while others follow the natural sort ordering of their
- * elements. Either way, null elements are not supported.
+ * A {@link SortedMultiset} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
- * <p>Unlike {@link Multisets#unmodifiableSortedMultiset}, which is a <i>view</i> of a separate
- * collection that can still change, an instance of {@code ImmutableSortedMultiset} contains its
- * own private data and will <i>never</i> change. This class is convenient for {@code public static
- * final} multisets ("constant multisets") and also lets you easily make a "defensive copy" of a
- * set provided to your class by a caller.
- *
- * <p>The multisets returned by the {@link #headMultiset}, {@link #tailMultiset}, and
- * {@link #subMultiset} methods share the same array as the original multiset, preventing that
- * array from being garbage collected. If this is a concern, the data may be copied into a
- * correctly-sized array by calling {@link #copyOfSorted}.
- *
- * <p><b>Note on element equivalence:</b> The {@link #contains(Object)},
- * {@link #containsAll(Collection)}, and {@link #equals(Object)} implementations must check whether
- * a provided object is equivalent to an element in the collection. Unlike most collections, an
- * {@code ImmutableSortedMultiset} doesn't use {@link Object#equals} to determine if two elements
- * are equivalent. Instead, with an explicit comparator, the following relation determines whether
- * elements {@code x} and {@code y} are equivalent:
- *
- * <pre> {@code
- *
- * {(x, y) | comparator.compare(x, y) == 0}}</pre>
- *
- * <p>With natural ordering of elements, the following relation determines whether two elements are
- * equivalent:
- *
- * <pre> {@code
- *
- * {(x, y) | x.compareTo(y) == 0}}</pre>
- *
- * <b>Warning:</b> Like most multisets, an {@code ImmutableSortedMultiset} will not function
- * correctly if an element is modified after being placed in the multiset. For this reason, and to
- * avoid general confusion, it is strongly recommended to place only immutable objects into this
- * collection.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as it has no public or
- * protected constructors. Thus, instances of this type are guaranteed to be immutable.
+ * <p><b>Warning:</b> as with any sorted collection, you are strongly advised not to use a {@link
+ * Comparator} or {@link Comparable} type whose comparison behavior is <i>inconsistent with
+ * equals</i>. That is, {@code a.compareTo(b)} or {@code comparator.compare(a, b)} should equal zero
+ * <i>if and only if</i> {@code a.equals(b)}. If this advice is not followed, the resulting
+ * collection will not correctly obey its specification.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Louis Wasserman
@@ -81,12 +49,12 @@ import java.util.List;
@GwtIncompatible("hasn't been tested yet")
public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultisetFauxverideShim<E>
implements SortedMultiset<E> {
- // TODO(user): GWT compatibility
+ // TODO(lowasser): GWT compatibility
private static final Comparator<Comparable> NATURAL_ORDER = Ordering.natural();
private static final ImmutableSortedMultiset<Comparable> NATURAL_EMPTY_MULTISET =
- new EmptyImmutableSortedMultiset<Comparable>(NATURAL_ORDER);
+ new RegularImmutableSortedMultiset<Comparable>(NATURAL_ORDER);
/**
* Returns the empty immutable sorted multiset.
@@ -102,9 +70,8 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(E element) {
RegularImmutableSortedSet<E> elementSet =
(RegularImmutableSortedSet<E>) ImmutableSortedSet.of(element);
- int[] counts = {1};
long[] cumulativeCounts = {0, 1};
- return new RegularImmutableSortedMultiset<E>(elementSet, counts, cumulativeCounts, 0, 1);
+ return new RegularImmutableSortedMultiset<E>(elementSet, cumulativeCounts, 0, 1);
}
/**
@@ -283,8 +250,8 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
* @throws NullPointerException if {@code sortedMultiset} or any of its elements is null
*/
public static <E> ImmutableSortedMultiset<E> copyOfSorted(SortedMultiset<E> sortedMultiset) {
- return copyOfSortedEntries(sortedMultiset.comparator(),
- Lists.newArrayList(sortedMultiset.entrySet()));
+ return copyOfSortedEntries(
+ sortedMultiset.comparator(), Lists.newArrayList(sortedMultiset.entrySet()));
}
private static <E> ImmutableSortedMultiset<E> copyOfSortedEntries(
@@ -293,26 +260,27 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
return emptyMultiset(comparator);
}
ImmutableList.Builder<E> elementsBuilder = new ImmutableList.Builder<E>(entries.size());
- int[] counts = new int[entries.size()];
long[] cumulativeCounts = new long[entries.size() + 1];
int i = 0;
for (Entry<E> entry : entries) {
elementsBuilder.add(entry.getElement());
- counts[i] = entry.getCount();
- cumulativeCounts[i + 1] = cumulativeCounts[i] + counts[i];
+ cumulativeCounts[i + 1] = cumulativeCounts[i] + entry.getCount();
i++;
}
return new RegularImmutableSortedMultiset<E>(
new RegularImmutableSortedSet<E>(elementsBuilder.build(), comparator),
- counts, cumulativeCounts, 0, entries.size());
+ cumulativeCounts,
+ 0,
+ entries.size());
}
@SuppressWarnings("unchecked")
static <E> ImmutableSortedMultiset<E> emptyMultiset(Comparator<? super E> comparator) {
if (NATURAL_ORDER.equals(comparator)) {
- return (ImmutableSortedMultiset) NATURAL_EMPTY_MULTISET;
+ return (ImmutableSortedMultiset<E>) NATURAL_EMPTY_MULTISET;
+ } else {
+ return new RegularImmutableSortedMultiset<E>(comparator);
}
- return new EmptyImmutableSortedMultiset<E>(comparator);
}
ImmutableSortedMultiset() {}
@@ -331,7 +299,10 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
public ImmutableSortedMultiset<E> descendingMultiset() {
ImmutableSortedMultiset<E> result = descendingMultiset;
if (result == null) {
- return descendingMultiset = new DescendingImmutableSortedMultiset<E>(this);
+ return descendingMultiset =
+ this.isEmpty()
+ ? emptyMultiset(Ordering.from(comparator()).reverse())
+ : new DescendingImmutableSortedMultiset<E>(this);
}
return result;
}
@@ -370,8 +341,11 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
@Override
public ImmutableSortedMultiset<E> subMultiset(
E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) {
- checkArgument(comparator().compare(lowerBound, upperBound) <= 0,
- "Expected lowerBound <= upperBound but %s > %s", lowerBound, upperBound);
+ checkArgument(
+ comparator().compare(lowerBound, upperBound) <= 0,
+ "Expected lowerBound <= upperBound but %s > %s",
+ lowerBound,
+ upperBound);
return tailMultiset(lowerBound, lowerBoundType).headMultiset(upperBound, upperBoundType);
}
@@ -394,11 +368,11 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
* Returns a builder that creates immutable sorted multisets whose elements are ordered by the
* reverse of their natural ordering.
*
- * <p>Note: the type parameter {@code E} extends {@code Comparable<E>} rather than {@code
+ * <p>Note: the type parameter {@code E} extends {@code Comparable<?>} rather than {@code
* Comparable<? super E>} as a workaround for javac <a
* href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6468354">bug 6468354</a>.
*/
- public static <E extends Comparable<E>> Builder<E> reverseOrder() {
+ public static <E extends Comparable<?>> Builder<E> reverseOrder() {
return new Builder<E>(Ordering.natural().reverse());
}
@@ -408,11 +382,11 @@ public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultiset
* method provides more type-safety than {@link #builder}, as it can be called only for classes
* that implement {@link Comparable}.
*
- * <p>Note: the type parameter {@code E} extends {@code Comparable<E>} rather than {@code
+ * <p>Note: the type parameter {@code E} extends {@code Comparable<?>} rather than {@code
* Comparable<? super E>} as a workaround for javac <a
* href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6468354">bug 6468354</a>.
*/
- public static <E extends Comparable<E>> Builder<E> naturalOrder() {
+ public static <E extends Comparable<?>> Builder<E> naturalOrder() {
return new Builder<E>(Ordering.natural());
}
diff --git a/guava/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java b/guava/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java
index 60ff701..8f13341 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java
@@ -20,7 +20,7 @@ package com.google.common.collect;
* prevents accidents like the following:
*
* <pre> {@code
- *
+ *
* List<Object> objects = ...;
* // Sort them:
* Set<Object> sorted = ImmutableSortedMultiset.copyOf(objects);
@@ -128,13 +128,7 @@ abstract class ImmutableSortedMultisetFauxverideShim<E> extends ImmutableMultise
*/
@Deprecated
public static <E> ImmutableSortedMultiset<E> of(
- E e1,
- E e2,
- E e3,
- E e4,
- E e5,
- E e6,
- E... remaining) {
+ E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) {
throw new UnsupportedOperationException();
}
diff --git a/guava/src/com/google/common/collect/ImmutableSortedSet.java b/guava/src/com/google/common/collect/ImmutableSortedSet.java
index c134890..4a7a94b 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedSet.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedSet.java
@@ -28,7 +28,6 @@ import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NavigableSet;
@@ -37,56 +36,22 @@ import java.util.SortedSet;
import javax.annotation.Nullable;
/**
- * An immutable {@code SortedSet} that stores its elements in a sorted array.
- * Some instances are ordered by an explicit comparator, while others follow the
- * natural sort ordering of their elements. Either way, null elements are not
- * supported.
+ * A {@link NavigableSet} whose contents will never change, with many other important properties
+ * detailed at {@link ImmutableCollection}.
*
- * <p>Unlike {@link Collections#unmodifiableSortedSet}, which is a <i>view</i>
- * of a separate collection that can still change, an instance of {@code
- * ImmutableSortedSet} contains its own private data and will <i>never</i>
- * change. This class is convenient for {@code public static final} sets
- * ("constant sets") and also lets you easily make a "defensive copy" of a set
- * provided to your class by a caller.
- *
- * <p>The sets returned by the {@link #headSet}, {@link #tailSet}, and
- * {@link #subSet} methods share the same array as the original set, preventing
- * that array from being garbage collected. If this is a concern, the data may
- * be copied into a correctly-sized array by calling {@link #copyOfSorted}.
- *
- * <p><b>Note on element equivalence:</b> The {@link #contains(Object)},
- * {@link #containsAll(Collection)}, and {@link #equals(Object)}
- * implementations must check whether a provided object is equivalent to an
- * element in the collection. Unlike most collections, an
- * {@code ImmutableSortedSet} doesn't use {@link Object#equals} to determine if
- * two elements are equivalent. Instead, with an explicit comparator, the
- * following relation determines whether elements {@code x} and {@code y} are
- * equivalent: <pre> {@code
- *
- * {(x, y) | comparator.compare(x, y) == 0}}</pre>
- *
- * <p>With natural ordering of elements, the following relation determines whether
- * two elements are equivalent: <pre> {@code
- *
- * {(x, y) | x.compareTo(y) == 0}}</pre>
- *
- * <b>Warning:</b> Like most sets, an {@code ImmutableSortedSet} will not
- * function correctly if an element is modified after being placed in the set.
- * For this reason, and to avoid general confusion, it is strongly recommended
- * to place only immutable objects into this collection.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this type are
- * guaranteed to be immutable.
+ * <p><b>Warning:</b> as with any sorted collection, you are strongly advised not to use a {@link
+ * Comparator} or {@link Comparable} type whose comparison behavior is <i>inconsistent with
+ * equals</i>. That is, {@code a.compareTo(b)} or {@code comparator.compare(a, b)} should equal zero
+ * <i>if and only if</i> {@code a.equals(b)}. If this advice is not followed, the resulting
+ * collection will not correctly obey its specification.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
- * @see ImmutableSet
* @author Jared Levy
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library; implements {@code NavigableSet} since 12.0)
+ * @since 2.0 (implements {@code NavigableSet} since 12.0)
*/
// TODO(benyu): benchmark and optimize all creation paths, which are a mess now
@GwtCompatible(serializable = true, emulated = true)
@@ -94,23 +59,16 @@ import javax.annotation.Nullable;
public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxverideShim<E>
implements NavigableSet<E>, SortedIterable<E> {
- private static final Comparator<Comparable> NATURAL_ORDER =
- Ordering.natural();
-
- private static final ImmutableSortedSet<Comparable> NATURAL_EMPTY_SET =
- new EmptyImmutableSortedSet<Comparable>(NATURAL_ORDER);
+ private static final Comparator<Comparable> NATURAL_ORDER = Ordering.natural();
- @SuppressWarnings("unchecked")
- private static <E> ImmutableSortedSet<E> emptySet() {
- return (ImmutableSortedSet<E>) NATURAL_EMPTY_SET;
- }
+ private static final RegularImmutableSortedSet<Comparable> NATURAL_EMPTY_SET =
+ new RegularImmutableSortedSet<Comparable>(ImmutableList.<Comparable>of(), NATURAL_ORDER);
- static <E> ImmutableSortedSet<E> emptySet(
- Comparator<? super E> comparator) {
+ static <E> RegularImmutableSortedSet<E> emptySet(Comparator<? super E> comparator) {
if (NATURAL_ORDER.equals(comparator)) {
- return emptySet();
+ return (RegularImmutableSortedSet<E>) NATURAL_EMPTY_SET;
} else {
- return new EmptyImmutableSortedSet<E>(comparator);
+ return new RegularImmutableSortedSet<E>(ImmutableList.<E>of(), comparator);
}
}
@@ -118,16 +76,14 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* Returns the empty immutable sorted set.
*/
public static <E> ImmutableSortedSet<E> of() {
- return emptySet();
+ return (ImmutableSortedSet<E>) NATURAL_EMPTY_SET;
}
/**
* Returns an immutable sorted set containing a single element.
*/
- public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(
- E element) {
- return new RegularImmutableSortedSet<E>(
- ImmutableList.of(element), Ordering.natural());
+ public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E element) {
+ return new RegularImmutableSortedSet<E>(ImmutableList.of(element), Ordering.natural());
}
/**
@@ -138,8 +94,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* @throws NullPointerException if any element is null
*/
@SuppressWarnings("unchecked")
- public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(
- E e1, E e2) {
+ public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E e1, E e2) {
return construct(Ordering.natural(), 2, e1, e2);
}
@@ -151,8 +106,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* @throws NullPointerException if any element is null
*/
@SuppressWarnings("unchecked")
- public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(
- E e1, E e2, E e3) {
+ public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E e1, E e2, E e3) {
return construct(Ordering.natural(), 3, e1, e2, e3);
}
@@ -164,8 +118,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* @throws NullPointerException if any element is null
*/
@SuppressWarnings("unchecked")
- public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(
- E e1, E e2, E e3, E e4) {
+ public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4) {
return construct(Ordering.natural(), 4, e1, e2, e3, e4);
}
@@ -214,8 +167,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* @throws NullPointerException if any of {@code elements} is null
* @since 3.0
*/
- public static <E extends Comparable<? super E>> ImmutableSortedSet<E> copyOf(
- E[] elements) {
+ public static <E extends Comparable<? super E>> ImmutableSortedSet<E> copyOf(E[] elements) {
return construct(Ordering.natural(), elements.length, elements.clone());
}
@@ -245,8 +197,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* @throws ClassCastException if the elements are not mutually comparable
* @throws NullPointerException if any of {@code elements} is null
*/
- public static <E> ImmutableSortedSet<E> copyOf(
- Iterable<? extends E> elements) {
+ public static <E> ImmutableSortedSet<E> copyOf(Iterable<? extends E> elements) {
// Hack around E not being a subtype of Comparable.
// Unsafe, see ImmutableSortedSetFauxverideShim.
@SuppressWarnings("unchecked")
@@ -283,8 +234,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* @throws NullPointerException if any of {@code elements} is null
* @since 7.0 (source-compatible since 2.0)
*/
- public static <E> ImmutableSortedSet<E> copyOf(
- Collection<? extends E> elements) {
+ public static <E> ImmutableSortedSet<E> copyOf(Collection<? extends E> elements) {
// Hack around E not being a subtype of Comparable.
// Unsafe, see ImmutableSortedSetFauxverideShim.
@SuppressWarnings("unchecked")
@@ -303,8 +253,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* @throws ClassCastException if the elements are not mutually comparable
* @throws NullPointerException if any of {@code elements} is null
*/
- public static <E> ImmutableSortedSet<E> copyOf(
- Iterator<? extends E> elements) {
+ public static <E> ImmutableSortedSet<E> copyOf(Iterator<? extends E> elements) {
// Hack around E not being a subtype of Comparable.
// Unsafe, see ImmutableSortedSetFauxverideShim.
@SuppressWarnings("unchecked")
@@ -342,8 +291,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
public static <E> ImmutableSortedSet<E> copyOf(
Comparator<? super E> comparator, Iterable<? extends E> elements) {
checkNotNull(comparator);
- boolean hasSameComparator =
- SortedIterables.hasSameComparator(comparator, elements);
+ boolean hasSameComparator = SortedIterables.hasSameComparator(comparator, elements);
if (hasSameComparator && (elements instanceof ImmutableSortedSet)) {
@SuppressWarnings("unchecked")
@@ -485,7 +433,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* times to build multiple sets in series. Each set is a superset of the set
* created before it.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public static final class Builder<E> extends ImmutableSet.Builder<E> {
private final Comparator<? super E> comparator;
@@ -508,7 +456,8 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* @return this {@code Builder} object
* @throws NullPointerException if {@code element} is null
*/
- @Override public Builder<E> add(E element) {
+ @Override
+ public Builder<E> add(E element) {
super.add(element);
return this;
}
@@ -521,7 +470,8 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* @return this {@code Builder} object
* @throws NullPointerException if {@code elements} contains a null element
*/
- @Override public Builder<E> add(E... elements) {
+ @Override
+ public Builder<E> add(E... elements) {
super.add(elements);
return this;
}
@@ -534,7 +484,8 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* @return this {@code Builder} object
* @throws NullPointerException if {@code elements} contains a null element
*/
- @Override public Builder<E> addAll(Iterable<? extends E> elements) {
+ @Override
+ public Builder<E> addAll(Iterable<? extends E> elements) {
super.addAll(elements);
return this;
}
@@ -547,7 +498,8 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* @return this {@code Builder} object
* @throws NullPointerException if {@code elements} contains a null element
*/
- @Override public Builder<E> addAll(Iterator<? extends E> elements) {
+ @Override
+ public Builder<E> addAll(Iterator<? extends E> elements) {
super.addAll(elements);
return this;
}
@@ -556,7 +508,8 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
* Returns a newly-created {@code ImmutableSortedSet} based on the contents
* of the {@code Builder} and its comparator.
*/
- @Override public ImmutableSortedSet<E> build() {
+ @Override
+ public ImmutableSortedSet<E> build() {
@SuppressWarnings("unchecked") // we're careful to put only E's in here
E[] contentsArray = (E[]) contents;
ImmutableSortedSet<E> result = construct(comparator, size, contentsArray);
@@ -569,8 +522,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
return unsafeCompare(comparator, a, b);
}
- static int unsafeCompare(
- Comparator<?> comparator, Object a, Object b) {
+ static int unsafeCompare(Comparator<?> comparator, Object a, Object b) {
// Pretend the comparator can compare anything. If it turns out it can't
// compare a and b, we should get a CCE on the subsequent line. Only methods
// that are spec'd to throw CCE should call this.
@@ -691,7 +643,7 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
E fromElement, boolean fromInclusive, E toElement, boolean toInclusive);
abstract ImmutableSortedSet<E> tailSetImpl(E fromElement, boolean inclusive);
-
+
/**
* @since 12.0
*/
@@ -824,13 +776,12 @@ public abstract class ImmutableSortedSet<E> extends ImmutableSortedSetFauxveride
private static final long serialVersionUID = 0;
}
- private void readObject(ObjectInputStream stream)
- throws InvalidObjectException {
+ private void readObject(ObjectInputStream stream) throws InvalidObjectException {
throw new InvalidObjectException("Use SerializedForm");
}
- @Override Object writeReplace() {
+ @Override
+ Object writeReplace() {
return new SerializedForm<E>(comparator, toArray());
}
}
-
diff --git a/guava/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java b/guava/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java
index 14c4d96..1ed865c 100644
--- a/guava/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java
+++ b/guava/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java
@@ -42,7 +42,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
* @deprecated Use {@link ImmutableSortedSet#naturalOrder}, which offers
* better type-safety.
*/
- @Deprecated public static <E> ImmutableSortedSet.Builder<E> builder() {
+ @Deprecated
+ public static <E> ImmutableSortedSet.Builder<E> builder() {
throw new UnsupportedOperationException();
}
@@ -55,7 +56,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
* @deprecated <b>Pass a parameter of type {@code Comparable} to use {@link
* ImmutableSortedSet#of(Comparable)}.</b>
*/
- @Deprecated public static <E> ImmutableSortedSet<E> of(E element) {
+ @Deprecated
+ public static <E> ImmutableSortedSet<E> of(E element) {
throw new UnsupportedOperationException();
}
@@ -68,7 +70,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
* @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link
* ImmutableSortedSet#of(Comparable, Comparable)}.</b>
*/
- @Deprecated public static <E> ImmutableSortedSet<E> of(E e1, E e2) {
+ @Deprecated
+ public static <E> ImmutableSortedSet<E> of(E e1, E e2) {
throw new UnsupportedOperationException();
}
@@ -81,7 +84,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
* @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link
* ImmutableSortedSet#of(Comparable, Comparable, Comparable)}.</b>
*/
- @Deprecated public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3) {
+ @Deprecated
+ public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3) {
throw new UnsupportedOperationException();
}
@@ -95,8 +99,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
* ImmutableSortedSet#of(Comparable, Comparable, Comparable, Comparable)}.
* </b>
*/
- @Deprecated public static <E> ImmutableSortedSet<E> of(
- E e1, E e2, E e3, E e4) {
+ @Deprecated
+ public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4) {
throw new UnsupportedOperationException();
}
@@ -110,8 +114,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
* ImmutableSortedSet#of(
* Comparable, Comparable, Comparable, Comparable, Comparable)}. </b>
*/
- @Deprecated public static <E> ImmutableSortedSet<E> of(
- E e1, E e2, E e3, E e4, E e5) {
+ @Deprecated
+ public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4, E e5) {
throw new UnsupportedOperationException();
}
@@ -122,11 +126,11 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
*
* @throws UnsupportedOperationException always
* @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link
- * ImmutableSortedSet#of(Comparable, Comparable, Comparable, Comparable,
+ * ImmutableSortedSet#of(Comparable, Comparable, Comparable, Comparable,
* Comparable, Comparable, Comparable...)}. </b>
*/
- @Deprecated public static <E> ImmutableSortedSet<E> of(
- E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) {
+ @Deprecated
+ public static <E> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) {
throw new UnsupportedOperationException();
}
@@ -139,7 +143,8 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
* @deprecated <b>Pass parameters of type {@code Comparable} to use {@link
* ImmutableSortedSet#copyOf(Comparable[])}.</b>
*/
- @Deprecated public static <E> ImmutableSortedSet<E> copyOf(E[] elements) {
+ @Deprecated
+ public static <E> ImmutableSortedSet<E> copyOf(E[] elements) {
throw new UnsupportedOperationException();
}
@@ -154,7 +159,7 @@ abstract class ImmutableSortedSetFauxverideShim<E> extends ImmutableSet<E> {
* compatibility with that version and with any other compilers that interpret
* the JLS similarly, there is no definition of copyOf() here, and the
* definition in ImmutableSortedSet matches that in ImmutableSet.
- *
+ *
* The result is that ImmutableSortedSet.copyOf() may be called on
* non-Comparable elements. We have not discovered a better solution. In
* retrospect, the static factory methods should have gone in a separate class
diff --git a/guava/src/com/google/common/collect/ImmutableTable.java b/guava/src/com/google/common/collect/ImmutableTable.java
index 3ed87be..354b299 100644
--- a/guava/src/com/google/common/collect/ImmutableTable.java
+++ b/guava/src/com/google/common/collect/ImmutableTable.java
@@ -29,15 +29,11 @@ import java.util.Map;
import javax.annotation.Nullable;
/**
- * An immutable {@link Table} with reliable user-specified iteration order.
- * Does not permit null keys or values.
- *
- * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
- * it has no public or protected constructors. Thus, instances of this class are
- * guaranteed to be immutable.
+ * A {@link Table} whose contents will never change, with many other important
+ * properties detailed at {@link ImmutableCollection}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
+ * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
* immutable collections</a>.
*
* @author Gregory Kick
@@ -46,11 +42,12 @@ import javax.annotation.Nullable;
@GwtCompatible
// TODO(gak): make serializable
public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
- private static final ImmutableTable<Object, Object, Object> EMPTY
- = new SparseImmutableTable<Object, Object, Object>(
- ImmutableList.<Cell<Object, Object, Object>>of(),
- ImmutableSet.of(), ImmutableSet.of());
-
+ private static final ImmutableTable<Object, Object, Object> EMPTY =
+ new SparseImmutableTable<Object, Object, Object>(
+ ImmutableList.<Cell<Object, Object, Object>>of(),
+ ImmutableSet.of(),
+ ImmutableSet.of());
+
/** Returns an empty immutable table. */
@SuppressWarnings("unchecked")
public static <R, C, V> ImmutableTable<R, C, V> of() {
@@ -58,8 +55,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
}
/** Returns an immutable table containing a single cell. */
- public static <R, C, V> ImmutableTable<R, C, V> of(R rowKey,
- C columnKey, V value) {
+ public static <R, C, V> ImmutableTable<R, C, V> of(R rowKey, C columnKey, V value) {
return new SingletonImmutableTable<R, C, V>(rowKey, columnKey, value);
}
@@ -81,8 +77,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
Table<? extends R, ? extends C, ? extends V> table) {
if (table instanceof ImmutableTable) {
@SuppressWarnings("unchecked")
- ImmutableTable<R, C, V> parameterizedTable
- = (ImmutableTable<R, C, V>) table;
+ ImmutableTable<R, C, V> parameterizedTable = (ImmutableTable<R, C, V>) table;
return parameterizedTable;
} else {
int size = table.size();
@@ -90,21 +85,20 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
case 0:
return of();
case 1:
- Cell<? extends R, ? extends C, ? extends V> onlyCell
- = Iterables.getOnlyElement(table.cellSet());
- return ImmutableTable.<R, C, V>of(onlyCell.getRowKey(),
- onlyCell.getColumnKey(), onlyCell.getValue());
+ Cell<? extends R, ? extends C, ? extends V> onlyCell =
+ Iterables.getOnlyElement(table.cellSet());
+ return ImmutableTable.<R, C, V>of(
+ onlyCell.getRowKey(), onlyCell.getColumnKey(), onlyCell.getValue());
default:
- ImmutableSet.Builder<Cell<R, C, V>> cellSetBuilder
- = ImmutableSet.builder();
- for (Cell<? extends R, ? extends C, ? extends V> cell :
- table.cellSet()) {
+ ImmutableSet.Builder<Cell<R, C, V>> cellSetBuilder =
+ new ImmutableSet.Builder<Cell<R, C, V>>(size);
+ for (Cell<? extends R, ? extends C, ? extends V> cell : table.cellSet()) {
/*
* Must cast to be able to create a Cell<R, C, V> rather than a
* Cell<? extends R, ? extends C, ? extends V>
*/
- cellSetBuilder.add(cellOf((R) cell.getRowKey(),
- (C) cell.getColumnKey(), (V) cell.getValue()));
+ cellSetBuilder.add(
+ cellOf((R) cell.getRowKey(), (C) cell.getColumnKey(), (V) cell.getValue()));
}
return RegularImmutableTable.forCells(cellSetBuilder.build());
}
@@ -124,8 +118,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
* non-null, and returns a new entry with those values.
*/
static <R, C, V> Cell<R, C, V> cellOf(R rowKey, C columnKey, V value) {
- return Tables.immutableCell(checkNotNull(rowKey), checkNotNull(columnKey),
- checkNotNull(value));
+ return Tables.immutableCell(checkNotNull(rowKey), checkNotNull(columnKey), checkNotNull(value));
}
/**
@@ -176,8 +169,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
/**
* Specifies the ordering of the generated table's columns.
*/
- public Builder<R, C, V> orderColumnsBy(
- Comparator<? super C> columnComparator) {
+ public Builder<R, C, V> orderColumnsBy(Comparator<? super C> columnComparator) {
this.columnComparator = checkNotNull(columnComparator);
return this;
}
@@ -197,8 +189,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
* necessary. Duplicate key pairs are not allowed and will cause {@link
* #build} to fail.
*/
- public Builder<R, C, V> put(
- Cell<? extends R, ? extends C, ? extends V> cell) {
+ public Builder<R, C, V> put(Cell<? extends R, ? extends C, ? extends V> cell) {
if (cell instanceof Tables.ImmutableCell) {
checkNotNull(cell.getRowKey());
checkNotNull(cell.getColumnKey());
@@ -219,8 +210,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
*
* @throws NullPointerException if any key or value in {@code table} is null
*/
- public Builder<R, C, V> putAll(
- Table<? extends R, ? extends C, ? extends V> table) {
+ public Builder<R, C, V> putAll(Table<? extends R, ? extends C, ? extends V> table) {
for (Cell<? extends R, ? extends C, ? extends V> cell : table.cellSet()) {
put(cell);
}
@@ -238,18 +228,17 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
case 0:
return of();
case 1:
- return new SingletonImmutableTable<R, C, V>(
- Iterables.getOnlyElement(cells));
+ return new SingletonImmutableTable<R, C, V>(Iterables.getOnlyElement(cells));
default:
- return RegularImmutableTable.forCells(
- cells, rowComparator, columnComparator);
+ return RegularImmutableTable.forCells(cells, rowComparator, columnComparator);
}
}
}
ImmutableTable() {}
- @Override public ImmutableSet<Cell<R, C, V>> cellSet() {
+ @Override
+ public ImmutableSet<Cell<R, C, V>> cellSet() {
return (ImmutableSet<Cell<R, C, V>>) super.cellSet();
}
@@ -271,7 +260,7 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
@Override
final Iterator<V> valuesIterator() {
- throw new AssertionError("should never be called");
+ throw new AssertionError("should never be called");
}
/**
@@ -279,14 +268,16 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
*
* @throws NullPointerException if {@code columnKey} is {@code null}
*/
- @Override public ImmutableMap<R, V> column(C columnKey) {
+ @Override
+ public ImmutableMap<R, V> column(C columnKey) {
checkNotNull(columnKey);
return MoreObjects.firstNonNull(
(ImmutableMap<R, V>) columnMap().get(columnKey),
ImmutableMap.<R, V>of());
}
- @Override public ImmutableSet<C> columnKeySet() {
+ @Override
+ public ImmutableSet<C> columnKeySet() {
return columnMap().keySet();
}
@@ -296,21 +287,24 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
* <p>The value {@code Map<R, V>} instances in the returned map are
* {@link ImmutableMap} instances as well.
*/
- @Override public abstract ImmutableMap<C, Map<R, V>> columnMap();
+ @Override
+ public abstract ImmutableMap<C, Map<R, V>> columnMap();
/**
* {@inheritDoc}
*
* @throws NullPointerException if {@code rowKey} is {@code null}
*/
- @Override public ImmutableMap<C, V> row(R rowKey) {
+ @Override
+ public ImmutableMap<C, V> row(R rowKey) {
checkNotNull(rowKey);
return MoreObjects.firstNonNull(
(ImmutableMap<C, V>) rowMap().get(rowKey),
ImmutableMap.<C, V>of());
}
- @Override public ImmutableSet<R> rowKeySet() {
+ @Override
+ public ImmutableSet<R> rowKeySet() {
return rowMap().keySet();
}
@@ -320,11 +314,12 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
* <p>The value {@code Map<C, V>} instances in the returned map are
* {@link ImmutableMap} instances as well.
*/
- @Override public abstract ImmutableMap<R, Map<C, V>> rowMap();
+ @Override
+ public abstract ImmutableMap<R, Map<C, V>> rowMap();
@Override
public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
- return get(rowKey, columnKey) != null;
+ return get(rowKey, columnKey) != null;
}
@Override
@@ -338,7 +333,9 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public final void clear() {
+ @Deprecated
+ @Override
+ public final void clear() {
throw new UnsupportedOperationException();
}
@@ -348,7 +345,9 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public final V put(R rowKey, C columnKey, V value) {
+ @Deprecated
+ @Override
+ public final V put(R rowKey, C columnKey, V value) {
throw new UnsupportedOperationException();
}
@@ -358,8 +357,9 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public final void putAll(
- Table<? extends R, ? extends C, ? extends V> table) {
+ @Deprecated
+ @Override
+ public final void putAll(Table<? extends R, ? extends C, ? extends V> table) {
throw new UnsupportedOperationException();
}
@@ -369,7 +369,9 @@ public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> {
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public final V remove(Object rowKey, Object columnKey) {
+ @Deprecated
+ @Override
+ public final V remove(Object rowKey, Object columnKey) {
throw new UnsupportedOperationException();
}
}
diff --git a/guava/src/com/google/common/collect/Interners.java b/guava/src/com/google/common/collect/Interners.java
index bd592d6..94531df 100644
--- a/guava/src/com/google/common/collect/Interners.java
+++ b/guava/src/com/google/common/collect/Interners.java
@@ -44,7 +44,8 @@ public final class Interners {
public static <E> Interner<E> newStrongInterner() {
final ConcurrentMap<E, E> map = new MapMaker().makeMap();
return new Interner<E>() {
- @Override public E intern(E sample) {
+ @Override
+ public E intern(E sample) {
E canonical = map.putIfAbsent(checkNotNull(sample), sample);
return (canonical == null) ? sample : canonical;
}
@@ -65,12 +66,14 @@ public final class Interners {
private static class WeakInterner<E> implements Interner<E> {
// MapMaker is our friend, we know about this type
- private final MapMakerInternalMap<E, Dummy> map = new MapMaker()
- .weakKeys()
- .keyEquivalence(Equivalence.equals())
- .makeCustomMap();
-
- @Override public E intern(E sample) {
+ private final MapMakerInternalMap<E, Dummy> map =
+ new MapMaker()
+ .weakKeys()
+ .keyEquivalence(Equivalence.equals())
+ .makeCustomMap();
+
+ @Override
+ public E intern(E sample) {
while (true) {
// trying to read the canonical...
ReferenceEntry<E, Dummy> entry = map.getEntry(sample);
@@ -96,7 +99,9 @@ public final class Interners {
}
}
- private enum Dummy { VALUE }
+ private enum Dummy {
+ VALUE
+ }
}
/**
@@ -116,15 +121,18 @@ public final class Interners {
this.interner = interner;
}
- @Override public E apply(E input) {
+ @Override
+ public E apply(E input) {
return interner.intern(input);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return interner.hashCode();
}
- @Override public boolean equals(Object other) {
+ @Override
+ public boolean equals(Object other) {
if (other instanceof InternerFunction) {
InternerFunction<?> that = (InternerFunction<?>) other;
return interner.equals(that.interner);
diff --git a/guava/src/com/google/common/collect/Iterables.java b/guava/src/com/google/common/collect/Iterables.java
index cacba1a..a1421a0 100644
--- a/guava/src/com/google/common/collect/Iterables.java
+++ b/guava/src/com/google/common/collect/Iterables.java
@@ -37,6 +37,7 @@ import java.util.Queue;
import java.util.RandomAccess;
import java.util.Set;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -49,23 +50,21 @@ import javax.annotation.Nullable;
* only advance the backing iteration when absolutely necessary.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Iterables">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#iterables">
* {@code Iterables}</a>.
*
* @author Kevin Bourrillion
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Iterables {
private Iterables() {}
/** Returns an unmodifiable view of {@code iterable}. */
- public static <T> Iterable<T> unmodifiableIterable(
- final Iterable<T> iterable) {
+ public static <T> Iterable<T> unmodifiableIterable(final Iterable<T> iterable) {
checkNotNull(iterable);
- if (iterable instanceof UnmodifiableIterable ||
- iterable instanceof ImmutableCollection) {
+ if (iterable instanceof UnmodifiableIterable || iterable instanceof ImmutableCollection) {
return iterable;
}
return new UnmodifiableIterable<T>(iterable);
@@ -77,8 +76,8 @@ public final class Iterables {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <E> Iterable<E> unmodifiableIterable(
- ImmutableCollection<E> iterable) {
+ @Deprecated
+ public static <E> Iterable<E> unmodifiableIterable(ImmutableCollection<E> iterable) {
return checkNotNull(iterable);
}
@@ -133,8 +132,7 @@ public final class Iterables {
* @param elementsToRemove the elements to remove
* @return {@code true} if any element was removed from {@code iterable}
*/
- public static boolean removeAll(
- Iterable<?> removeFrom, Collection<?> elementsToRemove) {
+ public static boolean removeAll(Iterable<?> removeFrom, Collection<?> elementsToRemove) {
return (removeFrom instanceof Collection)
? ((Collection<?>) removeFrom).removeAll(checkNotNull(elementsToRemove))
: Iterators.removeAll(removeFrom.iterator(), elementsToRemove);
@@ -151,8 +149,7 @@ public final class Iterables {
* @param elementsToRetain the elements to retain
* @return {@code true} if any element was removed from {@code iterable}
*/
- public static boolean retainAll(
- Iterable<?> removeFrom, Collection<?> elementsToRetain) {
+ public static boolean retainAll(Iterable<?> removeFrom, Collection<?> elementsToRetain) {
return (removeFrom instanceof Collection)
? ((Collection<?>) removeFrom).retainAll(checkNotNull(elementsToRetain))
: Iterators.retainAll(removeFrom.iterator(), elementsToRetain);
@@ -171,11 +168,9 @@ public final class Iterables {
* {@code remove()}.
* @since 2.0
*/
- public static <T> boolean removeIf(
- Iterable<T> removeFrom, Predicate<? super T> predicate) {
+ public static <T> boolean removeIf(Iterable<T> removeFrom, Predicate<? super T> predicate) {
if (removeFrom instanceof RandomAccess && removeFrom instanceof List) {
- return removeIfFromRandomAccessList(
- (List<T>) removeFrom, checkNotNull(predicate));
+ return removeIfFromRandomAccessList((List<T>) removeFrom, checkNotNull(predicate));
}
return Iterators.removeIf(removeFrom.iterator(), predicate);
}
@@ -207,8 +202,8 @@ public final class Iterables {
return from != to;
}
- private static <T> void slowRemoveIfForRemainingElements(List<T> list,
- Predicate<? super T> predicate, int to, int from) {
+ private static <T> void slowRemoveIfForRemainingElements(
+ List<T> list, Predicate<? super T> predicate, int to, int from) {
// Here we know that:
// * (to < from) and that both are valid indices.
// * Everything with (index < to) should be kept.
@@ -254,8 +249,8 @@ public final class Iterables {
* of {@code iterable1} is equal to the corresponding element of
* {@code iterable2}.
*/
- public static boolean elementsEqual(
- Iterable<?> iterable1, Iterable<?> iterable2) {
+ @CheckReturnValue
+ public static boolean elementsEqual(Iterable<?> iterable1, Iterable<?> iterable2) {
if (iterable1 instanceof Collection && iterable2 instanceof Collection) {
Collection<?> collection1 = (Collection<?>) iterable1;
Collection<?> collection2 = (Collection<?>) iterable2;
@@ -297,8 +292,7 @@ public final class Iterables {
* elements
*/
@Nullable
- public static <T> T getOnlyElement(
- Iterable<? extends T> iterable, @Nullable T defaultValue) {
+ public static <T> T getOnlyElement(Iterable<? extends T> iterable, @Nullable T defaultValue) {
return Iterators.getOnlyElement(iterable.iterator(), defaultValue);
}
@@ -317,6 +311,11 @@ public final class Iterables {
return collection.toArray(array);
}
+ static <T> T[] toArray(Iterable<? extends T> iterable, T[] array) {
+ Collection<? extends T> collection = toCollection(iterable);
+ return collection.toArray(array);
+ }
+
/**
* Copies an iterable's elements into an array.
*
@@ -345,8 +344,7 @@ public final class Iterables {
* @return {@code true} if {@code collection} was modified as a result of this
* operation.
*/
- public static <T> boolean addAll(
- Collection<T> addTo, Iterable<? extends T> elementsToAdd) {
+ public static <T> boolean addAll(Collection<T> addTo, Iterable<? extends T> elementsToAdd) {
if (elementsToAdd instanceof Collection) {
Collection<? extends T> c = Collections2.cast(elementsToAdd);
return addTo.addAll(c);
@@ -394,7 +392,9 @@ public final class Iterables {
public Iterator<T> iterator() {
return Iterators.cycle(iterable);
}
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return iterable.toString() + " (cycled)";
}
};
@@ -430,8 +430,7 @@ public final class Iterables {
* <p>The returned iterable's iterator supports {@code remove()} when the
* corresponding input iterator supports it.
*/
- public static <T> Iterable<T> concat(
- Iterable<? extends T> a, Iterable<? extends T> b) {
+ public static <T> Iterable<T> concat(Iterable<? extends T> a, Iterable<? extends T> b) {
return concat(ImmutableList.of(a, b));
}
@@ -444,8 +443,8 @@ public final class Iterables {
* <p>The returned iterable's iterator supports {@code remove()} when the
* corresponding input iterator supports it.
*/
- public static <T> Iterable<T> concat(Iterable<? extends T> a,
- Iterable<? extends T> b, Iterable<? extends T> c) {
+ public static <T> Iterable<T> concat(
+ Iterable<? extends T> a, Iterable<? extends T> b, Iterable<? extends T> c) {
return concat(ImmutableList.of(a, b, c));
}
@@ -459,8 +458,10 @@ public final class Iterables {
* <p>The returned iterable's iterator supports {@code remove()} when the
* corresponding input iterator supports it.
*/
- public static <T> Iterable<T> concat(Iterable<? extends T> a,
- Iterable<? extends T> b, Iterable<? extends T> c,
+ public static <T> Iterable<T> concat(
+ Iterable<? extends T> a,
+ Iterable<? extends T> b,
+ Iterable<? extends T> c,
Iterable<? extends T> d) {
return concat(ImmutableList.of(a, b, c, d));
}
@@ -489,8 +490,7 @@ public final class Iterables {
* iterable may throw {@code NullPointerException} if any of the input
* iterators is null.
*/
- public static <T> Iterable<T> concat(
- final Iterable<? extends Iterable<? extends T>> inputs) {
+ public static <T> Iterable<T> concat(final Iterable<? extends Iterable<? extends T>> inputs) {
checkNotNull(inputs);
return new FluentIterable<T>() {
@Override
@@ -534,8 +534,7 @@ public final class Iterables {
* iterable} divided into partitions
* @throws IllegalArgumentException if {@code size} is nonpositive
*/
- public static <T> Iterable<List<T>> partition(
- final Iterable<T> iterable, final int size) {
+ public static <T> Iterable<List<T>> partition(final Iterable<T> iterable, final int size) {
checkNotNull(iterable);
checkArgument(size > 0);
return new FluentIterable<List<T>>() {
@@ -563,8 +562,7 @@ public final class Iterables {
* trailing null elements)
* @throws IllegalArgumentException if {@code size} is nonpositive
*/
- public static <T> Iterable<List<T>> paddedPartition(
- final Iterable<T> iterable, final int size) {
+ public static <T> Iterable<List<T>> paddedPartition(final Iterable<T> iterable, final int size) {
checkNotNull(iterable);
checkArgument(size > 0);
return new FluentIterable<List<T>>() {
@@ -579,6 +577,7 @@ public final class Iterables {
* Returns the elements of {@code unfiltered} that satisfy a predicate. The
* resulting iterable's iterator does not support {@code remove()}.
*/
+ @CheckReturnValue
public static <T> Iterable<T> filter(
final Iterable<T> unfiltered, final Predicate<? super T> predicate) {
checkNotNull(unfiltered);
@@ -603,8 +602,8 @@ public final class Iterables {
* iterable that were of the requested type
*/
@GwtIncompatible("Class.isInstance")
- public static <T> Iterable<T> filter(
- final Iterable<?> unfiltered, final Class<T> type) {
+ @CheckReturnValue
+ public static <T> Iterable<T> filter(final Iterable<?> unfiltered, final Class<T> type) {
checkNotNull(unfiltered);
checkNotNull(type);
return new FluentIterable<T>() {
@@ -618,8 +617,7 @@ public final class Iterables {
/**
* Returns {@code true} if any element in {@code iterable} satisfies the predicate.
*/
- public static <T> boolean any(
- Iterable<T> iterable, Predicate<? super T> predicate) {
+ public static <T> boolean any(Iterable<T> iterable, Predicate<? super T> predicate) {
return Iterators.any(iterable.iterator(), predicate);
}
@@ -627,8 +625,7 @@ public final class Iterables {
* Returns {@code true} if every element in {@code iterable} satisfies the
* predicate. If {@code iterable} is empty, {@code true} is returned.
*/
- public static <T> boolean all(
- Iterable<T> iterable, Predicate<? super T> predicate) {
+ public static <T> boolean all(Iterable<T> iterable, Predicate<? super T> predicate) {
return Iterators.all(iterable.iterator(), predicate);
}
@@ -641,8 +638,7 @@ public final class Iterables {
* @throws NoSuchElementException if no element in {@code iterable} matches
* the given predicate
*/
- public static <T> T find(Iterable<T> iterable,
- Predicate<? super T> predicate) {
+ public static <T> T find(Iterable<T> iterable, Predicate<? super T> predicate) {
return Iterators.find(iterable.iterator(), predicate);
}
@@ -655,8 +651,8 @@ public final class Iterables {
* @since 7.0
*/
@Nullable
- public static <T> T find(Iterable<? extends T> iterable,
- Predicate<? super T> predicate, @Nullable T defaultValue) {
+ public static <T> T find(
+ Iterable<? extends T> iterable, Predicate<? super T> predicate, @Nullable T defaultValue) {
return Iterators.find(iterable.iterator(), predicate, defaultValue);
}
@@ -670,8 +666,7 @@ public final class Iterables {
*
* @since 11.0
*/
- public static <T> Optional<T> tryFind(Iterable<T> iterable,
- Predicate<? super T> predicate) {
+ public static <T> Optional<T> tryFind(Iterable<T> iterable, Predicate<? super T> predicate) {
return Iterators.tryFind(iterable.iterator(), predicate);
}
@@ -686,8 +681,7 @@ public final class Iterables {
*
* @since 2.0
*/
- public static <T> int indexOf(
- Iterable<T> iterable, Predicate<? super T> predicate) {
+ public static <T> int indexOf(Iterable<T> iterable, Predicate<? super T> predicate) {
return Iterators.indexOf(iterable.iterator(), predicate);
}
@@ -703,8 +697,9 @@ public final class Iterables {
* {@code Collection}, consider {@link Lists#transform} and {@link
* Collections2#transform}.
*/
- public static <F, T> Iterable<T> transform(final Iterable<F> fromIterable,
- final Function<? super F, ? extends T> function) {
+ @CheckReturnValue
+ public static <F, T> Iterable<T> transform(
+ final Iterable<F> fromIterable, final Function<? super F, ? extends T> function) {
checkNotNull(fromIterable);
checkNotNull(function);
return new FluentIterable<T>() {
@@ -840,8 +835,7 @@ public final class Iterables {
*
* @since 3.0
*/
- public static <T> Iterable<T> skip(final Iterable<T> iterable,
- final int numberToSkip) {
+ public static <T> Iterable<T> skip(final Iterable<T> iterable, final int numberToSkip) {
checkNotNull(iterable);
checkArgument(numberToSkip >= 0, "number to skip cannot be negative");
@@ -906,8 +900,7 @@ public final class Iterables {
* @throws IllegalArgumentException if {@code limitSize} is negative
* @since 3.0
*/
- public static <T> Iterable<T> limit(
- final Iterable<T> iterable, final int limitSize) {
+ public static <T> Iterable<T> limit(final Iterable<T> iterable, final int limitSize) {
checkNotNull(iterable);
checkArgument(limitSize >= 0, "limit is negative");
return new FluentIterable<T>() {
@@ -967,22 +960,6 @@ public final class Iterables {
};
}
- private static class ConsumingQueueIterator<T> extends AbstractIterator<T> {
- private final Queue<T> queue;
-
- private ConsumingQueueIterator(Queue<T> queue) {
- this.queue = queue;
- }
-
- @Override public T computeNext() {
- try {
- return queue.remove();
- } catch (NoSuchElementException e) {
- return endOfData();
- }
- }
- }
-
// Methods only in Iterables, not in Iterators
/**
@@ -1019,21 +996,21 @@ public final class Iterables {
final Comparator<? super T> comparator) {
checkNotNull(iterables, "iterables");
checkNotNull(comparator, "comparator");
- Iterable<T> iterable = new FluentIterable<T>() {
- @Override
- public Iterator<T> iterator() {
- return Iterators.mergeSorted(
- Iterables.transform(iterables, Iterables.<T>toIterator()),
- comparator);
- }
- };
+ Iterable<T> iterable =
+ new FluentIterable<T>() {
+ @Override
+ public Iterator<T> iterator() {
+ return Iterators.mergeSorted(
+ Iterables.transform(iterables, Iterables.<T>toIterator()),
+ comparator);
+ }
+ };
return new UnmodifiableIterable<T>(iterable);
}
// TODO(user): Is this the best place for this? Move to fluent functions?
// Useful as a public method?
- private static <T> Function<Iterable<? extends T>, Iterator<? extends T>>
- toIterator() {
+ private static <T> Function<Iterable<? extends T>, Iterator<? extends T>> toIterator() {
return new Function<Iterable<? extends T>, Iterator<? extends T>>() {
@Override
public Iterator<? extends T> apply(Iterable<? extends T> iterable) {
diff --git a/guava/src/com/google/common/collect/Iterators.java b/guava/src/com/google/common/collect/Iterators.java
index 229964b..c94b1e8 100644
--- a/guava/src/com/google/common/collect/Iterators.java
+++ b/guava/src/com/google/common/collect/Iterators.java
@@ -46,6 +46,7 @@ import java.util.NoSuchElementException;
import java.util.PriorityQueue;
import java.util.Queue;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -58,39 +59,44 @@ import javax.annotation.Nullable;
* the backing iteration when absolutely necessary.
*
* <p>See the Guava User Guide section on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Iterables">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#iterables">
* {@code Iterators}</a>.
*
* @author Kevin Bourrillion
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Iterators {
private Iterators() {}
- static final UnmodifiableListIterator<Object> EMPTY_LIST_ITERATOR
- = new UnmodifiableListIterator<Object>() {
+ static final UnmodifiableListIterator<Object> EMPTY_LIST_ITERATOR =
+ new UnmodifiableListIterator<Object>() {
@Override
public boolean hasNext() {
return false;
}
+
@Override
public Object next() {
throw new NoSuchElementException();
}
+
@Override
public boolean hasPrevious() {
return false;
}
+
@Override
public Object previous() {
throw new NoSuchElementException();
}
+
@Override
public int nextIndex() {
return 0;
}
+
@Override
public int previousIndex() {
return -1;
@@ -126,15 +132,18 @@ public final class Iterators {
private static final Iterator<Object> EMPTY_MODIFIABLE_ITERATOR =
new Iterator<Object>() {
- @Override public boolean hasNext() {
+ @Override
+ public boolean hasNext() {
return false;
}
- @Override public Object next() {
+ @Override
+ public Object next() {
throw new NoSuchElementException();
}
- @Override public void remove() {
+ @Override
+ public void remove() {
checkRemove(false);
}
};
@@ -152,8 +161,7 @@ public final class Iterators {
}
/** Returns an unmodifiable view of {@code iterator}. */
- public static <T> UnmodifiableIterator<T> unmodifiableIterator(
- final Iterator<T> iterator) {
+ public static <T> UnmodifiableIterator<T> unmodifiableIterator(final Iterator<T> iterator) {
checkNotNull(iterator);
if (iterator instanceof UnmodifiableIterator) {
return (UnmodifiableIterator<T>) iterator;
@@ -163,6 +171,7 @@ public final class Iterators {
public boolean hasNext() {
return iterator.hasNext();
}
+
@Override
public T next() {
return iterator.next();
@@ -176,8 +185,8 @@ public final class Iterators {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <T> UnmodifiableIterator<T> unmodifiableIterator(
- UnmodifiableIterator<T> iterator) {
+ @Deprecated
+ public static <T> UnmodifiableIterator<T> unmodifiableIterator(UnmodifiableIterator<T> iterator) {
return checkNotNull(iterator);
}
@@ -211,8 +220,7 @@ public final class Iterators {
* @param elementsToRemove the elements to remove
* @return {@code true} if any element was removed from {@code iterator}
*/
- public static boolean removeAll(
- Iterator<?> removeFrom, Collection<?> elementsToRemove) {
+ public static boolean removeAll(Iterator<?> removeFrom, Collection<?> elementsToRemove) {
return removeIf(removeFrom, in(elementsToRemove));
}
@@ -227,8 +235,7 @@ public final class Iterators {
* @return {@code true} if any elements were removed from the iterator
* @since 2.0
*/
- public static <T> boolean removeIf(
- Iterator<T> removeFrom, Predicate<? super T> predicate) {
+ public static <T> boolean removeIf(Iterator<T> removeFrom, Predicate<? super T> predicate) {
checkNotNull(predicate);
boolean modified = false;
while (removeFrom.hasNext()) {
@@ -249,8 +256,7 @@ public final class Iterators {
* @param elementsToRetain the elements to retain
* @return {@code true} if any element was removed from {@code iterator}
*/
- public static boolean retainAll(
- Iterator<?> removeFrom, Collection<?> elementsToRetain) {
+ public static boolean retainAll(Iterator<?> removeFrom, Collection<?> elementsToRetain) {
return removeIf(removeFrom, not(in(elementsToRetain)));
}
@@ -264,8 +270,7 @@ public final class Iterators {
* <p>Note that this will modify the supplied iterators, since they will have
* been advanced some number of elements forward.
*/
- public static boolean elementsEqual(
- Iterator<?> iterator1, Iterator<?> iterator2) {
+ public static boolean elementsEqual(Iterator<?> iterator1, Iterator<?> iterator2) {
while (iterator1.hasNext()) {
if (!iterator2.hasNext()) {
return false;
@@ -339,8 +344,7 @@ public final class Iterators {
* have been copied
*/
@GwtIncompatible("Array.newInstance(Class, int)")
- public static <T> T[] toArray(
- Iterator<? extends T> iterator, Class<T> type) {
+ public static <T> T[] toArray(Iterator<? extends T> iterator, Class<T> type) {
List<T> list = Lists.newArrayList(iterator);
return Iterables.toArray(list, type);
}
@@ -353,8 +357,7 @@ public final class Iterators {
* @return {@code true} if {@code collection} was modified as a result of this
* operation
*/
- public static <T> boolean addAll(
- Collection<T> addTo, Iterator<? extends T> iterator) {
+ public static <T> boolean addAll(Collection<T> addTo, Iterator<? extends T> iterator) {
checkNotNull(addTo);
checkNotNull(iterator);
boolean wasModified = false;
@@ -392,29 +395,36 @@ public final class Iterators {
public static <T> Iterator<T> cycle(final Iterable<T> iterable) {
checkNotNull(iterable);
return new Iterator<T>() {
- Iterator<T> iterator = emptyIterator();
- Iterator<T> removeFrom;
+ Iterator<T> iterator = emptyModifiableIterator();
@Override
public boolean hasNext() {
- if (!iterator.hasNext()) {
- iterator = iterable.iterator();
- }
- return iterator.hasNext();
+ /*
+ * Don't store a new Iterator until we know the user can't remove() the last returned
+ * element anymore. Otherwise, when we remove from the old iterator, we may be invalidating
+ * the new one. The result is a ConcurrentModificationException or other bad behavior.
+ *
+ * (If we decide that we really, really hate allocating two Iterators per cycle instead of
+ * one, we can optimistically store the new Iterator and then be willing to throw it out if
+ * the user calls remove().)
+ */
+ return iterator.hasNext() || iterable.iterator().hasNext();
}
+
@Override
public T next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
+ if (!iterator.hasNext()) {
+ iterator = iterable.iterator();
+ if (!iterator.hasNext()) {
+ throw new NoSuchElementException();
+ }
}
- removeFrom = iterator;
return iterator.next();
}
+
@Override
public void remove() {
- checkRemove(removeFrom != null);
- removeFrom.remove();
- removeFrom = null;
+ iterator.remove();
}
};
}
@@ -449,9 +459,10 @@ public final class Iterators {
* {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
* resulting iterator has a cubic complexity to the depth of the nesting.
*/
- public static <T> Iterator<T> concat(Iterator<? extends T> a,
- Iterator<? extends T> b) {
- return concat(ImmutableList.of(a, b).iterator());
+ public static <T> Iterator<T> concat(Iterator<? extends T> a, Iterator<? extends T> b) {
+ checkNotNull(a);
+ checkNotNull(b);
+ return concat(new ConsumingQueueIterator<Iterator<? extends T>>(a, b));
}
/**
@@ -468,9 +479,12 @@ public final class Iterators {
* {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
* resulting iterator has a cubic complexity to the depth of the nesting.
*/
- public static <T> Iterator<T> concat(Iterator<? extends T> a,
- Iterator<? extends T> b, Iterator<? extends T> c) {
- return concat(ImmutableList.of(a, b, c).iterator());
+ public static <T> Iterator<T> concat(
+ Iterator<? extends T> a, Iterator<? extends T> b, Iterator<? extends T> c) {
+ checkNotNull(a);
+ checkNotNull(b);
+ checkNotNull(c);
+ return concat(new ConsumingQueueIterator<Iterator<? extends T>>(a, b, c));
}
/**
@@ -487,10 +501,16 @@ public final class Iterators {
* {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
* resulting iterator has a cubic complexity to the depth of the nesting.
*/
- public static <T> Iterator<T> concat(Iterator<? extends T> a,
- Iterator<? extends T> b, Iterator<? extends T> c,
+ public static <T> Iterator<T> concat(
+ Iterator<? extends T> a,
+ Iterator<? extends T> b,
+ Iterator<? extends T> c,
Iterator<? extends T> d) {
- return concat(ImmutableList.of(a, b, c, d).iterator());
+ checkNotNull(a);
+ checkNotNull(b);
+ checkNotNull(c);
+ checkNotNull(d);
+ return concat(new ConsumingQueueIterator<Iterator<? extends T>>(a, b, c, d));
}
/**
@@ -509,7 +529,10 @@ public final class Iterators {
* @throws NullPointerException if any of the provided iterators is null
*/
public static <T> Iterator<T> concat(Iterator<? extends T>... inputs) {
- return concat(ImmutableList.copyOf(inputs).iterator());
+ for (Iterator<? extends T> input : checkNotNull(inputs)) {
+ checkNotNull(input);
+ }
+ return concat(new ConsumingQueueIterator<Iterator<? extends T>>(inputs));
}
/**
@@ -526,8 +549,7 @@ public final class Iterators {
* {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the
* resulting iterator has a cubic complexity to the depth of the nesting.
*/
- public static <T> Iterator<T> concat(
- final Iterator<? extends Iterator<? extends T>> inputs) {
+ public static <T> Iterator<T> concat(final Iterator<? extends Iterator<? extends T>> inputs) {
checkNotNull(inputs);
return new Iterator<T>() {
Iterator<? extends T> current = emptyIterator();
@@ -543,12 +565,12 @@ public final class Iterators {
// because otherwise we'll have called inputs.next() before throwing
// the first NPE, and the next time around we'll call inputs.next()
// again, incorrectly moving beyond the error.
- while (!(currentHasNext = checkNotNull(current).hasNext())
- && inputs.hasNext()) {
+ while (!(currentHasNext = checkNotNull(current).hasNext()) && inputs.hasNext()) {
current = inputs.next();
}
return currentHasNext;
}
+
@Override
public T next() {
if (!hasNext()) {
@@ -557,6 +579,7 @@ public final class Iterators {
removeFrom = current;
return current.next();
}
+
@Override
public void remove() {
checkRemove(removeFrom != null);
@@ -581,8 +604,7 @@ public final class Iterators {
* iterator} divided into partitions
* @throws IllegalArgumentException if {@code size} is nonpositive
*/
- public static <T> UnmodifiableIterator<List<T>> partition(
- Iterator<T> iterator, int size) {
+ public static <T> UnmodifiableIterator<List<T>> partition(Iterator<T> iterator, int size) {
return partitionImpl(iterator, size, false);
}
@@ -602,8 +624,7 @@ public final class Iterators {
* trailing null elements)
* @throws IllegalArgumentException if {@code size} is nonpositive
*/
- public static <T> UnmodifiableIterator<List<T>> paddedPartition(
- Iterator<T> iterator, int size) {
+ public static <T> UnmodifiableIterator<List<T>> paddedPartition(Iterator<T> iterator, int size) {
return partitionImpl(iterator, size, true);
}
@@ -616,6 +637,7 @@ public final class Iterators {
public boolean hasNext() {
return iterator.hasNext();
}
+
@Override
public List<T> next() {
if (!hasNext()) {
@@ -631,8 +653,7 @@ public final class Iterators {
}
@SuppressWarnings("unchecked") // we only put Ts in it
- List<T> list = Collections.unmodifiableList(
- (List<T>) Arrays.asList(array));
+ List<T> list = Collections.unmodifiableList((List<T>) Arrays.asList(array));
return (pad || count == size) ? list : list.subList(0, count);
}
};
@@ -641,12 +662,14 @@ public final class Iterators {
/**
* Returns the elements of {@code unfiltered} that satisfy a predicate.
*/
+ @CheckReturnValue
public static <T> UnmodifiableIterator<T> filter(
final Iterator<T> unfiltered, final Predicate<? super T> predicate) {
checkNotNull(unfiltered);
checkNotNull(predicate);
return new AbstractIterator<T>() {
- @Override protected T computeNext() {
+ @Override
+ protected T computeNext() {
while (unfiltered.hasNext()) {
T element = unfiltered.next();
if (predicate.apply(element)) {
@@ -670,8 +693,8 @@ public final class Iterators {
*/
@SuppressWarnings("unchecked") // can cast to <T> because non-Ts are removed
@GwtIncompatible("Class.isInstance")
- public static <T> UnmodifiableIterator<T> filter(
- Iterator<?> unfiltered, Class<T> type) {
+ @CheckReturnValue
+ public static <T> UnmodifiableIterator<T> filter(Iterator<?> unfiltered, Class<T> type) {
return (UnmodifiableIterator<T>) filter(unfiltered, instanceOf(type));
}
@@ -679,8 +702,7 @@ public final class Iterators {
* Returns {@code true} if one or more elements returned by {@code iterator}
* satisfy the given predicate.
*/
- public static <T> boolean any(
- Iterator<T> iterator, Predicate<? super T> predicate) {
+ public static <T> boolean any(Iterator<T> iterator, Predicate<? super T> predicate) {
return indexOf(iterator, predicate) != -1;
}
@@ -689,8 +711,7 @@ public final class Iterators {
* satisfies the given predicate. If {@code iterator} is empty, {@code true}
* is returned.
*/
- public static <T> boolean all(
- Iterator<T> iterator, Predicate<? super T> predicate) {
+ public static <T> boolean all(Iterator<T> iterator, Predicate<? super T> predicate) {
checkNotNull(predicate);
while (iterator.hasNext()) {
T element = iterator.next();
@@ -712,8 +733,7 @@ public final class Iterators {
* @throws NoSuchElementException if no element in {@code iterator} matches
* the given predicate
*/
- public static <T> T find(
- Iterator<T> iterator, Predicate<? super T> predicate) {
+ public static <T> T find(Iterator<T> iterator, Predicate<? super T> predicate) {
return filter(iterator, predicate).next();
}
@@ -728,8 +748,8 @@ public final class Iterators {
* @since 7.0
*/
@Nullable
- public static <T> T find(Iterator<? extends T> iterator, Predicate<? super T> predicate,
- @Nullable T defaultValue) {
+ public static <T> T find(
+ Iterator<? extends T> iterator, Predicate<? super T> predicate, @Nullable T defaultValue) {
return getNext(filter(iterator, predicate), defaultValue);
}
@@ -746,8 +766,7 @@ public final class Iterators {
*
* @since 11.0
*/
- public static <T> Optional<T> tryFind(
- Iterator<T> iterator, Predicate<? super T> predicate) {
+ public static <T> Optional<T> tryFind(Iterator<T> iterator, Predicate<? super T> predicate) {
UnmodifiableIterator<T> filteredIterator = filter(iterator, predicate);
return filteredIterator.hasNext()
? Optional.of(filteredIterator.next())
@@ -770,8 +789,7 @@ public final class Iterators {
*
* @since 2.0
*/
- public static <T> int indexOf(
- Iterator<T> iterator, Predicate<? super T> predicate) {
+ public static <T> int indexOf(Iterator<T> iterator, Predicate<? super T> predicate) {
checkNotNull(predicate, "predicate");
for (int i = 0; iterator.hasNext(); i++) {
T current = iterator.next();
@@ -790,8 +808,8 @@ public final class Iterators {
* does. After a successful {@code remove()} call, {@code fromIterator} no
* longer contains the corresponding element.
*/
- public static <F, T> Iterator<T> transform(final Iterator<F> fromIterator,
- final Function<? super F, ? extends T> function) {
+ public static <F, T> Iterator<T> transform(
+ final Iterator<F> fromIterator, final Function<? super F, ? extends T> function) {
checkNotNull(function);
return new TransformedIterator<F, T>(fromIterator) {
@Override
@@ -815,17 +833,19 @@ public final class Iterators {
checkNonnegative(position);
int skipped = advance(iterator, position);
if (!iterator.hasNext()) {
- throw new IndexOutOfBoundsException("position (" + position
- + ") must be less than the number of elements that remained ("
- + skipped + ")");
+ throw new IndexOutOfBoundsException(
+ "position ("
+ + position
+ + ") must be less than the number of elements that remained ("
+ + skipped
+ + ")");
}
return iterator.next();
}
static void checkNonnegative(int position) {
if (position < 0) {
- throw new IndexOutOfBoundsException("position (" + position
- + ") must not be negative");
+ throw new IndexOutOfBoundsException("position (" + position + ") must not be negative");
}
}
@@ -923,8 +943,7 @@ public final class Iterators {
* @throws IllegalArgumentException if {@code limitSize} is negative
* @since 3.0
*/
- public static <T> Iterator<T> limit(
- final Iterator<T> iterator, final int limitSize) {
+ public static <T> Iterator<T> limit(final Iterator<T> iterator, final int limitSize) {
checkNotNull(iterator);
checkArgument(limitSize >= 0, "limit is negative");
return new Iterator<T>() {
@@ -1056,7 +1075,8 @@ public final class Iterators {
* past the beginning of the iteration.
*/
return new AbstractIndexedListIterator<T>(length, index) {
- @Override protected T get(int index) {
+ @Override
+ protected T get(int index) {
return array[offset + index];
}
};
@@ -1068,14 +1088,15 @@ public final class Iterators {
* <p>The {@link Iterable} equivalent of this method is {@link
* Collections#singleton}.
*/
- public static <T> UnmodifiableIterator<T> singletonIterator(
- @Nullable final T value) {
+ public static <T> UnmodifiableIterator<T> singletonIterator(@Nullable final T value) {
return new UnmodifiableIterator<T>() {
boolean done;
+
@Override
public boolean hasNext() {
return !done;
}
+
@Override
public T next() {
if (done) {
@@ -1095,14 +1116,14 @@ public final class Iterators {
* contents can be <i>copied</i> into a collection using {@link
* Collections#list}.
*/
- public static <T> UnmodifiableIterator<T> forEnumeration(
- final Enumeration<T> enumeration) {
+ public static <T> UnmodifiableIterator<T> forEnumeration(final Enumeration<T> enumeration) {
checkNotNull(enumeration);
return new UnmodifiableIterator<T>() {
@Override
public boolean hasNext() {
return enumeration.hasMoreElements();
}
+
@Override
public T next() {
return enumeration.nextElement();
@@ -1124,6 +1145,7 @@ public final class Iterators {
public boolean hasMoreElements() {
return iterator.hasNext();
}
+
@Override
public T nextElement() {
return iterator.next();
@@ -1214,8 +1236,7 @@ public final class Iterators {
* additional {@link PeekingIterator#peek()} method, this iterator behaves
* exactly the same as {@code iterator}.
*/
- public static <T> PeekingIterator<T> peekingIterator(
- Iterator<? extends T> iterator) {
+ public static <T> PeekingIterator<T> peekingIterator(Iterator<? extends T> iterator) {
if (iterator instanceof PeekingImpl) {
// Safe to cast <? extends T> to <T> because PeekingImpl only uses T
// covariantly (and cannot be subclassed to add non-covariant uses).
@@ -1232,8 +1253,8 @@ public final class Iterators {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <T> PeekingIterator<T> peekingIterator(
- PeekingIterator<T> iterator) {
+ @Deprecated
+ public static <T> PeekingIterator<T> peekingIterator(PeekingIterator<T> iterator) {
return checkNotNull(iterator);
}
@@ -1252,8 +1273,7 @@ public final class Iterators {
*/
@Beta
public static <T> UnmodifiableIterator<T> mergeSorted(
- Iterable<? extends Iterator<? extends T>> iterators,
- Comparator<? super T> comparator) {
+ Iterable<? extends Iterator<? extends T>> iterators, Comparator<? super T> comparator) {
checkNotNull(iterators, "iterators");
checkNotNull(comparator, "comparator");
@@ -1272,7 +1292,8 @@ public final class Iterators {
private static class MergingIterator<T> extends UnmodifiableIterator<T> {
final Queue<PeekingIterator<T>> queue;
- public MergingIterator(Iterable<? extends Iterator<? extends T>> iterators,
+ public MergingIterator(
+ Iterable<? extends Iterator<? extends T>> iterators,
final Comparator<? super T> itemComparator) {
// A comparator that's used by the heap, allowing the heap
// to be sorted based on the top of each iterator.
diff --git a/guava/src/com/google/common/collect/LexicographicalOrdering.java b/guava/src/com/google/common/collect/LexicographicalOrdering.java
index 0d993e4..801af6d 100644
--- a/guava/src/com/google/common/collect/LexicographicalOrdering.java
+++ b/guava/src/com/google/common/collect/LexicographicalOrdering.java
@@ -19,6 +19,7 @@ package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
+import java.util.Comparator;
import java.util.Iterator;
import javax.annotation.Nullable;
@@ -28,16 +29,15 @@ import javax.annotation.Nullable;
* pairwise.
*/
@GwtCompatible(serializable = true)
-final class LexicographicalOrdering<T>
- extends Ordering<Iterable<T>> implements Serializable {
- final Ordering<? super T> elementOrder;
+final class LexicographicalOrdering<T> extends Ordering<Iterable<T>> implements Serializable {
+ final Comparator<? super T> elementOrder;
- LexicographicalOrdering(Ordering<? super T> elementOrder) {
+ LexicographicalOrdering(Comparator<? super T> elementOrder) {
this.elementOrder = elementOrder;
}
- @Override public int compare(
- Iterable<T> leftIterable, Iterable<T> rightIterable) {
+ @Override
+ public int compare(Iterable<T> leftIterable, Iterable<T> rightIterable) {
Iterator<T> left = leftIterable.iterator();
Iterator<T> right = rightIterable.iterator();
while (left.hasNext()) {
@@ -55,7 +55,8 @@ final class LexicographicalOrdering<T>
return 0;
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -66,11 +67,13 @@ final class LexicographicalOrdering<T>
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return elementOrder.hashCode() ^ 2075626741; // meaningless
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return elementOrder + ".lexicographical()";
}
diff --git a/guava/src/com/google/common/collect/LinkedHashMultimap.java b/guava/src/com/google/common/collect/LinkedHashMultimap.java
index 19bc620..0893619 100644
--- a/guava/src/com/google/common/collect/LinkedHashMultimap.java
+++ b/guava/src/com/google/common/collect/LinkedHashMultimap.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -71,12 +72,12 @@ import javax.annotation.Nullable;
* Multimaps#synchronizedSetMultimap}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
* {@code Multimap}</a>.
*
* @author Jared Levy
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
@@ -98,11 +99,9 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
* @throws IllegalArgumentException if {@code expectedKeys} or {@code
* expectedValuesPerKey} is negative
*/
- public static <K, V> LinkedHashMultimap<K, V> create(
- int expectedKeys, int expectedValuesPerKey) {
+ public static <K, V> LinkedHashMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
return new LinkedHashMultimap<K, V>(
- Maps.capacity(expectedKeys),
- Maps.capacity(expectedValuesPerKey));
+ Maps.capacity(expectedKeys), Maps.capacity(expectedValuesPerKey));
}
/**
@@ -123,9 +122,11 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
private interface ValueSetLink<K, V> {
ValueSetLink<K, V> getPredecessorInValueSet();
+
ValueSetLink<K, V> getSuccessorInValueSet();
void setPredecessorInValueSet(ValueSetLink<K, V> entry);
+
void setSuccessorInValueSet(ValueSetLink<K, V> entry);
}
@@ -134,8 +135,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
succ.setPredecessorInValueSet(pred);
}
- private static <K, V> void succeedsInMultimap(
- ValueEntry<K, V> pred, ValueEntry<K, V> succ) {
+ private static <K, V> void succeedsInMultimap(ValueEntry<K, V> pred, ValueEntry<K, V> succ) {
pred.setSuccessorInMultimap(succ);
succ.setPredecessorInMultimap(pred);
}
@@ -155,8 +155,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
* in the LinkedHashMultimap as a whole.
*/
@VisibleForTesting
- static final class ValueEntry<K, V> extends ImmutableEntry<K, V>
- implements ValueSetLink<K, V> {
+ static final class ValueEntry<K, V> extends ImmutableEntry<K, V> implements ValueSetLink<K, V> {
final int smearedValueHash;
@Nullable ValueEntry<K, V> nextInValueBucket;
@@ -167,13 +166,16 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
ValueEntry<K, V> predecessorInMultimap;
ValueEntry<K, V> successorInMultimap;
- ValueEntry(@Nullable K key, @Nullable V value, int smearedValueHash,
+ ValueEntry(
+ @Nullable K key,
+ @Nullable V value,
+ int smearedValueHash,
@Nullable ValueEntry<K, V> nextInValueBucket) {
super(key, value);
this.smearedValueHash = smearedValueHash;
this.nextInValueBucket = nextInValueBucket;
}
-
+
boolean matchesValue(@Nullable Object v, int smearedVHash) {
return smearedValueHash == smearedVHash && Objects.equal(getValue(), v);
}
@@ -284,7 +286,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
* multimap, taken at the time the entry is returned by a method call to the
* collection or its iterator.
*/
- @Override public Set<Map.Entry<K, V>> entries() {
+ @Override
+ public Set<Map.Entry<K, V>> entries() {
return super.entries();
}
@@ -295,11 +298,13 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
* <p>The iterator generated by the returned collection traverses the values
* in the order they were added to the multimap.
*/
- @Override public Collection<V> values() {
+ @Override
+ public Collection<V> values() {
return super.values();
}
@VisibleForTesting
+ @WeakOuter
final class ValueSet extends Sets.ImprovedAbstractSet<V> implements ValueSetLink<K, V> {
/*
* We currently use a fixed load factor of 1.0, a bit higher than normal to reduce memory
@@ -322,12 +327,12 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
this.lastEntry = this;
// Round expected values up to a power of 2 to get the table size.
int tableSize = Hashing.closedTableSize(expectedValues, VALUE_SET_LOAD_FACTOR);
-
+
@SuppressWarnings("unchecked")
ValueEntry<K, V>[] hashTable = new ValueEntry[tableSize];
this.hashTable = hashTable;
}
-
+
private int mask() {
return hashTable.length - 1;
}
@@ -402,7 +407,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
@Override
public boolean contains(@Nullable Object o) {
int smearedHash = Hashing.smearedHash(o);
- for (ValueEntry<K, V> entry = hashTable[smearedHash & mask()]; entry != null;
+ for (ValueEntry<K, V> entry = hashTable[smearedHash & mask()];
+ entry != null;
entry = entry.nextInValueBucket) {
if (entry.matchesValue(o, smearedHash)) {
return true;
@@ -416,8 +422,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
int smearedHash = Hashing.smearedHash(value);
int bucket = smearedHash & mask();
ValueEntry<K, V> rowHead = hashTable[bucket];
- for (ValueEntry<K, V> entry = rowHead; entry != null;
- entry = entry.nextInValueBucket) {
+ for (ValueEntry<K, V> entry = rowHead; entry != null; entry = entry.nextInValueBucket) {
if (entry.matchesValue(value, smearedHash)) {
return false;
}
@@ -442,7 +447,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
this.hashTable = hashTable;
int mask = hashTable.length - 1;
for (ValueSetLink<K, V> entry = firstEntry;
- entry != this; entry = entry.getSuccessorInValueSet()) {
+ entry != this;
+ entry = entry.getSuccessorInValueSet()) {
ValueEntry<K, V> valueEntry = (ValueEntry<K, V>) entry;
int bucket = valueEntry.smearedValueHash & mask;
valueEntry.nextInValueBucket = hashTable[bucket];
@@ -456,8 +462,9 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
int smearedHash = Hashing.smearedHash(o);
int bucket = smearedHash & mask();
ValueEntry<K, V> prev = null;
- for (ValueEntry<K, V> entry = hashTable[bucket]; entry != null;
- prev = entry, entry = entry.nextInValueBucket) {
+ for (ValueEntry<K, V> entry = hashTable[bucket];
+ entry != null;
+ prev = entry, entry = entry.nextInValueBucket) {
if (entry.matchesValue(o, smearedHash)) {
if (prev == null) {
// first entry in the bucket
@@ -480,7 +487,8 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
Arrays.fill(hashTable, null);
size = 0;
for (ValueSetLink<K, V> entry = firstEntry;
- entry != this; entry = entry.getSuccessorInValueSet()) {
+ entry != this;
+ entry = entry.getSuccessorInValueSet()) {
ValueEntry<K, V> valueEntry = (ValueEntry<K, V>) entry;
deleteFromMultimap(valueEntry);
}
@@ -519,7 +527,7 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
}
};
}
-
+
@Override
Iterator<V> valueIterator() {
return Maps.valueIterator(entryIterator());
@@ -538,7 +546,6 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
- stream.writeInt(valueSetCapacity);
stream.writeInt(keySet().size());
for (K key : keySet()) {
stream.writeObject(key);
@@ -551,15 +558,13 @@ public final class LinkedHashMultimap<K, V> extends AbstractSetMultimap<K, V> {
}
@GwtIncompatible("java.io.ObjectInputStream")
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
multimapHeaderEntry = new ValueEntry<K, V>(null, null, 0, null);
succeedsInMultimap(multimapHeaderEntry, multimapHeaderEntry);
- valueSetCapacity = stream.readInt();
+ valueSetCapacity = DEFAULT_VALUE_SET_CAPACITY;
int distinctKeys = stream.readInt();
- Map<K, Collection<V>> map =
- new LinkedHashMap<K, Collection<V>>(Maps.capacity(distinctKeys));
+ Map<K, Collection<V>> map = new LinkedHashMap<K, Collection<V>>();
for (int i = 0; i < distinctKeys; i++) {
@SuppressWarnings("unchecked")
K key = (K) stream.readObject();
diff --git a/guava/src/com/google/common/collect/LinkedHashMultiset.java b/guava/src/com/google/common/collect/LinkedHashMultiset.java
index 9b8c45b..e597236 100644
--- a/guava/src/com/google/common/collect/LinkedHashMultiset.java
+++ b/guava/src/com/google/common/collect/LinkedHashMultiset.java
@@ -31,14 +31,14 @@ import java.util.LinkedHashMap;
* element, those instances are consecutive in the iteration order. If all
* occurrences of an element are removed, after which that element is added to
* the multiset, the element will appear at the end of the iteration.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
* {@code Multiset}</a>.
*
* @author Kevin Bourrillion
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
@@ -71,10 +71,8 @@ public final class LinkedHashMultiset<E> extends AbstractMapBasedMultiset<E> {
*
* @param elements the elements that the multiset should contain
*/
- public static <E> LinkedHashMultiset<E> create(
- Iterable<? extends E> elements) {
- LinkedHashMultiset<E> multiset =
- create(Multisets.inferDistinctElements(elements));
+ public static <E> LinkedHashMultiset<E> create(Iterable<? extends E> elements) {
+ LinkedHashMultiset<E> multiset = create(Multisets.inferDistinctElements(elements));
Iterables.addAll(multiset, elements);
return multiset;
}
@@ -84,8 +82,7 @@ public final class LinkedHashMultiset<E> extends AbstractMapBasedMultiset<E> {
}
private LinkedHashMultiset(int distinctElements) {
- // Could use newLinkedHashMapWithExpectedSize() if it existed
- super(new LinkedHashMap<E, Count>(Maps.capacity(distinctElements)));
+ super(Maps.<E, Count>newLinkedHashMapWithExpectedSize(distinctElements));
}
/**
@@ -99,12 +96,10 @@ public final class LinkedHashMultiset<E> extends AbstractMapBasedMultiset<E> {
}
@GwtIncompatible("java.io.ObjectInputStream")
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
int distinctElements = Serialization.readCount(stream);
- setBackingMap(new LinkedHashMap<E, Count>(
- Maps.capacity(distinctElements)));
+ setBackingMap(new LinkedHashMap<E, Count>());
Serialization.populateMultiset(this, stream, distinctElements);
}
diff --git a/guava/src/com/google/common/collect/LinkedListMultimap.java b/guava/src/com/google/common/collect/LinkedListMultimap.java
index 30969f3..99c8ffa 100644
--- a/guava/src/com/google/common/collect/LinkedListMultimap.java
+++ b/guava/src/com/google/common/collect/LinkedListMultimap.java
@@ -23,6 +23,7 @@ import static java.util.Collections.unmodifiableList;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -92,11 +93,11 @@ import javax.annotation.Nullable;
* Multimaps#synchronizedListMultimap}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
* {@code Multimap}</a>.
*
* @author Mike Bostock
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
@@ -138,12 +139,12 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
return result;
}
}
-
+
private static class KeyList<K, V> {
Node<K, V> head;
Node<K, V> tail;
int count;
-
+
KeyList(Node<K, V> firstNode) {
this.head = firstNode;
this.tail = firstNode;
@@ -157,7 +158,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
private transient Node<K, V> tail; // the tail for all keys
private transient Map<K, KeyList<K, V>> keyToKeyList;
private transient int size;
-
+
/*
* Tracks modifications to keyToKeyList so that addition or removal of keys invalidates
* preexisting iterators. This does *not* track simple additions and removals of values
@@ -215,8 +216,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
* nextSibling} is null. Note: if {@code nextSibling} is specified, it MUST be
* for an node for the same {@code key}!
*/
- private Node<K, V> addNode(
- @Nullable K key, @Nullable V value, @Nullable Node<K, V> nextSibling) {
+ private Node<K, V> addNode(@Nullable K key, @Nullable V value, @Nullable Node<K, V> nextSibling) {
Node<K, V> node = new Node<K, V>(key, value);
if (head == null) { // empty list
head = tail = node;
@@ -290,7 +290,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
} else {
node.previousSibling.nextSibling = node.nextSibling;
}
-
+
if (node.nextSibling == null) {
keyList.tail = node.previousSibling;
} else {
@@ -337,16 +337,19 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
}
current = null;
}
+
private void checkForConcurrentModification() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
+
@Override
public boolean hasNext() {
checkForConcurrentModification();
return next != null;
}
+
@Override
public Node<K, V> next() {
checkForConcurrentModification();
@@ -356,6 +359,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
nextIndex++;
return current;
}
+
@Override
public void remove() {
checkForConcurrentModification();
@@ -370,11 +374,13 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
current = null;
expectedModCount = modCount;
}
+
@Override
public boolean hasPrevious() {
checkForConcurrentModification();
return previous != null;
}
+
@Override
public Node<K, V> previous() {
checkForConcurrentModification();
@@ -384,22 +390,27 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
nextIndex--;
return current;
}
+
@Override
public int nextIndex() {
return nextIndex;
}
+
@Override
public int previousIndex() {
return nextIndex - 1;
}
+
@Override
public void set(Entry<K, V> e) {
throw new UnsupportedOperationException();
}
+
@Override
public void add(Entry<K, V> e) {
throw new UnsupportedOperationException();
}
+
void setValue(V value) {
checkState(current != null);
current.value = value;
@@ -412,17 +423,19 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
Node<K, V> next = head;
Node<K, V> current;
int expectedModCount = modCount;
-
+
private void checkForConcurrentModification() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
+
@Override
public boolean hasNext() {
checkForConcurrentModification();
return next != null;
}
+
@Override
public K next() {
checkForConcurrentModification();
@@ -434,6 +447,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
} while ((next != null) && !seenKeys.add(next.key));
return current.key;
}
+
@Override
public void remove() {
checkForConcurrentModification();
@@ -669,11 +683,14 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
@Override
public List<V> get(final @Nullable K key) {
return new AbstractSequentialList<V>() {
- @Override public int size() {
+ @Override
+ public int size() {
KeyList<K, V> keyList = keyToKeyList.get(key);
return (keyList == null) ? 0 : keyList.count;
}
- @Override public ListIterator<V> listIterator(int index) {
+
+ @Override
+ public ListIterator<V> listIterator(int index) {
return new ValueForKeyIterator(key, index);
}
};
@@ -681,21 +698,29 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
@Override
Set<K> createKeySet() {
- return new Sets.ImprovedAbstractSet<K>() {
- @Override public int size() {
+ @WeakOuter
+ class KeySetImpl extends Sets.ImprovedAbstractSet<K> {
+ @Override
+ public int size() {
return keyToKeyList.size();
}
- @Override public Iterator<K> iterator() {
+
+ @Override
+ public Iterator<K> iterator() {
return new DistinctKeyIterator();
}
- @Override public boolean contains(Object key) { // for performance
+
+ @Override
+ public boolean contains(Object key) { // for performance
return containsKey(key);
}
+
@Override
public boolean remove(Object o) { // for performance
return !LinkedListMultimap.this.removeAll(o).isEmpty();
}
- };
+ }
+ return new KeySetImpl();
}
/**
@@ -714,12 +739,15 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
@Override
List<V> createValues() {
- return new AbstractSequentialList<V>() {
- @Override public int size() {
+ @WeakOuter
+ class ValuesImpl extends AbstractSequentialList<V> {
+ @Override
+ public int size() {
return size;
}
- @Override public ListIterator<V> listIterator(int index) {
+ @Override
+ public ListIterator<V> listIterator(int index) {
final NodeIterator nodeItr = new NodeIterator(index);
return new TransformedListIterator<Entry<K, V>, V>(nodeItr) {
@Override
@@ -733,7 +761,8 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
}
};
}
- };
+ }
+ return new ValuesImpl();
}
/**
@@ -761,15 +790,19 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
@Override
List<Entry<K, V>> createEntries() {
- return new AbstractSequentialList<Entry<K, V>>() {
- @Override public int size() {
+ @WeakOuter
+ class EntriesImpl extends AbstractSequentialList<Entry<K, V>> {
+ @Override
+ public int size() {
return size;
}
- @Override public ListIterator<Entry<K, V>> listIterator(int index) {
+ @Override
+ public ListIterator<Entry<K, V>> listIterator(int index) {
return new NodeIterator(index);
}
- };
+ }
+ return new EntriesImpl();
}
@Override
@@ -798,8 +831,7 @@ public class LinkedListMultimap<K, V> extends AbstractMultimap<K, V>
}
@GwtIncompatible("java.io.ObjectInputStream")
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
keyToKeyList = Maps.newLinkedHashMap();
int size = stream.readInt();
diff --git a/guava/src/com/google/common/collect/ListMultimap.java b/guava/src/com/google/common/collect/ListMultimap.java
index b76671e..c281c6c 100644
--- a/guava/src/com/google/common/collect/ListMultimap.java
+++ b/guava/src/com/google/common/collect/ListMultimap.java
@@ -32,13 +32,13 @@ import javax.annotation.Nullable;
* <p>The {@link #get}, {@link #removeAll}, and {@link #replaceValues} methods
* each return a {@link List} of values. Though the method signature doesn't say
* so explicitly, the map returned by {@link #asMap} has {@code List} values.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
* {@code Multimap}</a>.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public interface ListMultimap<K, V> extends Multimap<K, V> {
diff --git a/guava/src/com/google/common/collect/Lists.java b/guava/src/com/google/common/collect/Lists.java
index c77a5fc..edf7651 100644
--- a/guava/src/com/google/common/collect/Lists.java
+++ b/guava/src/com/google/common/collect/Lists.java
@@ -50,6 +50,7 @@ import java.util.NoSuchElementException;
import java.util.RandomAccess;
import java.util.concurrent.CopyOnWriteArrayList;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -57,13 +58,13 @@ import javax.annotation.Nullable;
* class's counterparts {@link Sets}, {@link Maps} and {@link Queues}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Lists">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#lists">
* {@code Lists}</a>.
*
* @author Kevin Bourrillion
* @author Mike Bostock
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Lists {
@@ -115,7 +116,8 @@ public final class Lists {
return list;
}
- @VisibleForTesting static int computeArrayListCapacity(int arraySize) {
+ @VisibleForTesting
+ static int computeArrayListCapacity(int arraySize) {
checkNonnegative(arraySize, "arraySize");
// TODO(kevinb): Figure out the right behavior, and document it
@@ -180,8 +182,7 @@ public final class Lists {
* @throws IllegalArgumentException if {@code initialArraySize} is negative
*/
@GwtCompatible(serializable = true)
- public static <E> ArrayList<E> newArrayListWithCapacity(
- int initialArraySize) {
+ public static <E> ArrayList<E> newArrayListWithCapacity(int initialArraySize) {
checkNonnegative(initialArraySize, "initialArraySize"); // for GWT.
return new ArrayList<E>(initialArraySize);
}
@@ -203,8 +204,7 @@ public final class Lists {
* @throws IllegalArgumentException if {@code estimatedSize} is negative
*/
@GwtCompatible(serializable = true)
- public static <E> ArrayList<E> newArrayListWithExpectedSize(
- int estimatedSize) {
+ public static <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) {
return new ArrayList<E>(computeArrayListCapacity(estimatedSize));
}
@@ -253,8 +253,7 @@ public final class Lists {
* advantage of the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
*/
@GwtCompatible(serializable = true)
- public static <E> LinkedList<E> newLinkedList(
- Iterable<? extends E> elements) {
+ public static <E> LinkedList<E> newLinkedList(Iterable<? extends E> elements) {
LinkedList<E> list = newLinkedList();
Iterables.addAll(list, elements);
return list;
@@ -286,9 +285,10 @@ public final class Lists {
Iterable<? extends E> elements) {
// We copy elements to an ArrayList first, rather than incurring the
// quadratic cost of adding them to the COWAL directly.
- Collection<? extends E> elementsCollection = (elements instanceof Collection)
- ? Collections2.cast(elements)
- : newArrayList(elements);
+ Collection<? extends E> elementsCollection =
+ (elements instanceof Collection)
+ ? Collections2.cast(elements)
+ : newArrayList(elements);
return new CopyOnWriteArrayList<E>(elementsCollection);
}
@@ -322,14 +322,19 @@ public final class Lists {
this.first = first;
this.rest = checkNotNull(rest);
}
- @Override public int size() {
+
+ @Override
+ public int size() {
return rest.length + 1;
}
- @Override public E get(int index) {
+
+ @Override
+ public E get(int index) {
// check explicitly so the IOOBE will have the right message
checkElementIndex(index, size());
return (index == 0) ? first : rest[index - 1];
}
+
private static final long serialVersionUID = 0;
}
@@ -350,8 +355,7 @@ public final class Lists {
* @param rest an array of additional elements, possibly empty
* @return an unmodifiable list containing the specified elements
*/
- public static <E> List<E> asList(
- @Nullable E first, @Nullable E second, E[] rest) {
+ public static <E> List<E> asList(@Nullable E first, @Nullable E second, E[] rest) {
return new TwoPlusArrayList<E>(first, second, rest);
}
@@ -367,10 +371,14 @@ public final class Lists {
this.second = second;
this.rest = checkNotNull(rest);
}
- @Override public int size() {
+
+ @Override
+ public int size() {
return rest.length + 2;
}
- @Override public E get(int index) {
+
+ @Override
+ public E get(int index) {
switch (index) {
case 0:
return first;
@@ -382,6 +390,7 @@ public final class Lists {
return rest[index - 2];
}
}
+
private static final long serialVersionUID = 0;
}
@@ -440,8 +449,9 @@ public final class Lists {
* be greater than {@link Integer#MAX_VALUE}
* @throws NullPointerException if {@code lists}, any one of the {@code lists},
* or any element of a provided list is null
- */ static <B> List<List<B>>
- cartesianProduct(List<? extends List<? extends B>> lists) {
+ * @since 19.0
+ */
+ public static <B> List<List<B>> cartesianProduct(List<? extends List<? extends B>> lists) {
return CartesianList.create(lists);
}
@@ -500,8 +510,9 @@ public final class Lists {
* be greater than {@link Integer#MAX_VALUE}
* @throws NullPointerException if {@code lists}, any one of the
* {@code lists}, or any element of a provided list is null
- */ static <B> List<List<B>>
- cartesianProduct(List<? extends B>... lists) {
+ * @since 19.0
+ */
+ public static <B> List<List<B>> cartesianProduct(List<? extends B>... lists) {
return cartesianProduct(Arrays.asList(lists));
}
@@ -538,6 +549,7 @@ public final class Lists {
* then serialize the copy. Other methods similar to this do not implement
* serialization at all for this reason.
*/
+ @CheckReturnValue
public static <F, T> List<T> transform(
List<F> fromList, Function<? super F, ? extends T> function) {
return (fromList instanceof RandomAccess)
@@ -550,13 +562,12 @@ public final class Lists {
*
* @see Lists#transform
*/
- private static class TransformingSequentialList<F, T>
- extends AbstractSequentialList<T> implements Serializable {
+ private static class TransformingSequentialList<F, T> extends AbstractSequentialList<T>
+ implements Serializable {
final List<F> fromList;
final Function<? super F, ? extends T> function;
- TransformingSequentialList(
- List<F> fromList, Function<? super F, ? extends T> function) {
+ TransformingSequentialList(List<F> fromList, Function<? super F, ? extends T> function) {
this.fromList = checkNotNull(fromList);
this.function = checkNotNull(function);
}
@@ -565,13 +576,18 @@ public final class Lists {
* each element which can be overkill. That's why we forward this call
* directly to the backing list.
*/
- @Override public void clear() {
+ @Override
+ public void clear() {
fromList.clear();
}
- @Override public int size() {
+
+ @Override
+ public int size() {
return fromList.size();
}
- @Override public ListIterator<T> listIterator(final int index) {
+
+ @Override
+ public ListIterator<T> listIterator(final int index) {
return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
@Override
T transform(F from) {
@@ -591,26 +607,33 @@ public final class Lists {
*
* @see Lists#transform
*/
- private static class TransformingRandomAccessList<F, T>
- extends AbstractList<T> implements RandomAccess, Serializable {
+ private static class TransformingRandomAccessList<F, T> extends AbstractList<T>
+ implements RandomAccess, Serializable {
final List<F> fromList;
final Function<? super F, ? extends T> function;
- TransformingRandomAccessList(
- List<F> fromList, Function<? super F, ? extends T> function) {
+ TransformingRandomAccessList(List<F> fromList, Function<? super F, ? extends T> function) {
this.fromList = checkNotNull(fromList);
this.function = checkNotNull(function);
}
- @Override public void clear() {
+
+ @Override
+ public void clear() {
fromList.clear();
}
- @Override public T get(int index) {
+
+ @Override
+ public T get(int index) {
return function.apply(fromList.get(index));
}
- @Override public Iterator<T> iterator() {
+
+ @Override
+ public Iterator<T> iterator() {
return listIterator();
}
- @Override public ListIterator<T> listIterator(int index) {
+
+ @Override
+ public ListIterator<T> listIterator(int index) {
return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
@Override
T transform(F from) {
@@ -618,15 +641,22 @@ public final class Lists {
}
};
}
- @Override public boolean isEmpty() {
+
+ @Override
+ public boolean isEmpty() {
return fromList.isEmpty();
}
- @Override public T remove(int index) {
+
+ @Override
+ public T remove(int index) {
return function.apply(fromList.remove(index));
}
- @Override public int size() {
+
+ @Override
+ public int size() {
return fromList.size();
}
+
private static final long serialVersionUID = 0;
}
@@ -665,24 +695,26 @@ public final class Lists {
this.size = size;
}
- @Override public List<T> get(int index) {
+ @Override
+ public List<T> get(int index) {
checkElementIndex(index, size());
int start = index * size;
int end = Math.min(start + size, list.size());
return list.subList(start, end);
}
- @Override public int size() {
+ @Override
+ public int size() {
return IntMath.divide(list.size(), size, RoundingMode.CEILING);
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return list.isEmpty();
}
}
- private static class RandomAccessPartition<T> extends Partition<T>
- implements RandomAccess {
+ private static class RandomAccessPartition<T> extends Partition<T> implements RandomAccess {
RandomAccessPartition(List<T> list, int size) {
super(list, size);
}
@@ -694,13 +726,13 @@ public final class Lists {
*
* @since 7.0
*/
- @Beta public static ImmutableList<Character> charactersOf(String string) {
+ @Beta
+ public static ImmutableList<Character> charactersOf(String string) {
return new StringAsImmutableList(checkNotNull(string));
}
@SuppressWarnings("serial") // serialized using ImmutableList serialization
- private static final class StringAsImmutableList
- extends ImmutableList<Character> {
+ private static final class StringAsImmutableList extends ImmutableList<Character> {
private final String string;
@@ -708,32 +740,35 @@ public final class Lists {
this.string = string;
}
- @Override public int indexOf(@Nullable Object object) {
- return (object instanceof Character)
- ? string.indexOf((Character) object) : -1;
+ @Override
+ public int indexOf(@Nullable Object object) {
+ return (object instanceof Character) ? string.indexOf((Character) object) : -1;
}
- @Override public int lastIndexOf(@Nullable Object object) {
- return (object instanceof Character)
- ? string.lastIndexOf((Character) object) : -1;
+ @Override
+ public int lastIndexOf(@Nullable Object object) {
+ return (object instanceof Character) ? string.lastIndexOf((Character) object) : -1;
}
- @Override public ImmutableList<Character> subList(
- int fromIndex, int toIndex) {
+ @Override
+ public ImmutableList<Character> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, size()); // for GWT
return charactersOf(string.substring(fromIndex, toIndex));
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return false;
}
- @Override public Character get(int index) {
+ @Override
+ public Character get(int index) {
checkElementIndex(index, size()); // for GWT
return string.charAt(index);
}
- @Override public int size() {
+ @Override
+ public int size() {
return string.length();
}
}
@@ -749,24 +784,26 @@ public final class Lists {
* @return an {@code List<Character>} view of the character sequence
* @since 7.0
*/
- @Beta public static List<Character> charactersOf(CharSequence sequence) {
+ @Beta
+ public static List<Character> charactersOf(CharSequence sequence) {
return new CharSequenceAsList(checkNotNull(sequence));
}
- private static final class CharSequenceAsList
- extends AbstractList<Character> {
+ private static final class CharSequenceAsList extends AbstractList<Character> {
private final CharSequence sequence;
CharSequenceAsList(CharSequence sequence) {
this.sequence = sequence;
}
- @Override public Character get(int index) {
+ @Override
+ public Character get(int index) {
checkElementIndex(index, size()); // for GWT
return sequence.charAt(index);
}
- @Override public int size() {
+ @Override
+ public int size() {
return sequence.length();
}
}
@@ -783,6 +820,7 @@ public final class Lists {
*
* @since 7.0
*/
+ @CheckReturnValue
public static <T> List<T> reverse(List<T> list) {
if (list instanceof ImmutableList) {
return ((ImmutableList<T>) list).reverse();
@@ -818,66 +856,79 @@ public final class Lists {
return size - index;
}
- @Override public void add(int index, @Nullable T element) {
+ @Override
+ public void add(int index, @Nullable T element) {
forwardList.add(reversePosition(index), element);
}
- @Override public void clear() {
+ @Override
+ public void clear() {
forwardList.clear();
}
- @Override public T remove(int index) {
+ @Override
+ public T remove(int index) {
return forwardList.remove(reverseIndex(index));
}
- @Override protected void removeRange(int fromIndex, int toIndex) {
+ @Override
+ protected void removeRange(int fromIndex, int toIndex) {
subList(fromIndex, toIndex).clear();
}
- @Override public T set(int index, @Nullable T element) {
+ @Override
+ public T set(int index, @Nullable T element) {
return forwardList.set(reverseIndex(index), element);
}
- @Override public T get(int index) {
+ @Override
+ public T get(int index) {
return forwardList.get(reverseIndex(index));
}
- @Override public int size() {
+ @Override
+ public int size() {
return forwardList.size();
}
- @Override public List<T> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<T> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, size());
- return reverse(forwardList.subList(
- reversePosition(toIndex), reversePosition(fromIndex)));
+ return reverse(forwardList.subList(reversePosition(toIndex), reversePosition(fromIndex)));
}
- @Override public Iterator<T> iterator() {
+ @Override
+ public Iterator<T> iterator() {
return listIterator();
}
- @Override public ListIterator<T> listIterator(int index) {
+ @Override
+ public ListIterator<T> listIterator(int index) {
int start = reversePosition(index);
final ListIterator<T> forwardIterator = forwardList.listIterator(start);
return new ListIterator<T>() {
boolean canRemoveOrSet;
- @Override public void add(T e) {
+ @Override
+ public void add(T e) {
forwardIterator.add(e);
forwardIterator.previous();
canRemoveOrSet = false;
}
- @Override public boolean hasNext() {
+ @Override
+ public boolean hasNext() {
return forwardIterator.hasPrevious();
}
- @Override public boolean hasPrevious() {
+ @Override
+ public boolean hasPrevious() {
return forwardIterator.hasNext();
}
- @Override public T next() {
+ @Override
+ public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
@@ -885,11 +936,13 @@ public final class Lists {
return forwardIterator.previous();
}
- @Override public int nextIndex() {
+ @Override
+ public int nextIndex() {
return reversePosition(forwardIterator.nextIndex());
}
- @Override public T previous() {
+ @Override
+ public T previous() {
if (!hasPrevious()) {
throw new NoSuchElementException();
}
@@ -897,17 +950,20 @@ public final class Lists {
return forwardIterator.next();
}
- @Override public int previousIndex() {
+ @Override
+ public int previousIndex() {
return nextIndex() - 1;
}
- @Override public void remove() {
+ @Override
+ public void remove() {
checkRemove(canRemoveOrSet);
forwardIterator.remove();
canRemoveOrSet = false;
}
- @Override public void set(T e) {
+ @Override
+ public void set(T e) {
checkState(canRemoveOrSet);
forwardIterator.set(e);
}
@@ -915,8 +971,7 @@ public final class Lists {
}
}
- private static class RandomAccessReverseList<T> extends ReverseList<T>
- implements RandomAccess {
+ private static class RandomAccessReverseList<T> extends ReverseList<T> implements RandomAccess {
RandomAccessReverseList(List<T> forwardList) {
super(forwardList);
}
@@ -926,7 +981,7 @@ public final class Lists {
* An implementation of {@link List#hashCode()}.
*/
static int hashCodeImpl(List<?> list) {
- // TODO(user): worth optimizing for RandomAccess?
+ // TODO(lowasser): worth optimizing for RandomAccess?
int hashCode = 1;
for (Object o : list) {
hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
@@ -940,25 +995,35 @@ public final class Lists {
/**
* An implementation of {@link List#equals(Object)}.
*/
- static boolean equalsImpl(List<?> list, @Nullable Object object) {
- if (object == checkNotNull(list)) {
+ static boolean equalsImpl(List<?> thisList, @Nullable Object other) {
+ if (other == checkNotNull(thisList)) {
return true;
}
- if (!(object instanceof List)) {
+ if (!(other instanceof List)) {
return false;
}
-
- List<?> o = (List<?>) object;
-
- return list.size() == o.size()
- && Iterators.elementsEqual(list.iterator(), o.iterator());
+ List<?> otherList = (List<?>) other;
+ int size = thisList.size();
+ if (size != otherList.size()) {
+ return false;
+ }
+ if (thisList instanceof RandomAccess && otherList instanceof RandomAccess) {
+ // avoid allocation and use the faster loop
+ for (int i = 0; i < size; i++) {
+ if (!Objects.equal(thisList.get(i), otherList.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return Iterators.elementsEqual(thisList.iterator(), otherList.iterator());
+ }
}
/**
* An implementation of {@link List#addAll(int, Collection)}.
*/
- static <E> boolean addAllImpl(
- List<E> list, int index, Iterable<? extends E> elements) {
+ static <E> boolean addAllImpl(List<E> list, int index, Iterable<? extends E> elements) {
boolean changed = false;
ListIterator<E> listIterator = list.listIterator(index);
for (E e : elements) {
@@ -972,10 +1037,32 @@ public final class Lists {
* An implementation of {@link List#indexOf(Object)}.
*/
static int indexOfImpl(List<?> list, @Nullable Object element) {
- ListIterator<?> listIterator = list.listIterator();
- while (listIterator.hasNext()) {
- if (Objects.equal(element, listIterator.next())) {
- return listIterator.previousIndex();
+ if (list instanceof RandomAccess) {
+ return indexOfRandomAccess(list, element);
+ } else {
+ ListIterator<?> listIterator = list.listIterator();
+ while (listIterator.hasNext()) {
+ if (Objects.equal(element, listIterator.next())) {
+ return listIterator.previousIndex();
+ }
+ }
+ return -1;
+ }
+ }
+
+ private static int indexOfRandomAccess(List<?> list, @Nullable Object element) {
+ int size = list.size();
+ if (element == null) {
+ for (int i = 0; i < size; i++) {
+ if (list.get(i) == null) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = 0; i < size; i++) {
+ if (element.equals(list.get(i))) {
+ return i;
+ }
}
}
return -1;
@@ -985,10 +1072,31 @@ public final class Lists {
* An implementation of {@link List#lastIndexOf(Object)}.
*/
static int lastIndexOfImpl(List<?> list, @Nullable Object element) {
- ListIterator<?> listIterator = list.listIterator(list.size());
- while (listIterator.hasPrevious()) {
- if (Objects.equal(element, listIterator.previous())) {
- return listIterator.nextIndex();
+ if (list instanceof RandomAccess) {
+ return lastIndexOfRandomAccess(list, element);
+ } else {
+ ListIterator<?> listIterator = list.listIterator(list.size());
+ while (listIterator.hasPrevious()) {
+ if (Objects.equal(element, listIterator.previous())) {
+ return listIterator.nextIndex();
+ }
+ }
+ return -1;
+ }
+ }
+
+ private static int lastIndexOfRandomAccess(List<?> list, @Nullable Object element) {
+ if (element == null) {
+ for (int i = list.size() - 1; i >= 0; i--) {
+ if (list.get(i) == null) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = list.size() - 1; i >= 0; i--) {
+ if (element.equals(list.get(i))) {
+ return i;
+ }
}
}
return -1;
@@ -1004,12 +1112,12 @@ public final class Lists {
/**
* An implementation of {@link List#subList(int, int)}.
*/
- static <E> List<E> subListImpl(
- final List<E> list, int fromIndex, int toIndex) {
+ static <E> List<E> subListImpl(final List<E> list, int fromIndex, int toIndex) {
List<E> wrapper;
if (list instanceof RandomAccess) {
wrapper = new RandomAccessListWrapper<E>(list) {
- @Override public ListIterator<E> listIterator(int index) {
+ @Override
+ public ListIterator<E> listIterator(int index) {
return backingList.listIterator(index);
}
@@ -1017,7 +1125,8 @@ public final class Lists {
};
} else {
wrapper = new AbstractListWrapper<E>(list) {
- @Override public ListIterator<E> listIterator(int index) {
+ @Override
+ public ListIterator<E> listIterator(int index) {
return backingList.listIterator(index);
}
@@ -1034,37 +1143,44 @@ public final class Lists {
this.backingList = checkNotNull(backingList);
}
- @Override public void add(int index, E element) {
+ @Override
+ public void add(int index, E element) {
backingList.add(index, element);
}
- @Override public boolean addAll(int index, Collection<? extends E> c) {
+ @Override
+ public boolean addAll(int index, Collection<? extends E> c) {
return backingList.addAll(index, c);
}
- @Override public E get(int index) {
+ @Override
+ public E get(int index) {
return backingList.get(index);
}
- @Override public E remove(int index) {
+ @Override
+ public E remove(int index) {
return backingList.remove(index);
}
- @Override public E set(int index, E element) {
+ @Override
+ public E set(int index, E element) {
return backingList.set(index, element);
}
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
return backingList.contains(o);
}
- @Override public int size() {
+ @Override
+ public int size() {
return backingList.size();
}
}
- private static class RandomAccessListWrapper<E>
- extends AbstractListWrapper<E> implements RandomAccess {
+ private static class RandomAccessListWrapper<E> extends AbstractListWrapper<E>
+ implements RandomAccess {
RandomAccessListWrapper(List<E> backingList) {
super(backingList);
}
diff --git a/guava/src/com/google/common/collect/MapConstraint.java b/guava/src/com/google/common/collect/MapConstraint.java
index 0f55bce..fb8f694 100644
--- a/guava/src/com/google/common/collect/MapConstraint.java
+++ b/guava/src/com/google/common/collect/MapConstraint.java
@@ -44,9 +44,15 @@ import javax.annotation.Nullable;
* @see MapConstraints
* @see Constraint
* @since 3.0
+ * @deprecated Use {@link Preconditions} for basic checks. In place of
+ * constrained maps, we encourage you to check your preconditions
+ * explicitly instead of leaving that work to the map implementation.
+ * For the specific case of rejecting null, consider {@link ImmutableMap}.
+ * This class is scheduled for removal in Guava 20.0.
*/
@GwtCompatible
@Beta
+ at Deprecated
public interface MapConstraint<K, V> {
/**
* Throws a suitable {@code RuntimeException} if the specified key or value is
diff --git a/guava/src/com/google/common/collect/MapConstraints.java b/guava/src/com/google/common/collect/MapConstraints.java
index 090625d..7b2636e 100644
--- a/guava/src/com/google/common/collect/MapConstraints.java
+++ b/guava/src/com/google/common/collect/MapConstraints.java
@@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.Collection;
@@ -40,9 +41,15 @@ import javax.annotation.Nullable;
* @see Constraints
* @author Mike Bostock
* @since 3.0
+ * @deprecated Use {@link Preconditions} for basic checks. In place of
+ * constrained maps, we encourage you to check your preconditions
+ * explicitly instead of leaving that work to the map implementation.
+ * For the specific case of rejecting null, consider {@link ImmutableMap}.
+ * This class is scheduled for removal in Guava 20.0.
*/
@Beta
@GwtCompatible
+ at Deprecated
public final class MapConstraints {
private MapConstraints() {}
@@ -64,7 +71,8 @@ public final class MapConstraints {
checkNotNull(value);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Not null";
}
}
@@ -124,8 +132,7 @@ public final class MapConstraints {
* @return a constrained view of the specified multimap
*/
public static <K, V> ListMultimap<K, V> constrainedListMultimap(
- ListMultimap<K, V> multimap,
- MapConstraint<? super K, ? super V> constraint) {
+ ListMultimap<K, V> multimap, MapConstraint<? super K, ? super V> constraint) {
return new ConstrainedListMultimap<K, V>(multimap, constraint);
}
@@ -145,8 +152,7 @@ public final class MapConstraints {
* @return a constrained view of the specified multimap
*/
public static <K, V> SetMultimap<K, V> constrainedSetMultimap(
- SetMultimap<K, V> multimap,
- MapConstraint<? super K, ? super V> constraint) {
+ SetMultimap<K, V> multimap, MapConstraint<? super K, ? super V> constraint) {
return new ConstrainedSetMultimap<K, V>(multimap, constraint);
}
@@ -166,8 +172,7 @@ public final class MapConstraints {
* @return a constrained view of the specified multimap
*/
public static <K, V> SortedSetMultimap<K, V> constrainedSortedSetMultimap(
- SortedSetMultimap<K, V> multimap,
- MapConstraint<? super K, ? super V> constraint) {
+ SortedSetMultimap<K, V> multimap, MapConstraint<? super K, ? super V> constraint) {
return new ConstrainedSortedSetMultimap<K, V>(multimap, constraint);
}
@@ -181,15 +186,17 @@ public final class MapConstraints {
* @return a constrained view of the specified entry
*/
private static <K, V> Entry<K, V> constrainedEntry(
- final Entry<K, V> entry,
- final MapConstraint<? super K, ? super V> constraint) {
+ final Entry<K, V> entry, final MapConstraint<? super K, ? super V> constraint) {
checkNotNull(entry);
checkNotNull(constraint);
return new ForwardingMapEntry<K, V>() {
- @Override protected Entry<K, V> delegate() {
+ @Override
+ protected Entry<K, V> delegate() {
return entry;
}
- @Override public V setValue(V value) {
+
+ @Override
+ public V setValue(V value) {
constraint.checkKeyValue(getKey(), value);
return entry.setValue(value);
}
@@ -207,23 +214,26 @@ public final class MapConstraints {
* @return a constrained view of the specified entry
*/
private static <K, V> Entry<K, Collection<V>> constrainedAsMapEntry(
- final Entry<K, Collection<V>> entry,
- final MapConstraint<? super K, ? super V> constraint) {
+ final Entry<K, Collection<V>> entry, final MapConstraint<? super K, ? super V> constraint) {
checkNotNull(entry);
checkNotNull(constraint);
return new ForwardingMapEntry<K, Collection<V>>() {
- @Override protected Entry<K, Collection<V>> delegate() {
+ @Override
+ protected Entry<K, Collection<V>> delegate() {
return entry;
}
- @Override public Collection<V> getValue() {
+
+ @Override
+ public Collection<V> getValue() {
return Constraints.constrainedTypePreservingCollection(
- entry.getValue(), new Constraint<V>() {
- @Override
- public V checkElement(V value) {
- constraint.checkKeyValue(getKey(), value);
- return value;
- }
- });
+ entry.getValue(),
+ new Constraint<V>() {
+ @Override
+ public V checkElement(V value) {
+ constraint.checkKeyValue(getKey(), value);
+ return value;
+ }
+ });
}
};
}
@@ -241,8 +251,7 @@ public final class MapConstraints {
* @return a constrained view of the entries
*/
private static <K, V> Set<Entry<K, Collection<V>>> constrainedAsMapEntries(
- Set<Entry<K, Collection<V>>> entries,
- MapConstraint<? super K, ? super V> constraint) {
+ Set<Entry<K, Collection<V>>> entries, MapConstraint<? super K, ? super V> constraint) {
return new ConstrainedAsMapEntries<K, V>(entries, constraint);
}
@@ -259,8 +268,7 @@ public final class MapConstraints {
* @return a constrained view of the specified entries
*/
private static <K, V> Collection<Entry<K, V>> constrainedEntries(
- Collection<Entry<K, V>> entries,
- MapConstraint<? super K, ? super V> constraint) {
+ Collection<Entry<K, V>> entries, MapConstraint<? super K, ? super V> constraint) {
if (entries instanceof Set) {
return constrainedEntrySet((Set<Entry<K, V>>) entries, constraint);
}
@@ -282,8 +290,7 @@ public final class MapConstraints {
* @return a constrained view of the specified entries
*/
private static <K, V> Set<Entry<K, V>> constrainedEntrySet(
- Set<Entry<K, V>> entries,
- MapConstraint<? super K, ? super V> constraint) {
+ Set<Entry<K, V>> entries, MapConstraint<? super K, ? super V> constraint) {
return new ConstrainedEntrySet<K, V>(entries, constraint);
}
@@ -293,27 +300,33 @@ public final class MapConstraints {
final MapConstraint<? super K, ? super V> constraint;
private transient Set<Entry<K, V>> entrySet;
- ConstrainedMap(
- Map<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
+ ConstrainedMap(Map<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
- @Override protected Map<K, V> delegate() {
+
+ @Override
+ protected Map<K, V> delegate() {
return delegate;
}
- @Override public Set<Entry<K, V>> entrySet() {
+
+ @Override
+ public Set<Entry<K, V>> entrySet() {
Set<Entry<K, V>> result = entrySet;
if (result == null) {
- entrySet = result =
- constrainedEntrySet(delegate.entrySet(), constraint);
+ entrySet = result = constrainedEntrySet(delegate.entrySet(), constraint);
}
return result;
}
- @Override public V put(K key, V value) {
+
+ @Override
+ public V put(K key, V value) {
constraint.checkKeyValue(key, value);
return delegate.put(key, value);
}
- @Override public void putAll(Map<? extends K, ? extends V> map) {
+
+ @Override
+ public void putAll(Map<? extends K, ? extends V> map) {
delegate.putAll(checkMap(map, constraint));
}
}
@@ -335,8 +348,7 @@ public final class MapConstraints {
}
/** @see MapConstraints#constrainedBiMap */
- private static class ConstrainedBiMap<K, V> extends ConstrainedMap<K, V>
- implements BiMap<K, V> {
+ private static class ConstrainedBiMap<K, V> extends ConstrainedMap<K, V> implements BiMap<K, V> {
/*
* We could switch to racy single-check lazy init and remove volatile, but
* there's a downside. That's because this field is also written in the
@@ -351,13 +363,16 @@ public final class MapConstraints {
*/
volatile BiMap<V, K> inverse;
- ConstrainedBiMap(BiMap<K, V> delegate, @Nullable BiMap<V, K> inverse,
+ ConstrainedBiMap(
+ BiMap<K, V> delegate,
+ @Nullable BiMap<V, K> inverse,
MapConstraint<? super K, ? super V> constraint) {
super(delegate, constraint);
this.inverse = inverse;
}
- @Override protected BiMap<K, V> delegate() {
+ @Override
+ protected BiMap<K, V> delegate() {
return (BiMap<K, V>) super.delegate();
}
@@ -370,13 +385,14 @@ public final class MapConstraints {
@Override
public BiMap<V, K> inverse() {
if (inverse == null) {
- inverse = new ConstrainedBiMap<V, K>(delegate().inverse(), this,
- new InverseConstraint<V, K>(constraint));
+ inverse = new ConstrainedBiMap<V, K>(
+ delegate().inverse(), this, new InverseConstraint<V, K>(constraint));
}
return inverse;
}
- @Override public Set<V> values() {
+ @Override
+ public Set<V> values() {
return delegate().values();
}
}
@@ -388,6 +404,7 @@ public final class MapConstraints {
public InverseConstraint(MapConstraint<? super V, ? super K> constraint) {
this.constraint = checkNotNull(constraint);
}
+
@Override
public void checkKeyValue(K key, V value) {
constraint.checkKeyValue(value, key);
@@ -395,47 +412,54 @@ public final class MapConstraints {
}
/** @see MapConstraints#constrainedMultimap */
- private static class ConstrainedMultimap<K, V>
- extends ForwardingMultimap<K, V> implements Serializable {
+ private static class ConstrainedMultimap<K, V> extends ForwardingMultimap<K, V>
+ implements Serializable {
final MapConstraint<? super K, ? super V> constraint;
final Multimap<K, V> delegate;
+
transient Collection<Entry<K, V>> entries;
+
transient Map<K, Collection<V>> asMap;
- public ConstrainedMultimap(Multimap<K, V> delegate,
- MapConstraint<? super K, ? super V> constraint) {
+ public ConstrainedMultimap(
+ Multimap<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
- @Override protected Multimap<K, V> delegate() {
+ @Override
+ protected Multimap<K, V> delegate() {
return delegate;
}
- @Override public Map<K, Collection<V>> asMap() {
+ @Override
+ public Map<K, Collection<V>> asMap() {
Map<K, Collection<V>> result = asMap;
if (result == null) {
final Map<K, Collection<V>> asMapDelegate = delegate.asMap();
- asMap = result = new ForwardingMap<K, Collection<V>>() {
+ @WeakOuter
+ class AsMap extends ForwardingMap<K, Collection<V>> {
Set<Entry<K, Collection<V>>> entrySet;
Collection<Collection<V>> values;
- @Override protected Map<K, Collection<V>> delegate() {
+ @Override
+ protected Map<K, Collection<V>> delegate() {
return asMapDelegate;
}
- @Override public Set<Entry<K, Collection<V>>> entrySet() {
+ @Override
+ public Set<Entry<K, Collection<V>>> entrySet() {
Set<Entry<K, Collection<V>>> result = entrySet;
if (result == null) {
- entrySet = result = constrainedAsMapEntries(
- asMapDelegate.entrySet(), constraint);
+ entrySet = result = constrainedAsMapEntries(asMapDelegate.entrySet(), constraint);
}
return result;
}
@SuppressWarnings("unchecked")
- @Override public Collection<V> get(Object key) {
+ @Override
+ public Collection<V> get(Object key) {
try {
Collection<V> collection = ConstrainedMultimap.this.get((K) key);
return collection.isEmpty() ? null : collection;
@@ -444,24 +468,27 @@ public final class MapConstraints {
}
}
- @Override public Collection<Collection<V>> values() {
+ @Override
+ public Collection<Collection<V>> values() {
Collection<Collection<V>> result = values;
if (result == null) {
- values = result = new ConstrainedAsMapValues<K, V>(
- delegate().values(), entrySet());
+ values = result = new ConstrainedAsMapValues<K, V>(delegate().values(), entrySet());
}
return result;
}
- @Override public boolean containsValue(Object o) {
+ @Override
+ public boolean containsValue(Object o) {
return values().contains(o);
}
- };
+ }
+ asMap = result = new AsMap();
}
return result;
}
- @Override public Collection<Entry<K, V>> entries() {
+ @Override
+ public Collection<Entry<K, V>> entries() {
Collection<Entry<K, V>> result = entries;
if (result == null) {
entries = result = constrainedEntries(delegate.entries(), constraint);
@@ -469,28 +496,32 @@ public final class MapConstraints {
return result;
}
- @Override public Collection<V> get(final K key) {
+ @Override
+ public Collection<V> get(final K key) {
return Constraints.constrainedTypePreservingCollection(
- delegate.get(key), new Constraint<V>() {
- @Override
- public V checkElement(V value) {
- constraint.checkKeyValue(key, value);
- return value;
- }
- });
+ delegate.get(key),
+ new Constraint<V>() {
+ @Override
+ public V checkElement(V value) {
+ constraint.checkKeyValue(key, value);
+ return value;
+ }
+ });
}
- @Override public boolean put(K key, V value) {
+ @Override
+ public boolean put(K key, V value) {
constraint.checkKeyValue(key, value);
return delegate.put(key, value);
}
- @Override public boolean putAll(K key, Iterable<? extends V> values) {
+ @Override
+ public boolean putAll(K key, Iterable<? extends V> values) {
return delegate.putAll(key, checkValues(key, values, constraint));
}
- @Override public boolean putAll(
- Multimap<? extends K, ? extends V> multimap) {
+ @Override
+ public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
boolean changed = false;
for (Entry<? extends K, ? extends V> entry : multimap.entries()) {
changed |= put(entry.getKey(), entry.getValue());
@@ -498,15 +529,14 @@ public final class MapConstraints {
return changed;
}
- @Override public Collection<V> replaceValues(
- K key, Iterable<? extends V> values) {
+ @Override
+ public Collection<V> replaceValues(K key, Iterable<? extends V> values) {
return delegate.replaceValues(key, checkValues(key, values, constraint));
}
}
/** @see ConstrainedMultimap#asMap */
- private static class ConstrainedAsMapValues<K, V>
- extends ForwardingCollection<Collection<V>> {
+ private static class ConstrainedAsMapValues<K, V> extends ForwardingCollection<Collection<V>> {
final Collection<Collection<V>> delegate;
final Set<Entry<K, Collection<V>>> entrySet;
@@ -514,26 +544,31 @@ public final class MapConstraints {
* @param entrySet map entries, linking each key with its corresponding
* values, that already enforce the constraint
*/
- ConstrainedAsMapValues(Collection<Collection<V>> delegate,
- Set<Entry<K, Collection<V>>> entrySet) {
+ ConstrainedAsMapValues(
+ Collection<Collection<V>> delegate, Set<Entry<K, Collection<V>>> entrySet) {
this.delegate = delegate;
this.entrySet = entrySet;
}
- @Override protected Collection<Collection<V>> delegate() {
+
+ @Override
+ protected Collection<Collection<V>> delegate() {
return delegate;
}
- @Override public Iterator<Collection<V>> iterator() {
+ @Override
+ public Iterator<Collection<V>> iterator() {
final Iterator<Entry<K, Collection<V>>> iterator = entrySet.iterator();
return new Iterator<Collection<V>>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
+
@Override
public Collection<V> next() {
return iterator.next().getValue();
}
+
@Override
public void remove() {
iterator.remove();
@@ -541,231 +576,282 @@ public final class MapConstraints {
};
}
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
return standardToArray();
}
- @Override public <T> T[] toArray(T[] array) {
+
+ @Override
+ public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
- @Override public boolean contains(Object o) {
+
+ @Override
+ public boolean contains(Object o) {
return standardContains(o);
}
- @Override public boolean containsAll(Collection<?> c) {
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
return standardContainsAll(c);
}
- @Override public boolean remove(Object o) {
+
+ @Override
+ public boolean remove(Object o) {
return standardRemove(o);
}
- @Override public boolean removeAll(Collection<?> c) {
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
return standardRemoveAll(c);
}
- @Override public boolean retainAll(Collection<?> c) {
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
return standardRetainAll(c);
}
}
/** @see MapConstraints#constrainedEntries */
- private static class ConstrainedEntries<K, V>
- extends ForwardingCollection<Entry<K, V>> {
+ private static class ConstrainedEntries<K, V> extends ForwardingCollection<Entry<K, V>> {
final MapConstraint<? super K, ? super V> constraint;
final Collection<Entry<K, V>> entries;
- ConstrainedEntries(Collection<Entry<K, V>> entries,
- MapConstraint<? super K, ? super V> constraint) {
+ ConstrainedEntries(
+ Collection<Entry<K, V>> entries, MapConstraint<? super K, ? super V> constraint) {
this.entries = entries;
this.constraint = constraint;
}
- @Override protected Collection<Entry<K, V>> delegate() {
+
+ @Override
+ protected Collection<Entry<K, V>> delegate() {
return entries;
}
- @Override public Iterator<Entry<K, V>> iterator() {
- final Iterator<Entry<K, V>> iterator = entries.iterator();
- return new ForwardingIterator<Entry<K, V>>() {
- @Override public Entry<K, V> next() {
- return constrainedEntry(iterator.next(), constraint);
- }
- @Override protected Iterator<Entry<K, V>> delegate() {
- return iterator;
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return new TransformedIterator<Entry<K, V>, Entry<K, V>>(entries.iterator()) {
+ @Override
+ Entry<K, V> transform(Entry<K, V> from) {
+ return constrainedEntry(from, constraint);
}
};
}
// See Collections.CheckedMap.CheckedEntrySet for details on attacks.
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
return standardToArray();
}
- @Override public <T> T[] toArray(T[] array) {
+
+ @Override
+ public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
- @Override public boolean contains(Object o) {
+
+ @Override
+ public boolean contains(Object o) {
return Maps.containsEntryImpl(delegate(), o);
}
- @Override public boolean containsAll(Collection<?> c) {
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
return standardContainsAll(c);
}
- @Override public boolean remove(Object o) {
+
+ @Override
+ public boolean remove(Object o) {
return Maps.removeEntryImpl(delegate(), o);
}
- @Override public boolean removeAll(Collection<?> c) {
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
return standardRemoveAll(c);
}
- @Override public boolean retainAll(Collection<?> c) {
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
return standardRetainAll(c);
}
}
/** @see MapConstraints#constrainedEntrySet */
- static class ConstrainedEntrySet<K, V>
- extends ConstrainedEntries<K, V> implements Set<Entry<K, V>> {
- ConstrainedEntrySet(Set<Entry<K, V>> entries,
- MapConstraint<? super K, ? super V> constraint) {
+ static class ConstrainedEntrySet<K, V> extends ConstrainedEntries<K, V>
+ implements Set<Entry<K, V>> {
+ ConstrainedEntrySet(Set<Entry<K, V>> entries, MapConstraint<? super K, ? super V> constraint) {
super(entries, constraint);
}
// See Collections.CheckedMap.CheckedEntrySet for details on attacks.
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return Sets.equalsImpl(this, object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Sets.hashCodeImpl(this);
}
}
/** @see MapConstraints#constrainedAsMapEntries */
- static class ConstrainedAsMapEntries<K, V>
- extends ForwardingSet<Entry<K, Collection<V>>> {
+ static class ConstrainedAsMapEntries<K, V> extends ForwardingSet<Entry<K, Collection<V>>> {
private final MapConstraint<? super K, ? super V> constraint;
private final Set<Entry<K, Collection<V>>> entries;
- ConstrainedAsMapEntries(Set<Entry<K, Collection<V>>> entries,
- MapConstraint<? super K, ? super V> constraint) {
+ ConstrainedAsMapEntries(
+ Set<Entry<K, Collection<V>>> entries, MapConstraint<? super K, ? super V> constraint) {
this.entries = entries;
this.constraint = constraint;
}
- @Override protected Set<Entry<K, Collection<V>>> delegate() {
+ @Override
+ protected Set<Entry<K, Collection<V>>> delegate() {
return entries;
}
- @Override public Iterator<Entry<K, Collection<V>>> iterator() {
- final Iterator<Entry<K, Collection<V>>> iterator = entries.iterator();
- return new ForwardingIterator<Entry<K, Collection<V>>>() {
- @Override public Entry<K, Collection<V>> next() {
- return constrainedAsMapEntry(iterator.next(), constraint);
- }
- @Override protected Iterator<Entry<K, Collection<V>>> delegate() {
- return iterator;
+ @Override
+ public Iterator<Entry<K, Collection<V>>> iterator() {
+ return new TransformedIterator<Entry<K, Collection<V>>, Entry<K, Collection<V>>>(
+ entries.iterator()) {
+ @Override
+ Entry<K, Collection<V>> transform(Entry<K, Collection<V>> from) {
+ return constrainedAsMapEntry(from, constraint);
}
};
}
// See Collections.CheckedMap.CheckedEntrySet for details on attacks.
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
return standardToArray();
}
- @Override public <T> T[] toArray(T[] array) {
+ @Override
+ public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
return Maps.containsEntryImpl(delegate(), o);
}
- @Override public boolean containsAll(Collection<?> c) {
+ @Override
+ public boolean containsAll(Collection<?> c) {
return standardContainsAll(c);
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return standardEquals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return standardHashCode();
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
return Maps.removeEntryImpl(delegate(), o);
}
- @Override public boolean removeAll(Collection<?> c) {
+ @Override
+ public boolean removeAll(Collection<?> c) {
return standardRemoveAll(c);
}
- @Override public boolean retainAll(Collection<?> c) {
+ @Override
+ public boolean retainAll(Collection<?> c) {
return standardRetainAll(c);
}
}
- private static class ConstrainedListMultimap<K, V>
- extends ConstrainedMultimap<K, V> implements ListMultimap<K, V> {
- ConstrainedListMultimap(ListMultimap<K, V> delegate,
- MapConstraint<? super K, ? super V> constraint) {
+ private static class ConstrainedListMultimap<K, V> extends ConstrainedMultimap<K, V>
+ implements ListMultimap<K, V> {
+ ConstrainedListMultimap(
+ ListMultimap<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
super(delegate, constraint);
}
- @Override public List<V> get(K key) {
+
+ @Override
+ public List<V> get(K key) {
return (List<V>) super.get(key);
}
- @Override public List<V> removeAll(Object key) {
+
+ @Override
+ public List<V> removeAll(Object key) {
return (List<V>) super.removeAll(key);
}
- @Override public List<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public List<V> replaceValues(K key, Iterable<? extends V> values) {
return (List<V>) super.replaceValues(key, values);
}
}
- private static class ConstrainedSetMultimap<K, V>
- extends ConstrainedMultimap<K, V> implements SetMultimap<K, V> {
- ConstrainedSetMultimap(SetMultimap<K, V> delegate,
- MapConstraint<? super K, ? super V> constraint) {
+ private static class ConstrainedSetMultimap<K, V> extends ConstrainedMultimap<K, V>
+ implements SetMultimap<K, V> {
+ ConstrainedSetMultimap(
+ SetMultimap<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
super(delegate, constraint);
}
- @Override public Set<V> get(K key) {
+
+ @Override
+ public Set<V> get(K key) {
return (Set<V>) super.get(key);
}
- @Override public Set<Map.Entry<K, V>> entries() {
+
+ @Override
+ public Set<Map.Entry<K, V>> entries() {
return (Set<Map.Entry<K, V>>) super.entries();
}
- @Override public Set<V> removeAll(Object key) {
+
+ @Override
+ public Set<V> removeAll(Object key) {
return (Set<V>) super.removeAll(key);
}
- @Override public Set<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public Set<V> replaceValues(K key, Iterable<? extends V> values) {
return (Set<V>) super.replaceValues(key, values);
}
}
- private static class ConstrainedSortedSetMultimap<K, V>
- extends ConstrainedSetMultimap<K, V> implements SortedSetMultimap<K, V> {
- ConstrainedSortedSetMultimap(SortedSetMultimap<K, V> delegate,
- MapConstraint<? super K, ? super V> constraint) {
+ private static class ConstrainedSortedSetMultimap<K, V> extends ConstrainedSetMultimap<K, V>
+ implements SortedSetMultimap<K, V> {
+ ConstrainedSortedSetMultimap(
+ SortedSetMultimap<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
super(delegate, constraint);
}
- @Override public SortedSet<V> get(K key) {
+
+ @Override
+ public SortedSet<V> get(K key) {
return (SortedSet<V>) super.get(key);
}
- @Override public SortedSet<V> removeAll(Object key) {
+
+ @Override
+ public SortedSet<V> removeAll(Object key) {
return (SortedSet<V>) super.removeAll(key);
}
- @Override public SortedSet<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
return (SortedSet<V>) super.replaceValues(key, values);
}
+
@Override
public Comparator<? super V> valueComparator() {
return ((SortedSetMultimap<K, V>) delegate()).valueComparator();
}
}
- private static <K, V> Collection<V> checkValues(K key,
- Iterable<? extends V> values,
- MapConstraint<? super K, ? super V> constraint) {
+ private static <K, V> Collection<V> checkValues(
+ K key, Iterable<? extends V> values, MapConstraint<? super K, ? super V> constraint) {
Collection<V> copy = Lists.newArrayList(values);
for (V value : copy) {
constraint.checkKeyValue(key, value);
@@ -773,8 +859,8 @@ public final class MapConstraints {
return copy;
}
- private static <K, V> Map<K, V> checkMap(Map<? extends K, ? extends V> map,
- MapConstraint<? super K, ? super V> constraint) {
+ private static <K, V> Map<K, V> checkMap(
+ Map<? extends K, ? extends V> map, MapConstraint<? super K, ? super V> constraint) {
Map<K, V> copy = new LinkedHashMap<K, V>(map);
for (Entry<K, V> entry : copy.entrySet()) {
constraint.checkKeyValue(entry.getKey(), entry.getValue());
diff --git a/guava/src/com/google/common/collect/MapDifference.java b/guava/src/com/google/common/collect/MapDifference.java
index 484cf67..c1c279e 100644
--- a/guava/src/com/google/common/collect/MapDifference.java
+++ b/guava/src/com/google/common/collect/MapDifference.java
@@ -26,7 +26,7 @@ import javax.annotation.Nullable;
* An object representing the differences between two maps.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public interface MapDifference<K, V> {
@@ -85,7 +85,7 @@ public interface MapDifference<K, V> {
* {@link #leftValue} and {@link #rightValue} are not equal, and one but not
* both of them may be null.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
interface ValueDifference<V> {
/**
@@ -102,13 +102,14 @@ public interface MapDifference<K, V> {
* Two instances are considered equal if their {@link #leftValue()}
* values are equal and their {@link #rightValue()} values are also equal.
*/
- @Override boolean equals(@Nullable Object other);
+ @Override
+ boolean equals(@Nullable Object other);
/**
* The hash code equals the value
* {@code Arrays.asList(leftValue(), rightValue()).hashCode()}.
*/
- @Override int hashCode();
+ @Override
+ int hashCode();
}
-
}
diff --git a/guava/src/com/google/common/collect/MapMaker.java b/guava/src/com/google/common/collect/MapMaker.java
index 0a71ad0..169d122 100644
--- a/guava/src/com/google/common/collect/MapMaker.java
+++ b/guava/src/com/google/common/collect/MapMaker.java
@@ -51,7 +51,6 @@ import javax.annotation.Nullable;
* <li>keys or values automatically wrapped in {@linkplain WeakReference weak} or {@linkplain
* SoftReference soft} references
* <li>notification of evicted (or otherwise removed) entries
- * <li>on-demand computation of values for keys not already present
* </ul>
*
* <p>Usage example: <pre> {@code
@@ -100,7 +99,7 @@ import javax.annotation.Nullable;
* @author Bob Lee
* @author Charles Fry
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class MapMaker extends GenericMapMaker<Object, Object> {
@@ -167,7 +166,9 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
*/
@Override
public MapMaker initialCapacity(int initialCapacity) {
- checkState(this.initialCapacity == UNSET_INT, "initial capacity was already set to %s",
+ checkState(
+ this.initialCapacity == UNSET_INT,
+ "initial capacity was already set to %s",
this.initialCapacity);
checkArgument(initialCapacity >= 0);
this.initialCapacity = initialCapacity;
@@ -204,7 +205,9 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
@Deprecated
@Override
MapMaker maximumSize(int size) {
- checkState(this.maximumSize == UNSET_INT, "maximum size was already set to %s",
+ checkState(
+ this.maximumSize == UNSET_INT,
+ "maximum size was already set to %s",
this.maximumSize);
checkArgument(size >= 0, "maximum size must not be negative");
this.maximumSize = size;
@@ -237,7 +240,9 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
*/
@Override
public MapMaker concurrencyLevel(int concurrencyLevel) {
- checkState(this.concurrencyLevel == UNSET_INT, "concurrency level was already set to %s",
+ checkState(
+ this.concurrencyLevel == UNSET_INT,
+ "concurrency level was already set to %s",
this.concurrencyLevel);
checkArgument(concurrencyLevel > 0);
this.concurrencyLevel = concurrencyLevel;
@@ -325,13 +330,12 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
* @deprecated Caching functionality in {@code MapMaker} has been moved to {@link
* com.google.common.cache.CacheBuilder}, with {@link #softValues} being replaced by {@link
* com.google.common.cache.CacheBuilder#softValues}. Note that {@code CacheBuilder} is simply
- * an enhanced API for an implementation which was branched from {@code MapMaker}. <b>This
- * method is scheduled for removal in March 2015.</b>
+ * an enhanced API for an implementation which was branched from {@code MapMaker}.
*/
@Deprecated
@GwtIncompatible("java.lang.ref.SoftReference")
@Override
- public MapMaker softValues() {
+ MapMaker softValues() {
return setValueStrength(Strength.SOFT);
}
@@ -388,9 +392,13 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
}
private void checkExpiration(long duration, TimeUnit unit) {
- checkState(expireAfterWriteNanos == UNSET_INT, "expireAfterWrite was already set to %s ns",
+ checkState(
+ expireAfterWriteNanos == UNSET_INT,
+ "expireAfterWrite was already set to %s ns",
expireAfterWriteNanos);
- checkState(expireAfterAccessNanos == UNSET_INT, "expireAfterAccess was already set to %s ns",
+ checkState(
+ expireAfterAccessNanos == UNSET_INT,
+ "expireAfterAccess was already set to %s ns",
expireAfterAccessNanos);
checkArgument(duration >= 0, "duration cannot be negative: %s %s", duration, unit);
}
@@ -440,7 +448,8 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
long getExpireAfterAccessNanos() {
return (expireAfterAccessNanos == UNSET_INT)
- ? DEFAULT_EXPIRATION_NANOS : expireAfterAccessNanos;
+ ? DEFAULT_EXPIRATION_NANOS
+ : expireAfterAccessNanos;
}
Ticker getTicker() {
@@ -490,9 +499,8 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
}
/**
- * Builds a thread-safe map, without on-demand computation of values. This method does not alter
- * the state of this {@code MapMaker} instance, so it can be invoked again to create multiple
- * independent maps.
+ * Builds a thread-safe map. This method does not alter the state of this {@code MapMaker}
+ * instance, so it can be invoked again to create multiple independent maps.
*
* <p>The bulk operations {@code putAll}, {@code equals}, and {@code clear} are not guaranteed to
* be performed atomically on the returned map. Additionally, {@code size} and {@code
@@ -575,13 +583,12 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
* @deprecated Caching functionality in {@code MapMaker} has been moved to
* {@link com.google.common.cache.CacheBuilder}, with {@link #makeComputingMap} being replaced
* by {@link com.google.common.cache.CacheBuilder#build}. See the
- * <a href="http://code.google.com/p/guava-libraries/wiki/MapMakerMigration">MapMaker
+ * <a href="https://github.com/google/guava/wiki/MapMakerMigration">MapMaker
* Migration Guide</a> for more details.
*/
@Deprecated
@Override
- <K, V> ConcurrentMap<K, V> makeComputingMap(
- Function<? super K, ? extends V> computingFunction) {
+ <K, V> ConcurrentMap<K, V> makeComputingMap(Function<? super K, ? extends V> computingFunction) {
return (nullRemovalCause == null)
? new MapMaker.ComputingMapAdapter<K, V>(this, computingFunction)
: new NullComputingConcurrentMap<K, V>(this, computingFunction);
@@ -868,12 +875,11 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
* This might make more sense in ComputingConcurrentHashMap, but it causes a javac crash in some
* cases there: http://code.google.com/p/guava-libraries/issues/detail?id=950
*/
- static final class ComputingMapAdapter<K, V>
- extends ComputingConcurrentHashMap<K, V> implements Serializable {
+ static final class ComputingMapAdapter<K, V> extends ComputingConcurrentHashMap<K, V>
+ implements Serializable {
private static final long serialVersionUID = 0;
- ComputingMapAdapter(MapMaker mapMaker,
- Function<? super K, ? extends V> computingFunction) {
+ ComputingMapAdapter(MapMaker mapMaker, Function<? super K, ? extends V> computingFunction) {
super(mapMaker, computingFunction);
}
diff --git a/guava/src/com/google/common/collect/MapMakerInternalMap.java b/guava/src/com/google/common/collect/MapMakerInternalMap.java
index 4232679..f3e6162 100644
--- a/guava/src/com/google/common/collect/MapMakerInternalMap.java
+++ b/guava/src/com/google/common/collect/MapMakerInternalMap.java
@@ -25,6 +25,8 @@ import com.google.common.collect.MapMaker.RemovalCause;
import com.google.common.collect.MapMaker.RemovalListener;
import com.google.common.collect.MapMaker.RemovalNotification;
import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -38,6 +40,7 @@ import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractQueue;
import java.util.AbstractSet;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
@@ -68,8 +71,8 @@ import javax.annotation.concurrent.GuardedBy;
* @author Charles Fry
* @author Doug Lea ({@code ConcurrentHashMap})
*/
-class MapMakerInternalMap<K, V>
- extends AbstractMap<K, V> implements ConcurrentMap<K, V>, Serializable {
+class MapMakerInternalMap<K, V> extends AbstractMap<K, V>
+ implements ConcurrentMap<K, V>, Serializable {
/*
* The basic strategy is to subdivide the table among Segments, each of which itself is a
@@ -209,9 +212,10 @@ class MapMakerInternalMap<K, V>
ticker = builder.getTicker();
removalListener = builder.getRemovalListener();
- removalNotificationQueue = (removalListener == NullListener.INSTANCE)
- ? MapMakerInternalMap.<RemovalNotification<K, V>>discardingQueue()
- : new ConcurrentLinkedQueue<RemovalNotification<K, V>>();
+ removalNotificationQueue =
+ (removalListener == NullListener.INSTANCE)
+ ? MapMakerInternalMap.<RemovalNotification<K, V>>discardingQueue()
+ : new ConcurrentLinkedQueue<RemovalNotification<K, V>>();
int initialCapacity = Math.min(builder.getInitialCapacity(), MAXIMUM_CAPACITY);
if (evictsBySize()) {
@@ -251,13 +255,11 @@ class MapMakerInternalMap<K, V>
if (i == remainder) {
maximumSegmentSize--;
}
- this.segments[i] =
- createSegment(segmentSize, maximumSegmentSize);
+ this.segments[i] = createSegment(segmentSize, maximumSegmentSize);
}
} else {
for (int i = 0; i < this.segments.length; ++i) {
- this.segments[i] =
- createSegment(segmentSize, MapMaker.UNSET_INT);
+ this.segments[i] = createSegment(segmentSize, MapMaker.UNSET_INT);
}
}
}
@@ -461,6 +463,7 @@ class MapMakerInternalMap<K, V>
* Masks used to compute indices in the following table.
*/
static final int EXPIRABLE_MASK = 1;
+
static final int EVICTABLE_MASK = 2;
/**
@@ -468,13 +471,13 @@ class MapMakerInternalMap<K, V>
* the result of OR-ing the feature masks.
*/
static final EntryFactory[][] factories = {
- { STRONG, STRONG_EXPIRABLE, STRONG_EVICTABLE, STRONG_EXPIRABLE_EVICTABLE },
+ {STRONG, STRONG_EXPIRABLE, STRONG_EVICTABLE, STRONG_EXPIRABLE_EVICTABLE},
{}, // no support for SOFT keys
- { WEAK, WEAK_EXPIRABLE, WEAK_EVICTABLE, WEAK_EXPIRABLE_EVICTABLE }
+ {WEAK, WEAK_EXPIRABLE, WEAK_EVICTABLE, WEAK_EXPIRABLE_EVICTABLE}
};
- static EntryFactory getFactory(Strength keyStrength, boolean expireAfterWrite,
- boolean evictsBySize) {
+ static EntryFactory getFactory(
+ Strength keyStrength, boolean expireAfterWrite, boolean evictsBySize) {
int flags = (expireAfterWrite ? EXPIRABLE_MASK : 0) | (evictsBySize ? EVICTABLE_MASK : 0);
return factories[keyStrength.ordinal()][flags];
}
@@ -575,36 +578,39 @@ class MapMakerInternalMap<K, V>
/**
* Placeholder. Indicates that the value hasn't been set yet.
*/
- static final ValueReference<Object, Object> UNSET = new ValueReference<Object, Object>() {
- @Override
- public Object get() {
- return null;
- }
+ static final ValueReference<Object, Object> UNSET =
+ new ValueReference<Object, Object>() {
+ @Override
+ public Object get() {
+ return null;
+ }
- @Override
- public ReferenceEntry<Object, Object> getEntry() {
- return null;
- }
+ @Override
+ public ReferenceEntry<Object, Object> getEntry() {
+ return null;
+ }
- @Override
- public ValueReference<Object, Object> copyFor(ReferenceQueue<Object> queue,
- @Nullable Object value, ReferenceEntry<Object, Object> entry) {
- return this;
- }
+ @Override
+ public ValueReference<Object, Object> copyFor(
+ ReferenceQueue<Object> queue,
+ @Nullable Object value,
+ ReferenceEntry<Object, Object> entry) {
+ return this;
+ }
- @Override
- public boolean isComputingReference() {
- return false;
- }
+ @Override
+ public boolean isComputingReference() {
+ return false;
+ }
- @Override
- public Object waitForValue() {
- return null;
- }
+ @Override
+ public Object waitForValue() {
+ return null;
+ }
- @Override
- public void clear(ValueReference<Object, Object> newValue) {}
- };
+ @Override
+ public void clear(ValueReference<Object, Object> newValue) {}
+ };
/**
* Singleton placeholder that indicates a value is being computed.
@@ -865,32 +871,33 @@ class MapMakerInternalMap<K, V>
return (ReferenceEntry<K, V>) NullEntry.INSTANCE;
}
- static final Queue<? extends Object> DISCARDING_QUEUE = new AbstractQueue<Object>() {
- @Override
- public boolean offer(Object o) {
- return true;
- }
+ static final Queue<? extends Object> DISCARDING_QUEUE =
+ new AbstractQueue<Object>() {
+ @Override
+ public boolean offer(Object o) {
+ return true;
+ }
- @Override
- public Object peek() {
- return null;
- }
+ @Override
+ public Object peek() {
+ return null;
+ }
- @Override
- public Object poll() {
- return null;
- }
+ @Override
+ public Object poll() {
+ return null;
+ }
- @Override
- public int size() {
- return 0;
- }
+ @Override
+ public int size() {
+ return 0;
+ }
- @Override
- public Iterator<Object> iterator() {
- return Iterators.emptyIterator();
- }
- };
+ @Override
+ public Iterator<Object> iterator() {
+ return Iterators.emptyIterator();
+ }
+ };
/**
* Queue that discards all elements.
@@ -1055,8 +1062,8 @@ class MapMakerInternalMap<K, V>
}
}
- static final class StrongEvictableEntry<K, V>
- extends StrongEntry<K, V> implements ReferenceEntry<K, V> {
+ static final class StrongEvictableEntry<K, V> extends StrongEntry<K, V>
+ implements ReferenceEntry<K, V> {
StrongEvictableEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
super(key, hash, next);
}
@@ -1090,8 +1097,8 @@ class MapMakerInternalMap<K, V>
}
}
- static final class StrongExpirableEvictableEntry<K, V>
- extends StrongEntry<K, V> implements ReferenceEntry<K, V> {
+ static final class StrongExpirableEvictableEntry<K, V> extends StrongEntry<K, V>
+ implements ReferenceEntry<K, V> {
StrongExpirableEvictableEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
super(key, hash, next);
}
@@ -1262,8 +1269,8 @@ class MapMakerInternalMap<K, V>
}
}
- static final class SoftExpirableEntry<K, V>
- extends SoftEntry<K, V> implements ReferenceEntry<K, V> {
+ static final class SoftExpirableEntry<K, V> extends SoftEntry<K, V>
+ implements ReferenceEntry<K, V> {
SoftExpirableEntry(
ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
super(queue, key, hash, next);
@@ -1310,8 +1317,8 @@ class MapMakerInternalMap<K, V>
}
}
- static final class SoftEvictableEntry<K, V>
- extends SoftEntry<K, V> implements ReferenceEntry<K, V> {
+ static final class SoftEvictableEntry<K, V> extends SoftEntry<K, V>
+ implements ReferenceEntry<K, V> {
SoftEvictableEntry(
ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
super(queue, key, hash, next);
@@ -1346,8 +1353,8 @@ class MapMakerInternalMap<K, V>
}
}
- static final class SoftExpirableEvictableEntry<K, V>
- extends SoftEntry<K, V> implements ReferenceEntry<K, V> {
+ static final class SoftExpirableEvictableEntry<K, V> extends SoftEntry<K, V>
+ implements ReferenceEntry<K, V> {
SoftExpirableEvictableEntry(
ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
super(queue, key, hash, next);
@@ -1520,8 +1527,8 @@ class MapMakerInternalMap<K, V>
}
}
- static final class WeakExpirableEntry<K, V>
- extends WeakEntry<K, V> implements ReferenceEntry<K, V> {
+ static final class WeakExpirableEntry<K, V> extends WeakEntry<K, V>
+ implements ReferenceEntry<K, V> {
WeakExpirableEntry(
ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
super(queue, key, hash, next);
@@ -1568,8 +1575,8 @@ class MapMakerInternalMap<K, V>
}
}
- static final class WeakEvictableEntry<K, V>
- extends WeakEntry<K, V> implements ReferenceEntry<K, V> {
+ static final class WeakEvictableEntry<K, V> extends WeakEntry<K, V>
+ implements ReferenceEntry<K, V> {
WeakEvictableEntry(
ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
super(queue, key, hash, next);
@@ -1604,8 +1611,8 @@ class MapMakerInternalMap<K, V>
}
}
- static final class WeakExpirableEvictableEntry<K, V>
- extends WeakEntry<K, V> implements ReferenceEntry<K, V> {
+ static final class WeakExpirableEvictableEntry<K, V> extends WeakEntry<K, V>
+ implements ReferenceEntry<K, V> {
WeakExpirableEvictableEntry(
ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
super(queue, key, hash, next);
@@ -1683,8 +1690,8 @@ class MapMakerInternalMap<K, V>
/**
* References a weak value.
*/
- static final class WeakValueReference<K, V>
- extends WeakReference<V> implements ValueReference<K, V> {
+ static final class WeakValueReference<K, V> extends WeakReference<V>
+ implements ValueReference<K, V> {
final ReferenceEntry<K, V> entry;
WeakValueReference(ReferenceQueue<V> queue, V referent, ReferenceEntry<K, V> entry) {
@@ -1722,8 +1729,8 @@ class MapMakerInternalMap<K, V>
/**
* References a soft value.
*/
- static final class SoftValueReference<K, V>
- extends SoftReference<V> implements ValueReference<K, V> {
+ static final class SoftValueReference<K, V> extends SoftReference<V>
+ implements ValueReference<K, V> {
final ReferenceEntry<K, V> entry;
SoftValueReference(ReferenceQueue<V> queue, V referent, ReferenceEntry<K, V> entry) {
@@ -2016,7 +2023,7 @@ class MapMakerInternalMap<K, V>
* comments.
*/
- final MapMakerInternalMap<K, V> map;
+ @Weak final MapMakerInternalMap<K, V> map;
/**
* The number of live elements in this segment's region. This does not include unset elements
@@ -2077,14 +2084,14 @@ class MapMakerInternalMap<K, V>
* A queue of elements currently in the map, ordered by access time. Elements are added to the
* tail of the queue on access/write.
*/
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
final Queue<ReferenceEntry<K, V>> evictionQueue;
/**
* A queue of elements currently in the map, ordered by expiration time (either access or write
* time). Elements are added to the tail of the queue on access/write.
*/
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
final Queue<ReferenceEntry<K, V>> expirationQueue;
Segment(MapMakerInternalMap<K, V> map, int initialCapacity, int maxSegmentSize) {
@@ -2092,23 +2099,24 @@ class MapMakerInternalMap<K, V>
this.maxSegmentSize = maxSegmentSize;
initTable(newEntryArray(initialCapacity));
- keyReferenceQueue = map.usesKeyReferences()
- ? new ReferenceQueue<K>() : null;
+ keyReferenceQueue = map.usesKeyReferences() ? new ReferenceQueue<K>() : null;
- valueReferenceQueue = map.usesValueReferences()
- ? new ReferenceQueue<V>() : null;
+ valueReferenceQueue = map.usesValueReferences() ? new ReferenceQueue<V>() : null;
- recencyQueue = (map.evictsBySize() || map.expiresAfterAccess())
- ? new ConcurrentLinkedQueue<ReferenceEntry<K, V>>()
- : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
+ recencyQueue =
+ (map.evictsBySize() || map.expiresAfterAccess())
+ ? new ConcurrentLinkedQueue<ReferenceEntry<K, V>>()
+ : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
- evictionQueue = map.evictsBySize()
- ? new EvictionQueue<K, V>()
- : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
+ evictionQueue =
+ map.evictsBySize()
+ ? new EvictionQueue<K, V>()
+ : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
- expirationQueue = map.expires()
- ? new ExpirationQueue<K, V>()
- : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
+ expirationQueue =
+ map.expires()
+ ? new ExpirationQueue<K, V>()
+ : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
}
AtomicReferenceArray<ReferenceEntry<K, V>> newEntryArray(int size) {
@@ -2124,7 +2132,7 @@ class MapMakerInternalMap<K, V>
this.table = newTable;
}
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
ReferenceEntry<K, V> newEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
return map.entryFactory.newEntry(this, key, hash, next);
}
@@ -2133,7 +2141,7 @@ class MapMakerInternalMap<K, V>
* Copies {@code original} into a new entry chained to {@code newNext}. Returns the new entry,
* or {@code null} if {@code original} was already garbage collected.
*/
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
ReferenceEntry<K, V> copyEntry(ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
if (original.getKey() == null) {
// key collected
@@ -2155,7 +2163,7 @@ class MapMakerInternalMap<K, V>
/**
* Sets a new value of an entry. Adds newly created entries at the end of the expiration queue.
*/
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
void setValue(ReferenceEntry<K, V> entry, V value) {
ValueReference<K, V> valueReference = map.valueStrength.referenceValue(this, entry, value);
entry.setValueReference(valueReference);
@@ -2181,7 +2189,7 @@ class MapMakerInternalMap<K, V>
* Drain the key and value reference queues, cleaning up internal entries containing garbage
* collected keys or values.
*/
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
void drainReferenceQueues() {
if (map.usesKeyReferences()) {
drainKeyReferenceQueue();
@@ -2191,7 +2199,7 @@ class MapMakerInternalMap<K, V>
}
}
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
void drainKeyReferenceQueue() {
Reference<? extends K> ref;
int i = 0;
@@ -2205,7 +2213,7 @@ class MapMakerInternalMap<K, V>
}
}
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
void drainValueReferenceQueue() {
Reference<? extends V> ref;
int i = 0;
@@ -2262,7 +2270,7 @@ class MapMakerInternalMap<K, V>
* <p>Note: this method should only be called under lock, as it directly manipulates the
* eviction queues. Unlocked reads should use {@link #recordRead}.
*/
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
void recordLockedRead(ReferenceEntry<K, V> entry) {
evictionQueue.add(entry);
if (map.expiresAfterAccess()) {
@@ -2275,7 +2283,7 @@ class MapMakerInternalMap<K, V>
* Updates eviction metadata that {@code entry} was just written. This currently amounts to
* adding {@code entry} to relevant eviction lists.
*/
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
void recordWrite(ReferenceEntry<K, V> entry) {
// we are already under lock, so drain the recency queue immediately
drainRecencyQueue();
@@ -2283,9 +2291,8 @@ class MapMakerInternalMap<K, V>
if (map.expires()) {
// currently MapMaker ensures that expireAfterWrite and
// expireAfterAccess are mutually exclusive
- long expiration = map.expiresAfterAccess()
- ? map.expireAfterAccessNanos
- : map.expireAfterWriteNanos;
+ long expiration =
+ map.expiresAfterAccess() ? map.expireAfterAccessNanos : map.expireAfterWriteNanos;
recordExpirationTime(entry, expiration);
expirationQueue.add(entry);
}
@@ -2297,7 +2304,7 @@ class MapMakerInternalMap<K, V>
* lists (accounting for the fact that they could have been removed from the map since being
* added to the recency queue).
*/
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
void drainRecencyQueue() {
ReferenceEntry<K, V> e;
while ((e = recencyQueue.poll()) != null) {
@@ -2335,7 +2342,7 @@ class MapMakerInternalMap<K, V>
}
}
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
void expireEntries() {
drainRecencyQueue();
@@ -2372,7 +2379,7 @@ class MapMakerInternalMap<K, V>
*
* @return {@code true} if eviction occurred
*/
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
boolean evictEntries() {
if (map.evictsBySize() && count >= maxSegmentSize) {
drainRecencyQueue();
@@ -2512,7 +2519,8 @@ class MapMakerInternalMap<K, V>
// Look for an existing entry.
for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
K entryKey = e.getKey();
- if (e.getHash() == hash && entryKey != null
+ if (e.getHash() == hash
+ && entryKey != null
&& map.keyEquivalence.equivalent(key, entryKey)) {
// We found an existing entry.
@@ -2565,7 +2573,7 @@ class MapMakerInternalMap<K, V>
/**
* Expands the table if possible.
*/
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
void expand() {
AtomicReferenceArray<ReferenceEntry<K, V>> oldTable = table;
int oldCapacity = oldTable.length();
@@ -2645,7 +2653,8 @@ class MapMakerInternalMap<K, V>
for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
K entryKey = e.getKey();
- if (e.getHash() == hash && entryKey != null
+ if (e.getHash() == hash
+ && entryKey != null
&& map.keyEquivalence.equivalent(key, entryKey)) {
// If the value disappeared, this entry is partially collected,
// and we should pretend like it doesn't exist.
@@ -2696,7 +2705,8 @@ class MapMakerInternalMap<K, V>
for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
K entryKey = e.getKey();
- if (e.getHash() == hash && entryKey != null
+ if (e.getHash() == hash
+ && entryKey != null
&& map.keyEquivalence.equivalent(key, entryKey)) {
// If the value disappeared, this entry is partially collected,
// and we should pretend like it doesn't exist.
@@ -2741,7 +2751,8 @@ class MapMakerInternalMap<K, V>
for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
K entryKey = e.getKey();
- if (e.getHash() == hash && entryKey != null
+ if (e.getHash() == hash
+ && entryKey != null
&& map.keyEquivalence.equivalent(key, entryKey)) {
ValueReference<K, V> valueReference = e.getValueReference();
V entryValue = valueReference.get();
@@ -2784,7 +2795,8 @@ class MapMakerInternalMap<K, V>
for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
K entryKey = e.getKey();
- if (e.getHash() == hash && entryKey != null
+ if (e.getHash() == hash
+ && entryKey != null
&& map.keyEquivalence.equivalent(key, entryKey)) {
ValueReference<K, V> valueReference = e.getValueReference();
V entryValue = valueReference.get();
@@ -2859,7 +2871,7 @@ class MapMakerInternalMap<K, V>
* @param entry the entry being removed from the table
* @return the new first entry for the table
*/
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
ReferenceEntry<K, V> removeFromChain(ReferenceEntry<K, V> first, ReferenceEntry<K, V> entry) {
evictionQueue.remove(entry);
expirationQueue.remove(entry);
@@ -2929,7 +2941,8 @@ class MapMakerInternalMap<K, V>
for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
K entryKey = e.getKey();
- if (e.getHash() == hash && entryKey != null
+ if (e.getHash() == hash
+ && entryKey != null
&& map.keyEquivalence.equivalent(key, entryKey)) {
ValueReference<K, V> v = e.getValueReference();
if (v == valueReference) {
@@ -2966,7 +2979,8 @@ class MapMakerInternalMap<K, V>
for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
K entryKey = e.getKey();
- if (e.getHash() == hash && entryKey != null
+ if (e.getHash() == hash
+ && entryKey != null
&& map.keyEquivalence.equivalent(key, entryKey)) {
ValueReference<K, V> v = e.getValueReference();
if (v == valueReference) {
@@ -2985,7 +2999,7 @@ class MapMakerInternalMap<K, V>
}
}
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
boolean removeEntry(ReferenceEntry<K, V> entry, int hash, RemovalCause cause) {
int newCount = this.count - 1;
AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
@@ -3057,7 +3071,7 @@ class MapMakerInternalMap<K, V>
*
* <p>Post-condition: expireEntries has been run.
*/
- @GuardedBy("Segment.this")
+ @GuardedBy("this")
void preWriteCleanup() {
runLockedCleanup();
}
@@ -3092,7 +3106,6 @@ class MapMakerInternalMap<K, V>
map.processPendingNotifications();
}
}
-
}
// Queues
@@ -3109,32 +3122,33 @@ class MapMakerInternalMap<K, V>
* for the current model.
*/
static final class EvictionQueue<K, V> extends AbstractQueue<ReferenceEntry<K, V>> {
- final ReferenceEntry<K, V> head = new AbstractReferenceEntry<K, V>() {
+ final ReferenceEntry<K, V> head =
+ new AbstractReferenceEntry<K, V>() {
- ReferenceEntry<K, V> nextEvictable = this;
+ ReferenceEntry<K, V> nextEvictable = this;
- @Override
- public ReferenceEntry<K, V> getNextEvictable() {
- return nextEvictable;
- }
+ @Override
+ public ReferenceEntry<K, V> getNextEvictable() {
+ return nextEvictable;
+ }
- @Override
- public void setNextEvictable(ReferenceEntry<K, V> next) {
- this.nextEvictable = next;
- }
+ @Override
+ public void setNextEvictable(ReferenceEntry<K, V> next) {
+ this.nextEvictable = next;
+ }
- ReferenceEntry<K, V> previousEvictable = this;
+ ReferenceEntry<K, V> previousEvictable = this;
- @Override
- public ReferenceEntry<K, V> getPreviousEvictable() {
- return previousEvictable;
- }
+ @Override
+ public ReferenceEntry<K, V> getPreviousEvictable() {
+ return previousEvictable;
+ }
- @Override
- public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
- this.previousEvictable = previous;
- }
- };
+ @Override
+ public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
+ this.previousEvictable = previous;
+ }
+ };
// implements Queue
@@ -3237,40 +3251,41 @@ class MapMakerInternalMap<K, V>
* for the current model.
*/
static final class ExpirationQueue<K, V> extends AbstractQueue<ReferenceEntry<K, V>> {
- final ReferenceEntry<K, V> head = new AbstractReferenceEntry<K, V>() {
+ final ReferenceEntry<K, V> head =
+ new AbstractReferenceEntry<K, V>() {
- @Override
- public long getExpirationTime() {
- return Long.MAX_VALUE;
- }
+ @Override
+ public long getExpirationTime() {
+ return Long.MAX_VALUE;
+ }
- @Override
- public void setExpirationTime(long time) {}
+ @Override
+ public void setExpirationTime(long time) {}
- ReferenceEntry<K, V> nextExpirable = this;
+ ReferenceEntry<K, V> nextExpirable = this;
- @Override
- public ReferenceEntry<K, V> getNextExpirable() {
- return nextExpirable;
- }
+ @Override
+ public ReferenceEntry<K, V> getNextExpirable() {
+ return nextExpirable;
+ }
- @Override
- public void setNextExpirable(ReferenceEntry<K, V> next) {
- this.nextExpirable = next;
- }
+ @Override
+ public void setNextExpirable(ReferenceEntry<K, V> next) {
+ this.nextExpirable = next;
+ }
- ReferenceEntry<K, V> previousExpirable = this;
+ ReferenceEntry<K, V> previousExpirable = this;
- @Override
- public ReferenceEntry<K, V> getPreviousExpirable() {
- return previousExpirable;
- }
+ @Override
+ public ReferenceEntry<K, V> getPreviousExpirable() {
+ return previousExpirable;
+ }
- @Override
- public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
- this.previousExpirable = previous;
- }
- };
+ @Override
+ public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
+ this.previousExpirable = previous;
+ }
+ };
// implements Queue
@@ -3472,8 +3487,7 @@ class MapMakerInternalMap<K, V>
long sum = 0L;
for (Segment<K, V> segment : segments) {
// ensure visibility of most recent completed write
- @SuppressWarnings({"UnusedDeclaration", "unused"})
- int c = segment.count; // read-volatile
+ int unused = segment.count; // read-volatile
AtomicReferenceArray<ReferenceEntry<K, V>> table = segment.table;
for (int j = 0; j < table.length(); j++) {
@@ -3770,7 +3784,8 @@ class MapMakerInternalMap<K, V>
}
}
- final class KeySet extends AbstractSet<K> {
+ @WeakOuter
+ final class KeySet extends SafeToArraySet<K> {
@Override
public Iterator<K> iterator() {
@@ -3803,6 +3818,7 @@ class MapMakerInternalMap<K, V>
}
}
+ @WeakOuter
final class Values extends AbstractCollection<V> {
@Override
@@ -3829,9 +3845,23 @@ class MapMakerInternalMap<K, V>
public void clear() {
MapMakerInternalMap.this.clear();
}
+
+ // super.toArray() may misbehave if size() is inaccurate, at least on old versions of Android.
+ // https://code.google.com/p/android/issues/detail?id=36519 / http://r.android.com/47508
+
+ @Override
+ public Object[] toArray() {
+ return toArrayList(this).toArray();
+ }
+
+ @Override
+ public <E> E[] toArray(E[] a) {
+ return toArrayList(this).toArray(a);
+ }
}
- final class EntrySet extends AbstractSet<Entry<K, V>> {
+ @WeakOuter
+ final class EntrySet extends SafeToArraySet<Entry<K, V>> {
@Override
public Iterator<Entry<K, V>> iterator() {
@@ -3879,22 +3909,52 @@ class MapMakerInternalMap<K, V>
}
}
+ private abstract static class SafeToArraySet<E> extends AbstractSet<E> {
+ // super.toArray() may misbehave if size() is inaccurate, at least on old versions of Android.
+ // https://code.google.com/p/android/issues/detail?id=36519 / http://r.android.com/47508
+
+ @Override
+ public Object[] toArray() {
+ return toArrayList(this).toArray();
+ }
+
+ @Override
+ public <E> E[] toArray(E[] a) {
+ return toArrayList(this).toArray(a);
+ }
+ }
+
+ private static <E> ArrayList<E> toArrayList(Collection<E> c) {
+ // Avoid calling ArrayList(Collection), which may call back into toArray.
+ ArrayList<E> result = new ArrayList<E>(c.size());
+ Iterators.addAll(result, c.iterator());
+ return result;
+ }
+
// Serialization Support
private static final long serialVersionUID = 5;
Object writeReplace() {
- return new SerializationProxy<K, V>(keyStrength, valueStrength, keyEquivalence,
- valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maximumSize,
- concurrencyLevel, removalListener, this);
+ return new SerializationProxy<K, V>(
+ keyStrength,
+ valueStrength,
+ keyEquivalence,
+ valueEquivalence,
+ expireAfterWriteNanos,
+ expireAfterAccessNanos,
+ maximumSize,
+ concurrencyLevel,
+ removalListener,
+ this);
}
/**
* The actual object that gets serialized. Unfortunately, readResolve() doesn't get called when a
* circular dependency is present, so the proxy must be able to behave as the map itself.
*/
- abstract static class AbstractSerializationProxy<K, V>
- extends ForwardingConcurrentMap<K, V> implements Serializable {
+ abstract static class AbstractSerializationProxy<K, V> extends ForwardingConcurrentMap<K, V>
+ implements Serializable {
private static final long serialVersionUID = 3;
final Strength keyStrength;
@@ -3909,10 +3969,16 @@ class MapMakerInternalMap<K, V>
transient ConcurrentMap<K, V> delegate;
- AbstractSerializationProxy(Strength keyStrength, Strength valueStrength,
- Equivalence<Object> keyEquivalence, Equivalence<Object> valueEquivalence,
- long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize,
- int concurrencyLevel, RemovalListener<? super K, ? super V> removalListener,
+ AbstractSerializationProxy(
+ Strength keyStrength,
+ Strength valueStrength,
+ Equivalence<Object> keyEquivalence,
+ Equivalence<Object> valueEquivalence,
+ long expireAfterWriteNanos,
+ long expireAfterAccessNanos,
+ int maximumSize,
+ int concurrencyLevel,
+ RemovalListener<? super K, ? super V> removalListener,
ConcurrentMap<K, V> delegate) {
this.keyStrength = keyStrength;
this.valueStrength = valueStrength;
@@ -3943,12 +4009,13 @@ class MapMakerInternalMap<K, V>
@SuppressWarnings("deprecation") // serialization of deprecated feature
MapMaker readMapMaker(ObjectInputStream in) throws IOException {
int size = in.readInt();
- MapMaker mapMaker = new MapMaker()
- .initialCapacity(size)
- .setKeyStrength(keyStrength)
- .setValueStrength(valueStrength)
- .keyEquivalence(keyEquivalence)
- .concurrencyLevel(concurrencyLevel);
+ MapMaker mapMaker =
+ new MapMaker()
+ .initialCapacity(size)
+ .setKeyStrength(keyStrength)
+ .setValueStrength(valueStrength)
+ .keyEquivalence(keyEquivalence)
+ .concurrencyLevel(concurrencyLevel);
mapMaker.removalListener(removalListener);
if (expireAfterWriteNanos > 0) {
mapMaker.expireAfterWrite(expireAfterWriteNanos, TimeUnit.NANOSECONDS);
@@ -3982,13 +4049,28 @@ class MapMakerInternalMap<K, V>
private static final class SerializationProxy<K, V> extends AbstractSerializationProxy<K, V> {
private static final long serialVersionUID = 3;
- SerializationProxy(Strength keyStrength, Strength valueStrength,
- Equivalence<Object> keyEquivalence, Equivalence<Object> valueEquivalence,
- long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize,
- int concurrencyLevel, RemovalListener<? super K, ? super V> removalListener,
+ SerializationProxy(
+ Strength keyStrength,
+ Strength valueStrength,
+ Equivalence<Object> keyEquivalence,
+ Equivalence<Object> valueEquivalence,
+ long expireAfterWriteNanos,
+ long expireAfterAccessNanos,
+ int maximumSize,
+ int concurrencyLevel,
+ RemovalListener<? super K, ? super V> removalListener,
ConcurrentMap<K, V> delegate) {
- super(keyStrength, valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos,
- expireAfterAccessNanos, maximumSize, concurrencyLevel, removalListener, delegate);
+ super(
+ keyStrength,
+ valueStrength,
+ keyEquivalence,
+ valueEquivalence,
+ expireAfterWriteNanos,
+ expireAfterAccessNanos,
+ maximumSize,
+ concurrencyLevel,
+ removalListener,
+ delegate);
}
private void writeObject(ObjectOutputStream out) throws IOException {
diff --git a/guava/src/com/google/common/collect/Maps.java b/guava/src/com/google/common/collect/Maps.java
index e8ab643..3cd4558 100644
--- a/guava/src/com/google/common/collect/Maps.java
+++ b/guava/src/com/google/common/collect/Maps.java
@@ -37,6 +37,8 @@ import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.MapDifference.ValueDifference;
import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.AbstractCollection;
@@ -61,6 +63,7 @@ import java.util.SortedSet;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentMap;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -69,14 +72,14 @@ import javax.annotation.Nullable;
* {@link Lists}, {@link Sets} and {@link Queues}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Maps">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#maps">
* {@code Maps}</a>.
*
* @author Kevin Bourrillion
* @author Mike Bostock
* @author Isaac Shum
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Maps {
@@ -117,21 +120,6 @@ public final class Maps {
return Iterators.transform(entryIterator, Maps.<V>valueFunction());
}
- static <K, V> UnmodifiableIterator<V> valueIterator(
- final UnmodifiableIterator<Entry<K, V>> entryIterator) {
- return new UnmodifiableIterator<V>() {
- @Override
- public boolean hasNext() {
- return entryIterator.hasNext();
- }
-
- @Override
- public V next() {
- return entryIterator.next().getValue();
- }
- };
- }
-
/**
* Returns an immutable map instance containing the given entries.
* Internally, the returned map will be backed by an {@link EnumMap}.
@@ -181,17 +169,16 @@ public final class Maps {
* Creates a {@code HashMap} instance, with a high enough "initial capacity"
* that it <i>should</i> hold {@code expectedSize} elements without growth.
* This behavior cannot be broadly guaranteed, but it is observed to be true
- * for OpenJDK 1.6. It also can't be guaranteed that the method isn't
+ * for OpenJDK 1.7. It also can't be guaranteed that the method isn't
* inadvertently <i>oversizing</i> the returned map.
*
- * @param expectedSize the number of elements you expect to add to the
+ * @param expectedSize the number of entries you expect to add to the
* returned map
* @return a new, empty {@code HashMap} with enough capacity to hold {@code
- * expectedSize} elements without resizing
+ * expectedSize} entries without resizing
* @throws IllegalArgumentException if {@code expectedSize} is negative
*/
- public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(
- int expectedSize) {
+ public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(int expectedSize) {
return new HashMap<K, V>(capacity(expectedSize));
}
@@ -206,7 +193,10 @@ public final class Maps {
return expectedSize + 1;
}
if (expectedSize < Ints.MAX_POWER_OF_TWO) {
- return expectedSize + expectedSize / 3;
+ // This is the calculation used in JDK8 to resize when a putAll
+ // happens; it seems to be the most conservative calculation we
+ // can make. 0.75 is the default load factor.
+ return (int) ((float) expectedSize / 0.75F + 1.0F);
}
return Integer.MAX_VALUE; // any large value
}
@@ -225,8 +215,7 @@ public final class Maps {
* @return a new {@code HashMap} initialized with the mappings from {@code
* map}
*/
- public static <K, V> HashMap<K, V> newHashMap(
- Map<? extends K, ? extends V> map) {
+ public static <K, V> HashMap<K, V> newHashMap(Map<? extends K, ? extends V> map) {
return new HashMap<K, V>(map);
}
@@ -244,6 +233,24 @@ public final class Maps {
}
/**
+ * Creates a {@code LinkedHashMap} instance, with a high enough
+ * "initial capacity" that it <i>should</i> hold {@code expectedSize}
+ * elements without growth. This behavior cannot be broadly guaranteed, but
+ * it is observed to be true for OpenJDK 1.7. It also can't be guaranteed
+ * that the method isn't inadvertently <i>oversizing</i> the returned map.
+ *
+ * @param expectedSize the number of entries you expect to add to the
+ * returned map
+ * @return a new, empty {@code LinkedHashMap} with enough capacity to hold
+ * {@code expectedSize} entries without resizing
+ * @throws IllegalArgumentException if {@code expectedSize} is negative
+ * @since 19.0
+ */
+ public static <K, V> LinkedHashMap<K, V> newLinkedHashMapWithExpectedSize(int expectedSize) {
+ return new LinkedHashMap<K, V>(capacity(expectedSize));
+ }
+
+ /**
* Creates a <i>mutable</i>, insertion-ordered {@code LinkedHashMap} instance
* with the same mappings as the specified map.
*
@@ -254,8 +261,7 @@ public final class Maps {
* @return a new, {@code LinkedHashMap} initialized with the mappings from
* {@code map}
*/
- public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(
- Map<? extends K, ? extends V> map) {
+ public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(Map<? extends K, ? extends V> map) {
return new LinkedHashMap<K, V>(map);
}
@@ -317,8 +323,7 @@ public final class Maps {
* @param comparator the comparator to sort the keys with
* @return a new, empty {@code TreeMap}
*/
- public static <C, K extends C, V> TreeMap<K, V> newTreeMap(
- @Nullable Comparator<C> comparator) {
+ public static <C, K extends C, V> TreeMap<K, V> newTreeMap(@Nullable Comparator<C> comparator) {
// Ideally, the extra type parameter "C" shouldn't be necessary. It is a
// work-around of a compiler type inference quirk that prevents the
// following code from being compiled:
@@ -346,8 +351,7 @@ public final class Maps {
* @throws IllegalArgumentException if {@code m} is not an {@code EnumMap}
* instance and contains no mappings
*/
- public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(
- Map<K, ? extends V> map) {
+ public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(Map<K, ? extends V> map) {
return new EnumMap<K, V>(map);
}
@@ -408,22 +412,26 @@ public final class Maps {
*/
@Beta
public static <K, V> MapDifference<K, V> difference(
- Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right,
+ Map<? extends K, ? extends V> left,
+ Map<? extends K, ? extends V> right,
Equivalence<? super V> valueEquivalence) {
Preconditions.checkNotNull(valueEquivalence);
- Map<K, V> onlyOnLeft = newHashMap();
- Map<K, V> onlyOnRight = new HashMap<K, V>(right); // will whittle it down
- Map<K, V> onBoth = newHashMap();
- Map<K, MapDifference.ValueDifference<V>> differences = newHashMap();
+ Map<K, V> onlyOnLeft = newLinkedHashMap();
+ Map<K, V> onlyOnRight = new LinkedHashMap<K, V>(right); // will whittle it down
+ Map<K, V> onBoth = newLinkedHashMap();
+ Map<K, MapDifference.ValueDifference<V>> differences = newLinkedHashMap();
doDifference(left, right, valueEquivalence, onlyOnLeft, onlyOnRight, onBoth, differences);
return new MapDifferenceImpl<K, V>(onlyOnLeft, onlyOnRight, onBoth, differences);
}
private static <K, V> void doDifference(
- Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right,
+ Map<? extends K, ? extends V> left,
+ Map<? extends K, ? extends V> right,
Equivalence<? super V> valueEquivalence,
- Map<K, V> onlyOnLeft, Map<K, V> onlyOnRight, Map<K, V> onBoth,
+ Map<K, V> onlyOnLeft,
+ Map<K, V> onlyOnRight,
+ Map<K, V> onBoth,
Map<K, MapDifference.ValueDifference<V>> differences) {
for (Entry<? extends K, ? extends V> entry : left.entrySet()) {
K leftKey = entry.getKey();
@@ -433,8 +441,7 @@ public final class Maps {
if (valueEquivalence.equivalent(leftValue, rightValue)) {
onBoth.put(leftKey, leftValue);
} else {
- differences.put(
- leftKey, ValueDifferenceImpl.create(leftValue, rightValue));
+ differences.put(leftKey, ValueDifferenceImpl.create(leftValue, rightValue));
}
} else {
onlyOnLeft.put(leftKey, leftValue);
@@ -456,8 +463,10 @@ public final class Maps {
final Map<K, V> onBoth;
final Map<K, ValueDifference<V>> differences;
- MapDifferenceImpl(Map<K, V> onlyOnLeft,
- Map<K, V> onlyOnRight, Map<K, V> onBoth,
+ MapDifferenceImpl(
+ Map<K, V> onlyOnLeft,
+ Map<K, V> onlyOnRight,
+ Map<K, V> onBoth,
Map<K, ValueDifference<V>> differences) {
this.onlyOnLeft = unmodifiableMap(onlyOnLeft);
this.onlyOnRight = unmodifiableMap(onlyOnRight);
@@ -490,7 +499,8 @@ public final class Maps {
return differences;
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(Object object) {
if (object == this) {
return true;
}
@@ -504,12 +514,14 @@ public final class Maps {
return false;
}
- @Override public int hashCode() {
- return Objects.hashCode(entriesOnlyOnLeft(), entriesOnlyOnRight(),
- entriesInCommon(), entriesDiffering());
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(
+ entriesOnlyOnLeft(), entriesOnlyOnRight(), entriesInCommon(), entriesDiffering());
}
- @Override public String toString() {
+ @Override
+ public String toString() {
if (areEqual()) {
return "equal";
}
@@ -528,8 +540,7 @@ public final class Maps {
}
}
- static class ValueDifferenceImpl<V>
- implements MapDifference.ValueDifference<V> {
+ static class ValueDifferenceImpl<V> implements MapDifference.ValueDifference<V> {
private final V left;
private final V right;
@@ -552,21 +563,23 @@ public final class Maps {
return right;
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object instanceof MapDifference.ValueDifference) {
- MapDifference.ValueDifference<?> that =
- (MapDifference.ValueDifference<?>) object;
+ MapDifference.ValueDifference<?> that = (MapDifference.ValueDifference<?>) object;
return Objects.equal(this.left, that.leftValue())
&& Objects.equal(this.right, that.rightValue());
}
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Objects.hashCode(left, right);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "(" + left + ", " + right + ")";
}
}
@@ -599,33 +612,38 @@ public final class Maps {
SortedMap<K, V> onlyOnRight = Maps.newTreeMap(comparator);
onlyOnRight.putAll(right); // will whittle it down
SortedMap<K, V> onBoth = Maps.newTreeMap(comparator);
- SortedMap<K, MapDifference.ValueDifference<V>> differences =
- Maps.newTreeMap(comparator);
+ SortedMap<K, MapDifference.ValueDifference<V>> differences = Maps.newTreeMap(comparator);
doDifference(left, right, Equivalence.equals(), onlyOnLeft, onlyOnRight, onBoth, differences);
return new SortedMapDifferenceImpl<K, V>(onlyOnLeft, onlyOnRight, onBoth, differences);
}
static class SortedMapDifferenceImpl<K, V> extends MapDifferenceImpl<K, V>
implements SortedMapDifference<K, V> {
- SortedMapDifferenceImpl(SortedMap<K, V> onlyOnLeft,
- SortedMap<K, V> onlyOnRight, SortedMap<K, V> onBoth,
+ SortedMapDifferenceImpl(
+ SortedMap<K, V> onlyOnLeft,
+ SortedMap<K, V> onlyOnRight,
+ SortedMap<K, V> onBoth,
SortedMap<K, ValueDifference<V>> differences) {
super(onlyOnLeft, onlyOnRight, onBoth, differences);
}
- @Override public SortedMap<K, ValueDifference<V>> entriesDiffering() {
+ @Override
+ public SortedMap<K, ValueDifference<V>> entriesDiffering() {
return (SortedMap<K, ValueDifference<V>>) super.entriesDiffering();
}
- @Override public SortedMap<K, V> entriesInCommon() {
+ @Override
+ public SortedMap<K, V> entriesInCommon() {
return (SortedMap<K, V>) super.entriesInCommon();
}
- @Override public SortedMap<K, V> entriesOnlyOnLeft() {
+ @Override
+ public SortedMap<K, V> entriesOnlyOnLeft() {
return (SortedMap<K, V>) super.entriesOnlyOnLeft();
}
- @Override public SortedMap<K, V> entriesOnlyOnRight() {
+ @Override
+ public SortedMap<K, V> entriesOnlyOnRight() {
return (SortedMap<K, V>) super.entriesOnlyOnRight();
}
}
@@ -636,8 +654,7 @@ public final class Maps {
* purpose of this method is to contain the ugly type-casting in one place.
*/
@SuppressWarnings("unchecked")
- static <E> Comparator<? super E> orNaturalOrder(
- @Nullable Comparator<? super E> comparator) {
+ static <E> Comparator<? super E> orNaturalOrder(@Nullable Comparator<? super E> comparator) {
if (comparator != null) { // can't use ? : because of javac bug 5080917
return comparator;
}
@@ -671,9 +688,7 @@ public final class Maps {
*
* @since 14.0
*/
- @Beta
- public static <K, V> Map<K, V> asMap(
- Set<K> set, Function<? super K, V> function) {
+ public static <K, V> Map<K, V> asMap(Set<K> set, Function<? super K, V> function) {
if (set instanceof SortedSet) {
return asMap((SortedSet<K>) set, function);
} else {
@@ -707,14 +722,12 @@ public final class Maps {
*
* @since 14.0
*/
- @Beta
- public static <K, V> SortedMap<K, V> asMap(
- SortedSet<K> set, Function<? super K, V> function) {
+ public static <K, V> SortedMap<K, V> asMap(SortedSet<K> set, Function<? super K, V> function) {
return Platform.mapsAsMapSortedSet(set, function);
}
- static <K, V> SortedMap<K, V> asMapSortedIgnoreNavigable(SortedSet<K> set,
- Function<? super K, V> function) {
+ static <K, V> SortedMap<K, V> asMapSortedIgnoreNavigable(
+ SortedSet<K> set, Function<? super K, V> function) {
return new SortedAsMapView<K, V>(set, function);
}
@@ -744,14 +757,13 @@ public final class Maps {
*
* @since 14.0
*/
- @Beta
@GwtIncompatible("NavigableMap")
public static <K, V> NavigableMap<K, V> asMap(
NavigableSet<K> set, Function<? super K, V> function) {
return new NavigableAsMapView<K, V>(set, function);
}
- private static class AsMapView<K, V> extends ImprovedAbstractMap<K, V> {
+ private static class AsMapView<K, V> extends ViewCachingAbstractMap<K, V> {
private final Set<K> set;
final Function<? super K, V> function;
@@ -814,7 +826,8 @@ public final class Maps {
@Override
protected Set<Entry<K, V>> createEntrySet() {
- return new EntrySet<K, V>() {
+ @WeakOuter
+ class EntrySetImpl extends EntrySet<K, V> {
@Override
Map<K, V> map() {
return AsMapView.this;
@@ -824,13 +837,14 @@ public final class Maps {
public Iterator<Entry<K, V>> iterator() {
return asMapEntryIterator(backingSet(), function);
}
- };
+ }
+ return new EntrySetImpl();
}
}
static <K, V> Iterator<Entry<K, V>> asMapEntryIterator(
Set<K> set, final Function<? super K, V> function) {
- return new TransformedIterator<K, Entry<K,V>>(set.iterator()) {
+ return new TransformedIterator<K, Entry<K, V>>(set.iterator()) {
@Override
Entry<K, V> transform(final K key) {
return immutableEntry(key, function.apply(key));
@@ -838,8 +852,7 @@ public final class Maps {
};
}
- private static class SortedAsMapView<K, V> extends AsMapView<K, V>
- implements SortedMap<K, V> {
+ private static class SortedAsMapView<K, V> extends AsMapView<K, V> implements SortedMap<K, V> {
SortedAsMapView(SortedSet<K> set, Function<? super K, V> function) {
super(set, function);
@@ -887,8 +900,7 @@ public final class Maps {
}
@GwtIncompatible("NavigableMap")
- private static final class NavigableAsMapView<K, V>
- extends AbstractNavigableMap<K, V> {
+ private static final class NavigableAsMapView<K, V> extends AbstractNavigableMap<K, V> {
/*
* Using AbstractNavigableMap is simpler than extending SortedAsMapView and rewriting all the
* NavigableMap methods.
@@ -1044,8 +1056,7 @@ public final class Maps {
@Override
public SortedSet<E> subSet(E fromElement, E toElement) {
- return removeOnlySortedSet(
- super.subSet(fromElement, toElement));
+ return removeOnlySortedSet(super.subSet(fromElement, toElement));
}
@Override
@@ -1064,10 +1075,10 @@ public final class Maps {
}
@Override
- public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
- E toElement, boolean toInclusive) {
- return removeOnlyNavigableSet(super.subSet(
- fromElement, fromInclusive, toElement, toInclusive));
+ public NavigableSet<E> subSet(
+ E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+ return removeOnlyNavigableSet(
+ super.subSet(fromElement, fromInclusive, toElement, toInclusive));
}
@Override
@@ -1083,6 +1094,11 @@ public final class Maps {
* The map's iteration order is the order of the first appearance of each key
* in {@code keys}.
*
+ * <p>When there are multiple instances of a key in {@code keys}, it is
+ * unspecified whether {@code valueFunction} will be applied to more than one
+ * instance of that key and, if it is, which result will be mapped to that
+ * key in the returned map.
+ *
* <p>If {@code keys} is a {@link Set}, a live view can be obtained instead of
* a copy using {@link Maps#asMap(Set, Function)}.
*
@@ -1091,9 +1107,8 @@ public final class Maps {
* for any key
* @since 14.0
*/
- @Beta
- public static <K, V> ImmutableMap<K, V> toMap(Iterable<K> keys,
- Function<? super K, V> valueFunction) {
+ public static <K, V> ImmutableMap<K, V> toMap(
+ Iterable<K> keys, Function<? super K, V> valueFunction) {
return toMap(keys.iterator(), valueFunction);
}
@@ -1103,14 +1118,18 @@ public final class Maps {
* The map's iteration order is the order of the first appearance of each key
* in {@code keys}.
*
+ * <p>When there are multiple instances of a key in {@code keys}, it is
+ * unspecified whether {@code valueFunction} will be applied to more than one
+ * instance of that key and, if it is, which result will be mapped to that
+ * key in the returned map.
+ *
* @throws NullPointerException if any element of {@code keys} is
* {@code null}, or if {@code valueFunction} produces {@code null}
* for any key
* @since 14.0
*/
- @Beta
- public static <K, V> ImmutableMap<K, V> toMap(Iterator<K> keys,
- Function<? super K, V> valueFunction) {
+ public static <K, V> ImmutableMap<K, V> toMap(
+ Iterator<K> keys, Function<? super K, V> valueFunction) {
checkNotNull(valueFunction);
// Using LHM instead of a builder so as not to fail on duplicate keys
Map<K, V> builder = newLinkedHashMap();
@@ -1122,9 +1141,22 @@ public final class Maps {
}
/**
- * Returns an immutable map for which the {@link Map#values} are the given
- * elements in the given order, and each key is the product of invoking a
- * supplied function on its corresponding value.
+ * Returns a map with the given {@code values}, indexed by keys derived from
+ * those values. In other words, each input value produces an entry in the map
+ * whose key is the result of applying {@code keyFunction} to that value.
+ * These entries appear in the same order as the input values. Example usage:
+ * <pre> {@code
+ *
+ * Color red = new Color("red", 255, 0, 0);
+ * ...
+ * ImmutableSet<Color> allColors = ImmutableSet.of(red, green, blue);
+ *
+ * Map<String, Color> colorForName =
+ * uniqueIndex(allColors, toStringFunction());
+ * assertThat(colorForName).containsEntry("red", red);}</pre>
+ *
+ * <p>If your index may associate multiple values with each key, use {@link
+ * Multimaps#index(Iterable, Function) Multimaps.index}.
*
* @param values the values to use when constructing the {@code Map}
* @param keyFunction the function used to produce the key for each value
@@ -1137,13 +1169,27 @@ public final class Maps {
*/
public static <K, V> ImmutableMap<K, V> uniqueIndex(
Iterable<V> values, Function<? super V, K> keyFunction) {
+ // TODO(lowasser): consider presizing the builder if values is a Collection
return uniqueIndex(values.iterator(), keyFunction);
}
/**
- * Returns an immutable map for which the {@link Map#values} are the given
- * elements in the given order, and each key is the product of invoking a
- * supplied function on its corresponding value.
+ * Returns a map with the given {@code values}, indexed by keys derived from
+ * those values. In other words, each input value produces an entry in the map
+ * whose key is the result of applying {@code keyFunction} to that value.
+ * These entries appear in the same order as the input values. Example usage:
+ * <pre> {@code
+ *
+ * Color red = new Color("red", 255, 0, 0);
+ * ...
+ * Iterator<Color> allColors = ImmutableSet.of(red, green, blue).iterator();
+ *
+ * Map<String, Color> colorForName =
+ * uniqueIndex(allColors, toStringFunction());
+ * assertThat(colorForName).containsEntry("red", red);}</pre>
+ *
+ * <p>If your index may associate multiple values with each key, use {@link
+ * Multimaps#index(Iterator, Function) Multimaps.index}.
*
* @param values the values to use when constructing the {@code Map}
* @param keyFunction the function used to produce the key for each value
@@ -1163,7 +1209,13 @@ public final class Maps {
V value = values.next();
builder.put(keyFunction.apply(value), value);
}
- return builder.build();
+ try {
+ return builder.build();
+ } catch (IllegalArgumentException duplicateKeys) {
+ throw new IllegalArgumentException(
+ duplicateKeys.getMessage()
+ + ". To index multiple values under a key, use Multimaps.index.");
+ }
}
/**
@@ -1180,11 +1232,10 @@ public final class Maps {
* null
*/
@GwtIncompatible("java.util.Properties")
- public static ImmutableMap<String, String> fromProperties(
- Properties properties) {
+ public static ImmutableMap<String, String> fromProperties(Properties properties) {
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
- for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements();) {
+ for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements(); ) {
String key = (String) e.nextElement();
builder.put(key, properties.getProperty(key));
}
@@ -1202,8 +1253,7 @@ public final class Maps {
* @param value the value to be associated with the returned entry
*/
@GwtCompatible(serializable = true)
- public static <K, V> Entry<K, V> immutableEntry(
- @Nullable K key, @Nullable V value) {
+ public static <K, V> Entry<K, V> immutableEntry(@Nullable K key, @Nullable V value) {
return new ImmutableEntry<K, V>(key, value);
}
@@ -1215,10 +1265,8 @@ public final class Maps {
* @param entrySet the entries for which to return an unmodifiable view
* @return an unmodifiable view of the entries
*/
- static <K, V> Set<Entry<K, V>> unmodifiableEntrySet(
- Set<Entry<K, V>> entrySet) {
- return new UnmodifiableEntrySet<K, V>(
- Collections.unmodifiableSet(entrySet));
+ static <K, V> Set<Entry<K, V>> unmodifiableEntrySet(Set<Entry<K, V>> entrySet) {
+ return new UnmodifiableEntrySet<K, V>(Collections.unmodifiableSet(entrySet));
}
/**
@@ -1233,68 +1281,80 @@ public final class Maps {
static <K, V> Entry<K, V> unmodifiableEntry(final Entry<? extends K, ? extends V> entry) {
checkNotNull(entry);
return new AbstractMapEntry<K, V>() {
- @Override public K getKey() {
+ @Override
+ public K getKey() {
return entry.getKey();
}
- @Override public V getValue() {
+ @Override
+ public V getValue() {
return entry.getValue();
}
};
}
+ static <K, V> UnmodifiableIterator<Entry<K, V>> unmodifiableEntryIterator(
+ final Iterator<Entry<K, V>> entryIterator) {
+ return new UnmodifiableIterator<Entry<K, V>>() {
+ @Override
+ public boolean hasNext() {
+ return entryIterator.hasNext();
+ }
+
+ @Override
+ public Entry<K, V> next() {
+ return unmodifiableEntry(entryIterator.next());
+ }
+ };
+ }
+
/** @see Multimaps#unmodifiableEntries */
- static class UnmodifiableEntries<K, V>
- extends ForwardingCollection<Entry<K, V>> {
+ static class UnmodifiableEntries<K, V> extends ForwardingCollection<Entry<K, V>> {
private final Collection<Entry<K, V>> entries;
UnmodifiableEntries(Collection<Entry<K, V>> entries) {
this.entries = entries;
}
- @Override protected Collection<Entry<K, V>> delegate() {
+ @Override
+ protected Collection<Entry<K, V>> delegate() {
return entries;
}
- @Override public Iterator<Entry<K, V>> iterator() {
- final Iterator<Entry<K, V>> delegate = super.iterator();
- return new UnmodifiableIterator<Entry<K, V>>() {
- @Override
- public boolean hasNext() {
- return delegate.hasNext();
- }
-
- @Override public Entry<K, V> next() {
- return unmodifiableEntry(delegate.next());
- }
- };
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return unmodifiableEntryIterator(entries.iterator());
}
// See java.util.Collections.UnmodifiableEntrySet for details on attacks.
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
return standardToArray();
}
- @Override public <T> T[] toArray(T[] array) {
+ @Override
+ public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
}
/** @see Maps#unmodifiableEntrySet(Set) */
- static class UnmodifiableEntrySet<K, V>
- extends UnmodifiableEntries<K, V> implements Set<Entry<K, V>> {
+ static class UnmodifiableEntrySet<K, V> extends UnmodifiableEntries<K, V>
+ implements Set<Entry<K, V>> {
UnmodifiableEntrySet(Set<Entry<K, V>> entries) {
super(entries);
}
// See java.util.Collections.UnmodifiableEntrySet for details on attacks.
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return Sets.equalsImpl(this, object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Sets.hashCodeImpl(this);
}
}
@@ -1406,27 +1466,26 @@ public final class Maps {
* @param bimap the bimap for which an unmodifiable view is to be returned
* @return an unmodifiable view of the specified bimap
*/
- public static <K, V> BiMap<K, V> unmodifiableBiMap(
- BiMap<? extends K, ? extends V> bimap) {
+ public static <K, V> BiMap<K, V> unmodifiableBiMap(BiMap<? extends K, ? extends V> bimap) {
return new UnmodifiableBiMap<K, V>(bimap, null);
}
/** @see Maps#unmodifiableBiMap(BiMap) */
- private static class UnmodifiableBiMap<K, V>
- extends ForwardingMap<K, V> implements BiMap<K, V>, Serializable {
+ private static class UnmodifiableBiMap<K, V> extends ForwardingMap<K, V>
+ implements BiMap<K, V>, Serializable {
final Map<K, V> unmodifiableMap;
final BiMap<? extends K, ? extends V> delegate;
BiMap<V, K> inverse;
transient Set<V> values;
- UnmodifiableBiMap(BiMap<? extends K, ? extends V> delegate,
- @Nullable BiMap<V, K> inverse) {
+ UnmodifiableBiMap(BiMap<? extends K, ? extends V> delegate, @Nullable BiMap<V, K> inverse) {
unmodifiableMap = Collections.unmodifiableMap(delegate);
this.delegate = delegate;
this.inverse = inverse;
}
- @Override protected Map<K, V> delegate() {
+ @Override
+ protected Map<K, V> delegate() {
return unmodifiableMap;
}
@@ -1443,7 +1502,8 @@ public final class Maps {
: result;
}
- @Override public Set<V> values() {
+ @Override
+ public Set<V> values() {
Set<V> result = values;
return (result == null)
? values = Collections.unmodifiableSet(delegate.values())
@@ -1637,8 +1697,7 @@ public final class Maps {
* @since 7.0
*/
public static <K, V1, V2> Map<K, V2> transformEntries(
- Map<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ Map<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
if (fromMap instanceof SortedMap) {
return transformEntries((SortedMap<K, V1>) fromMap, transformer);
}
@@ -1698,8 +1757,7 @@ public final class Maps {
* @since 11.0
*/
public static <K, V1, V2> SortedMap<K, V2> transformEntries(
- SortedMap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
return Platform.mapsTransformEntriesSortedMap(fromMap, transformer);
}
@@ -1758,14 +1816,12 @@ public final class Maps {
*/
@GwtIncompatible("NavigableMap")
public static <K, V1, V2> NavigableMap<K, V2> transformEntries(
- final NavigableMap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ NavigableMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
return new TransformedEntriesNavigableMap<K, V1, V2>(fromMap, transformer);
}
static <K, V1, V2> SortedMap<K, V2> transformEntriesIgnoreNavigable(
- SortedMap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
return new TransformedEntriesSortedMap<K, V1, V2>(fromMap, transformer);
}
@@ -1803,8 +1859,8 @@ public final class Maps {
/**
* Views a function as an entry transformer that ignores the entry key.
*/
- static <K, V1, V2> EntryTransformer<K, V1, V2>
- asEntryTransformer(final Function<? super V1, V2> function) {
+ static <K, V1, V2> EntryTransformer<K, V1, V2> asEntryTransformer(
+ final Function<? super V1, V2> function) {
checkNotNull(function);
return new EntryTransformer<K, V1, V2>() {
@Override
@@ -1873,29 +1929,30 @@ public final class Maps {
};
}
- static class TransformedEntriesMap<K, V1, V2>
- extends ImprovedAbstractMap<K, V2> {
+ static class TransformedEntriesMap<K, V1, V2> extends IteratorBasedAbstractMap<K, V2> {
final Map<K, V1> fromMap;
final EntryTransformer<? super K, ? super V1, V2> transformer;
TransformedEntriesMap(
- Map<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ Map<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
this.fromMap = checkNotNull(fromMap);
this.transformer = checkNotNull(transformer);
}
- @Override public int size() {
+ @Override
+ public int size() {
return fromMap.size();
}
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return fromMap.containsKey(key);
}
// safe as long as the user followed the <b>Warning</b> in the javadoc
@SuppressWarnings("unchecked")
- @Override public V2 get(Object key) {
+ @Override
+ public V2 get(Object key) {
V1 value = fromMap.get(key);
return (value != null || fromMap.containsKey(key))
? transformer.transformEntry((K) key, value)
@@ -1904,169 +1961,192 @@ public final class Maps {
// safe as long as the user followed the <b>Warning</b> in the javadoc
@SuppressWarnings("unchecked")
- @Override public V2 remove(Object key) {
+ @Override
+ public V2 remove(Object key) {
return fromMap.containsKey(key)
? transformer.transformEntry((K) key, fromMap.remove(key))
: null;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
fromMap.clear();
}
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
return fromMap.keySet();
}
@Override
- protected Set<Entry<K, V2>> createEntrySet() {
- return new EntrySet<K, V2>() {
- @Override Map<K, V2> map() {
- return TransformedEntriesMap.this;
- }
+ Iterator<Entry<K, V2>> entryIterator() {
+ return Iterators.transform(
+ fromMap.entrySet().iterator(), Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
+ }
- @Override public Iterator<Entry<K, V2>> iterator() {
- return Iterators.transform(fromMap.entrySet().iterator(),
- Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
- }
- };
+ @Override
+ public Collection<V2> values() {
+ return new Values<K, V2>(this);
}
}
- static class TransformedEntriesSortedMap<K, V1, V2>
- extends TransformedEntriesMap<K, V1, V2> implements SortedMap<K, V2> {
+ static class TransformedEntriesSortedMap<K, V1, V2> extends TransformedEntriesMap<K, V1, V2>
+ implements SortedMap<K, V2> {
protected SortedMap<K, V1> fromMap() {
return (SortedMap<K, V1>) fromMap;
}
- TransformedEntriesSortedMap(SortedMap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ TransformedEntriesSortedMap(
+ SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
super(fromMap, transformer);
}
- @Override public Comparator<? super K> comparator() {
+ @Override
+ public Comparator<? super K> comparator() {
return fromMap().comparator();
}
- @Override public K firstKey() {
+ @Override
+ public K firstKey() {
return fromMap().firstKey();
}
- @Override public SortedMap<K, V2> headMap(K toKey) {
+ @Override
+ public SortedMap<K, V2> headMap(K toKey) {
return transformEntries(fromMap().headMap(toKey), transformer);
}
- @Override public K lastKey() {
+ @Override
+ public K lastKey() {
return fromMap().lastKey();
}
- @Override public SortedMap<K, V2> subMap(K fromKey, K toKey) {
- return transformEntries(
- fromMap().subMap(fromKey, toKey), transformer);
+ @Override
+ public SortedMap<K, V2> subMap(K fromKey, K toKey) {
+ return transformEntries(fromMap().subMap(fromKey, toKey), transformer);
}
- @Override public SortedMap<K, V2> tailMap(K fromKey) {
+ @Override
+ public SortedMap<K, V2> tailMap(K fromKey) {
return transformEntries(fromMap().tailMap(fromKey), transformer);
}
}
@GwtIncompatible("NavigableMap")
private static class TransformedEntriesNavigableMap<K, V1, V2>
- extends TransformedEntriesSortedMap<K, V1, V2>
- implements NavigableMap<K, V2> {
+ extends TransformedEntriesSortedMap<K, V1, V2> implements NavigableMap<K, V2> {
- TransformedEntriesNavigableMap(NavigableMap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ TransformedEntriesNavigableMap(
+ NavigableMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
super(fromMap, transformer);
}
- @Override public Entry<K, V2> ceilingEntry(K key) {
+ @Override
+ public Entry<K, V2> ceilingEntry(K key) {
return transformEntry(fromMap().ceilingEntry(key));
}
- @Override public K ceilingKey(K key) {
+ @Override
+ public K ceilingKey(K key) {
return fromMap().ceilingKey(key);
}
- @Override public NavigableSet<K> descendingKeySet() {
+ @Override
+ public NavigableSet<K> descendingKeySet() {
return fromMap().descendingKeySet();
}
- @Override public NavigableMap<K, V2> descendingMap() {
+ @Override
+ public NavigableMap<K, V2> descendingMap() {
return transformEntries(fromMap().descendingMap(), transformer);
}
- @Override public Entry<K, V2> firstEntry() {
+ @Override
+ public Entry<K, V2> firstEntry() {
return transformEntry(fromMap().firstEntry());
}
- @Override public Entry<K, V2> floorEntry(K key) {
+
+ @Override
+ public Entry<K, V2> floorEntry(K key) {
return transformEntry(fromMap().floorEntry(key));
}
- @Override public K floorKey(K key) {
+ @Override
+ public K floorKey(K key) {
return fromMap().floorKey(key);
}
- @Override public NavigableMap<K, V2> headMap(K toKey) {
+ @Override
+ public NavigableMap<K, V2> headMap(K toKey) {
return headMap(toKey, false);
}
- @Override public NavigableMap<K, V2> headMap(K toKey, boolean inclusive) {
- return transformEntries(
- fromMap().headMap(toKey, inclusive), transformer);
+ @Override
+ public NavigableMap<K, V2> headMap(K toKey, boolean inclusive) {
+ return transformEntries(fromMap().headMap(toKey, inclusive), transformer);
}
- @Override public Entry<K, V2> higherEntry(K key) {
+ @Override
+ public Entry<K, V2> higherEntry(K key) {
return transformEntry(fromMap().higherEntry(key));
}
- @Override public K higherKey(K key) {
+ @Override
+ public K higherKey(K key) {
return fromMap().higherKey(key);
}
- @Override public Entry<K, V2> lastEntry() {
+ @Override
+ public Entry<K, V2> lastEntry() {
return transformEntry(fromMap().lastEntry());
}
- @Override public Entry<K, V2> lowerEntry(K key) {
+ @Override
+ public Entry<K, V2> lowerEntry(K key) {
return transformEntry(fromMap().lowerEntry(key));
}
- @Override public K lowerKey(K key) {
+ @Override
+ public K lowerKey(K key) {
return fromMap().lowerKey(key);
}
- @Override public NavigableSet<K> navigableKeySet() {
+ @Override
+ public NavigableSet<K> navigableKeySet() {
return fromMap().navigableKeySet();
}
- @Override public Entry<K, V2> pollFirstEntry() {
+ @Override
+ public Entry<K, V2> pollFirstEntry() {
return transformEntry(fromMap().pollFirstEntry());
}
- @Override public Entry<K, V2> pollLastEntry() {
+ @Override
+ public Entry<K, V2> pollLastEntry() {
return transformEntry(fromMap().pollLastEntry());
}
- @Override public NavigableMap<K, V2> subMap(
+ @Override
+ public NavigableMap<K, V2> subMap(
K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
return transformEntries(
- fromMap().subMap(fromKey, fromInclusive, toKey, toInclusive),
- transformer);
+ fromMap().subMap(fromKey, fromInclusive, toKey, toInclusive), transformer);
}
- @Override public NavigableMap<K, V2> subMap(K fromKey, K toKey) {
+ @Override
+ public NavigableMap<K, V2> subMap(K fromKey, K toKey) {
return subMap(fromKey, true, toKey, false);
}
- @Override public NavigableMap<K, V2> tailMap(K fromKey) {
+ @Override
+ public NavigableMap<K, V2> tailMap(K fromKey) {
return tailMap(fromKey, true);
}
- @Override public NavigableMap<K, V2> tailMap(K fromKey, boolean inclusive) {
- return transformEntries(
- fromMap().tailMap(fromKey, inclusive), transformer);
+ @Override
+ public NavigableMap<K, V2> tailMap(K fromKey, boolean inclusive) {
+ return transformEntries(fromMap().tailMap(fromKey, inclusive), transformer);
}
@Nullable
@@ -2074,7 +2154,8 @@ public final class Maps {
return (entry == null) ? null : Maps.transformEntry(transformer, entry);
}
- @Override protected NavigableMap<K, V1> fromMap() {
+ @Override
+ protected NavigableMap<K, V1> fromMap() {
return (NavigableMap<K, V1>) super.fromMap();
}
}
@@ -2115,6 +2196,7 @@ public final class Maps {
* predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is
* inconsistent with equals.
*/
+ @CheckReturnValue
public static <K, V> Map<K, V> filterKeys(
Map<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
if (unfiltered instanceof SortedMap) {
@@ -2126,8 +2208,7 @@ public final class Maps {
Predicate<Entry<K, ?>> entryPredicate = keyPredicateOnEntries(keyPredicate);
return (unfiltered instanceof AbstractFilteredMap)
? filterFiltered((AbstractFilteredMap<K, V>) unfiltered, entryPredicate)
- : new FilteredKeyMap<K, V>(
- checkNotNull(unfiltered), keyPredicate, entryPredicate);
+ : new FilteredKeyMap<K, V>(checkNotNull(unfiltered), keyPredicate, entryPredicate);
}
/**
@@ -2160,9 +2241,10 @@ public final class Maps {
*
* @since 11.0
*/
+ @CheckReturnValue
public static <K, V> SortedMap<K, V> filterKeys(
SortedMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
- // TODO(user): Return a subclass of Maps.FilteredKeyMap for slightly better
+ // TODO(lowasser): Return a subclass of Maps.FilteredKeyMap for slightly better
// performance.
return filterEntries(unfiltered, Maps.<K>keyPredicateOnEntries(keyPredicate));
}
@@ -2198,9 +2280,10 @@ public final class Maps {
* @since 14.0
*/
@GwtIncompatible("NavigableMap")
+ @CheckReturnValue
public static <K, V> NavigableMap<K, V> filterKeys(
NavigableMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
- // TODO(user): Return a subclass of Maps.FilteredKeyMap for slightly better
+ // TODO(lowasser): Return a subclass of Maps.FilteredKeyMap for slightly better
// performance.
return filterEntries(unfiltered, Maps.<K>keyPredicateOnEntries(keyPredicate));
}
@@ -2230,6 +2313,7 @@ public final class Maps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> BiMap<K, V> filterKeys(
BiMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
checkNotNull(keyPredicate);
@@ -2265,6 +2349,7 @@ public final class Maps {
* predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is
* inconsistent with equals.
*/
+ @CheckReturnValue
public static <K, V> Map<K, V> filterValues(
Map<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
if (unfiltered instanceof SortedMap) {
@@ -2306,6 +2391,7 @@ public final class Maps {
*
* @since 11.0
*/
+ @CheckReturnValue
public static <K, V> SortedMap<K, V> filterValues(
SortedMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -2343,6 +2429,7 @@ public final class Maps {
* @since 14.0
*/
@GwtIncompatible("NavigableMap")
+ @CheckReturnValue
public static <K, V> NavigableMap<K, V> filterValues(
NavigableMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -2376,6 +2463,7 @@ public final class Maps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> BiMap<K, V> filterValues(
BiMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -2410,6 +2498,7 @@ public final class Maps {
* <p><b>Warning:</b> {@code entryPredicate} must be <i>consistent with
* equals</i>, as documented at {@link Predicate#apply}.
*/
+ @CheckReturnValue
public static <K, V> Map<K, V> filterEntries(
Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
if (unfiltered instanceof SortedMap) {
@@ -2454,15 +2543,14 @@ public final class Maps {
*
* @since 11.0
*/
+ @CheckReturnValue
public static <K, V> SortedMap<K, V> filterEntries(
- SortedMap<K, V> unfiltered,
- Predicate<? super Entry<K, V>> entryPredicate) {
+ SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
return Platform.mapsFilterSortedMap(unfiltered, entryPredicate);
}
static <K, V> SortedMap<K, V> filterSortedIgnoreNavigable(
- SortedMap<K, V> unfiltered,
- Predicate<? super Entry<K, V>> entryPredicate) {
+ SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
checkNotNull(entryPredicate);
return (unfiltered instanceof FilteredEntrySortedMap)
? filterFiltered((FilteredEntrySortedMap<K, V>) unfiltered, entryPredicate)
@@ -2501,9 +2589,9 @@ public final class Maps {
* @since 14.0
*/
@GwtIncompatible("NavigableMap")
+ @CheckReturnValue
public static <K, V> NavigableMap<K, V> filterEntries(
- NavigableMap<K, V> unfiltered,
- Predicate<? super Entry<K, V>> entryPredicate) {
+ NavigableMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
checkNotNull(entryPredicate);
return (unfiltered instanceof FilteredEntryNavigableMap)
? filterFiltered((FilteredEntryNavigableMap<K, V>) unfiltered, entryPredicate)
@@ -2537,6 +2625,7 @@ public final class Maps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> BiMap<K, V> filterEntries(
BiMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
checkNotNull(unfiltered);
@@ -2550,19 +2639,17 @@ public final class Maps {
* Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when
* filtering a filtered map.
*/
- private static <K, V> Map<K, V> filterFiltered(AbstractFilteredMap<K, V> map,
- Predicate<? super Entry<K, V>> entryPredicate) {
- return new FilteredEntryMap<K, V>(map.unfiltered,
- Predicates.<Entry<K, V>>and(map.predicate, entryPredicate));
+ private static <K, V> Map<K, V> filterFiltered(
+ AbstractFilteredMap<K, V> map, Predicate<? super Entry<K, V>> entryPredicate) {
+ return new FilteredEntryMap<K, V>(
+ map.unfiltered, Predicates.<Entry<K, V>>and(map.predicate, entryPredicate));
}
- private abstract static class AbstractFilteredMap<K, V>
- extends ImprovedAbstractMap<K, V> {
+ private abstract static class AbstractFilteredMap<K, V> extends ViewCachingAbstractMap<K, V> {
final Map<K, V> unfiltered;
final Predicate<? super Entry<K, V>> predicate;
- AbstractFilteredMap(
- Map<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
+ AbstractFilteredMap(Map<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
this.unfiltered = unfiltered;
this.predicate = predicate;
}
@@ -2575,32 +2662,38 @@ public final class Maps {
return predicate.apply(Maps.immutableEntry(k, value));
}
- @Override public V put(K key, V value) {
+ @Override
+ public V put(K key, V value) {
checkArgument(apply(key, value));
return unfiltered.put(key, value);
}
- @Override public void putAll(Map<? extends K, ? extends V> map) {
+ @Override
+ public void putAll(Map<? extends K, ? extends V> map) {
for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
checkArgument(apply(entry.getKey(), entry.getValue()));
}
unfiltered.putAll(map);
}
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return unfiltered.containsKey(key) && apply(key, unfiltered.get(key));
}
- @Override public V get(Object key) {
+ @Override
+ public V get(Object key) {
V value = unfiltered.get(key);
return ((value != null) && apply(key, value)) ? value : null;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return entrySet().isEmpty();
}
- @Override public V remove(Object key) {
+ @Override
+ public V remove(Object key) {
return containsKey(key) ? unfiltered.remove(key) : null;
}
@@ -2614,38 +2707,45 @@ public final class Maps {
Map<K, V> unfiltered;
Predicate<? super Entry<K, V>> predicate;
- FilteredMapValues(Map<K, V> filteredMap, Map<K, V> unfiltered,
- Predicate<? super Entry<K, V>> predicate) {
+ FilteredMapValues(
+ Map<K, V> filteredMap, Map<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
super(filteredMap);
this.unfiltered = unfiltered;
this.predicate = predicate;
}
- @Override public boolean remove(Object o) {
- return Iterables.removeFirstMatching(unfiltered.entrySet(),
- Predicates.<Entry<K, V>>and(predicate, Maps.<V>valuePredicateOnEntries(equalTo(o))))
+ @Override
+ public boolean remove(Object o) {
+ return Iterables.removeFirstMatching(
+ unfiltered.entrySet(),
+ Predicates.<Entry<K, V>>and(predicate, Maps.<V>valuePredicateOnEntries(equalTo(o))))
!= null;
}
private boolean removeIf(Predicate<? super V> valuePredicate) {
- return Iterables.removeIf(unfiltered.entrySet(), Predicates.<Entry<K, V>>and(
- predicate, Maps.<V>valuePredicateOnEntries(valuePredicate)));
+ return Iterables.removeIf(
+ unfiltered.entrySet(),
+ Predicates.<Entry<K, V>>and(predicate, Maps.<V>valuePredicateOnEntries(valuePredicate)));
}
- @Override public boolean removeAll(Collection<?> collection) {
+ @Override
+ public boolean removeAll(Collection<?> collection) {
return removeIf(in(collection));
}
- @Override public boolean retainAll(Collection<?> collection) {
+ @Override
+ public boolean retainAll(Collection<?> collection) {
return removeIf(not(in(collection)));
}
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
// creating an ArrayList so filtering happens once
return Lists.newArrayList(iterator()).toArray();
}
- @Override public <T> T[] toArray(T[] array) {
+ @Override
+ public <T> T[] toArray(T[] array) {
return Lists.newArrayList(iterator()).toArray(array);
}
}
@@ -2653,7 +2753,9 @@ public final class Maps {
private static class FilteredKeyMap<K, V> extends AbstractFilteredMap<K, V> {
Predicate<? super K> keyPredicate;
- FilteredKeyMap(Map<K, V> unfiltered, Predicate<? super K> keyPredicate,
+ FilteredKeyMap(
+ Map<K, V> unfiltered,
+ Predicate<? super K> keyPredicate,
Predicate<? super Entry<K, V>> entryPredicate) {
super(unfiltered, entryPredicate);
this.keyPredicate = keyPredicate;
@@ -2685,8 +2787,7 @@ public final class Maps {
*/
final Set<Entry<K, V>> filteredEntrySet;
- FilteredEntryMap(
- Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
+ FilteredEntryMap(Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
super(unfiltered, entryPredicate);
filteredEntrySet = Sets.filter(unfiltered.entrySet(), predicate);
}
@@ -2696,12 +2797,15 @@ public final class Maps {
return new EntrySet();
}
+ @WeakOuter
private class EntrySet extends ForwardingSet<Entry<K, V>> {
- @Override protected Set<Entry<K, V>> delegate() {
+ @Override
+ protected Set<Entry<K, V>> delegate() {
return filteredEntrySet;
}
- @Override public Iterator<Entry<K, V>> iterator() {
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
return new TransformedIterator<Entry<K, V>, Entry<K, V>>(filteredEntrySet.iterator()) {
@Override
Entry<K, V> transform(final Entry<K, V> entry) {
@@ -2727,12 +2831,14 @@ public final class Maps {
return new KeySet();
}
+ @WeakOuter
class KeySet extends Maps.KeySet<K, V> {
KeySet() {
super(FilteredEntryMap.this);
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
if (containsKey(o)) {
unfiltered.remove(o);
return true;
@@ -2741,8 +2847,9 @@ public final class Maps {
}
private boolean removeIf(Predicate<? super K> keyPredicate) {
- return Iterables.removeIf(unfiltered.entrySet(), Predicates.<Entry<K, V>>and(
- predicate, Maps.<K>keyPredicateOnEntries(keyPredicate)));
+ return Iterables.removeIf(
+ unfiltered.entrySet(),
+ Predicates.<Entry<K, V>>and(predicate, Maps.<K>keyPredicateOnEntries(keyPredicate)));
}
@Override
@@ -2755,12 +2862,14 @@ public final class Maps {
return removeIf(not(in(c)));
}
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
// creating an ArrayList so filtering happens once
return Lists.newArrayList(iterator()).toArray();
}
- @Override public <T> T[] toArray(T[] array) {
+ @Override
+ public <T> T[] toArray(T[] array) {
return Lists.newArrayList(iterator()).toArray(array);
}
}
@@ -2771,18 +2880,16 @@ public final class Maps {
* filtering a filtered sorted map.
*/
private static <K, V> SortedMap<K, V> filterFiltered(
- FilteredEntrySortedMap<K, V> map,
- Predicate<? super Entry<K, V>> entryPredicate) {
- Predicate<Entry<K, V>> predicate
- = Predicates.and(map.predicate, entryPredicate);
+ FilteredEntrySortedMap<K, V> map, Predicate<? super Entry<K, V>> entryPredicate) {
+ Predicate<Entry<K, V>> predicate = Predicates.and(map.predicate, entryPredicate);
return new FilteredEntrySortedMap<K, V>(map.sortedMap(), predicate);
}
- private static class FilteredEntrySortedMap<K, V>
- extends FilteredEntryMap<K, V> implements SortedMap<K, V> {
+ private static class FilteredEntrySortedMap<K, V> extends FilteredEntryMap<K, V>
+ implements SortedMap<K, V> {
- FilteredEntrySortedMap(SortedMap<K, V> unfiltered,
- Predicate<? super Entry<K, V>> entryPredicate) {
+ FilteredEntrySortedMap(
+ SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
super(unfiltered, entryPredicate);
}
@@ -2790,7 +2897,8 @@ public final class Maps {
return (SortedMap<K, V>) unfiltered;
}
- @Override public SortedSet<K> keySet() {
+ @Override
+ public SortedSet<K> keySet() {
return (SortedSet<K>) super.keySet();
}
@@ -2799,6 +2907,7 @@ public final class Maps {
return new SortedKeySet();
}
+ @WeakOuter
class SortedKeySet extends KeySet implements SortedSet<K> {
@Override
public Comparator<? super K> comparator() {
@@ -2831,16 +2940,19 @@ public final class Maps {
}
}
- @Override public Comparator<? super K> comparator() {
+ @Override
+ public Comparator<? super K> comparator() {
return sortedMap().comparator();
}
- @Override public K firstKey() {
+ @Override
+ public K firstKey() {
// correctly throws NoSuchElementException when filtered map is empty.
return keySet().iterator().next();
}
- @Override public K lastKey() {
+ @Override
+ public K lastKey() {
SortedMap<K, V> headMap = sortedMap();
while (true) {
// correctly throws NoSuchElementException when filtered map is empty.
@@ -2852,18 +2964,19 @@ public final class Maps {
}
}
- @Override public SortedMap<K, V> headMap(K toKey) {
+ @Override
+ public SortedMap<K, V> headMap(K toKey) {
return new FilteredEntrySortedMap<K, V>(sortedMap().headMap(toKey), predicate);
}
- @Override public SortedMap<K, V> subMap(K fromKey, K toKey) {
- return new FilteredEntrySortedMap<K, V>(
- sortedMap().subMap(fromKey, toKey), predicate);
+ @Override
+ public SortedMap<K, V> subMap(K fromKey, K toKey) {
+ return new FilteredEntrySortedMap<K, V>(sortedMap().subMap(fromKey, toKey), predicate);
}
- @Override public SortedMap<K, V> tailMap(K fromKey) {
- return new FilteredEntrySortedMap<K, V>(
- sortedMap().tailMap(fromKey), predicate);
+ @Override
+ public SortedMap<K, V> tailMap(K fromKey) {
+ return new FilteredEntrySortedMap<K, V>(sortedMap().tailMap(fromKey), predicate);
}
}
@@ -2873,10 +2986,8 @@ public final class Maps {
*/
@GwtIncompatible("NavigableMap")
private static <K, V> NavigableMap<K, V> filterFiltered(
- FilteredEntryNavigableMap<K, V> map,
- Predicate<? super Entry<K, V>> entryPredicate) {
- Predicate<Entry<K, V>> predicate
- = Predicates.and(map.entryPredicate, entryPredicate);
+ FilteredEntryNavigableMap<K, V> map, Predicate<? super Entry<K, V>> entryPredicate) {
+ Predicate<Entry<K, V>> predicate = Predicates.and(map.entryPredicate, entryPredicate);
return new FilteredEntryNavigableMap<K, V>(map.unfiltered, predicate);
}
@@ -2909,14 +3020,17 @@ public final class Maps {
return new Maps.NavigableKeySet<K, V>(this) {
@Override
public boolean removeAll(Collection<?> c) {
- return Iterators.removeIf(unfiltered.entrySet().iterator(),
+ return Iterators.removeIf(
+ unfiltered.entrySet().iterator(),
Predicates.<Entry<K, V>>and(entryPredicate, Maps.<K>keyPredicateOnEntries(in(c))));
}
@Override
public boolean retainAll(Collection<?> c) {
- return Iterators.removeIf(unfiltered.entrySet().iterator(), Predicates.<Entry<K, V>>and(
- entryPredicate, Maps.<K>keyPredicateOnEntries(not(in(c)))));
+ return Iterators.removeIf(
+ unfiltered.entrySet().iterator(),
+ Predicates.<Entry<K, V>>and(
+ entryPredicate, Maps.<K>keyPredicateOnEntries(not(in(c)))));
}
};
}
@@ -3034,22 +3148,19 @@ public final class Maps {
return new Predicate<Entry<V, K>>() {
@Override
public boolean apply(Entry<V, K> input) {
- return forwardPredicate.apply(
- Maps.immutableEntry(input.getValue(), input.getKey()));
+ return forwardPredicate.apply(Maps.immutableEntry(input.getValue(), input.getKey()));
}
};
}
- FilteredEntryBiMap(BiMap<K, V> delegate,
- Predicate<? super Entry<K, V>> predicate) {
+ FilteredEntryBiMap(BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate) {
super(delegate, predicate);
- this.inverse = new FilteredEntryBiMap<V, K>(
- delegate.inverse(), inversePredicate(predicate), this);
+ this.inverse =
+ new FilteredEntryBiMap<V, K>(delegate.inverse(), inversePredicate(predicate), this);
}
private FilteredEntryBiMap(
- BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate,
- BiMap<V, K> inverse) {
+ BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate, BiMap<V, K> inverse) {
super(delegate, predicate);
this.inverse = inverse;
}
@@ -3097,13 +3208,14 @@ public final class Maps {
}
}
- @Nullable private static <K, V> Entry<K, V> unmodifiableOrNull(@Nullable Entry<K, V> entry) {
+ @Nullable
+ private static <K, V> Entry<K, V> unmodifiableOrNull(@Nullable Entry<K, V> entry) {
return (entry == null) ? null : Maps.unmodifiableEntry(entry);
}
@GwtIncompatible("NavigableMap")
- static class UnmodifiableNavigableMap<K, V>
- extends ForwardingSortedMap<K, V> implements NavigableMap<K, V>, Serializable {
+ static class UnmodifiableNavigableMap<K, V> extends ForwardingSortedMap<K, V>
+ implements NavigableMap<K, V>, Serializable {
private final NavigableMap<K, V> delegate;
UnmodifiableNavigableMap(NavigableMap<K, V> delegate) {
@@ -3222,14 +3334,10 @@ public final class Maps {
}
@Override
- public
- NavigableMap<K, V>
- subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
- return Maps.unmodifiableNavigableMap(delegate.subMap(
- fromKey,
- fromInclusive,
- toKey,
- toInclusive));
+ public NavigableMap<K, V> subMap(
+ K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+ return Maps.unmodifiableNavigableMap(
+ delegate.subMap(fromKey, fromInclusive, toKey, toInclusive));
}
@Override
@@ -3298,14 +3406,11 @@ public final class Maps {
}
/**
- * {@code AbstractMap} extension that implements {@link #isEmpty()} as {@code
- * entrySet().isEmpty()} instead of {@code size() == 0} to speed up
- * implementations where {@code size()} is O(n), and it delegates the {@code
- * isEmpty()} methods of its key set and value collection to this
- * implementation.
+ * {@code AbstractMap} extension that makes it easy to cache customized keySet, values,
+ * and entrySet views.
*/
@GwtCompatible
- abstract static class ImprovedAbstractMap<K, V> extends AbstractMap<K, V> {
+ abstract static class ViewCachingAbstractMap<K, V> extends AbstractMap<K, V> {
/**
* Creates the entry set to be returned by {@link #entrySet()}. This method
* is invoked at most once on a given map, at the time when {@code entrySet}
@@ -3315,14 +3420,16 @@ public final class Maps {
private transient Set<Entry<K, V>> entrySet;
- @Override public Set<Entry<K, V>> entrySet() {
+ @Override
+ public Set<Entry<K, V>> entrySet() {
Set<Entry<K, V>> result = entrySet;
return (result == null) ? entrySet = createEntrySet() : result;
}
private transient Set<K> keySet;
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
Set<K> result = keySet;
return (result == null) ? keySet = createKeySet() : result;
}
@@ -3333,7 +3440,8 @@ public final class Maps {
private transient Collection<V> values;
- @Override public Collection<V> values() {
+ @Override
+ public Collection<V> values() {
Collection<V> result = values;
return (result == null) ? values = createValues() : result;
}
@@ -3343,6 +3451,33 @@ public final class Maps {
}
}
+ abstract static class IteratorBasedAbstractMap<K, V> extends AbstractMap<K, V> {
+ @Override
+ public abstract int size();
+
+ abstract Iterator<Entry<K, V>> entryIterator();
+
+ @Override
+ public Set<Entry<K, V>> entrySet() {
+ return new EntrySet<K, V>() {
+ @Override
+ Map<K, V> map() {
+ return IteratorBasedAbstractMap.this;
+ }
+
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return entryIterator();
+ }
+ };
+ }
+
+ @Override
+ public void clear() {
+ Iterators.clear(entryIterator());
+ }
+ }
+
/**
* Delegates to {@link Map#get}. Returns {@code null} on {@code
* ClassCastException} and {@code NullPointerException}.
@@ -3455,15 +3590,13 @@ public final class Maps {
return false;
}
- static final MapJoiner STANDARD_JOINER =
- Collections2.STANDARD_JOINER.withKeyValueSeparator("=");
+ static final MapJoiner STANDARD_JOINER = Collections2.STANDARD_JOINER.withKeyValueSeparator("=");
/**
* An implementation of {@link Map#toString}.
*/
static String toStringImpl(Map<?, ?> map) {
- StringBuilder sb
- = Collections2.newStringBuilderForCollection(map.size()).append('{');
+ StringBuilder sb = Collections2.newStringBuilderForCollection(map.size()).append('{');
STANDARD_JOINER.appendTo(sb, map);
return sb.append('}').toString();
}
@@ -3471,15 +3604,14 @@ public final class Maps {
/**
* An implementation of {@link Map#putAll}.
*/
- static <K, V> void putAllImpl(
- Map<K, V> self, Map<? extends K, ? extends V> map) {
+ static <K, V> void putAllImpl(Map<K, V> self, Map<? extends K, ? extends V> map) {
for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
self.put(entry.getKey(), entry.getValue());
}
}
static class KeySet<K, V> extends Sets.ImprovedAbstractSet<K> {
- final Map<K, V> map;
+ @Weak final Map<K, V> map;
KeySet(Map<K, V> map) {
this.map = checkNotNull(map);
@@ -3489,23 +3621,28 @@ public final class Maps {
return map;
}
- @Override public Iterator<K> iterator() {
+ @Override
+ public Iterator<K> iterator() {
return keyIterator(map().entrySet().iterator());
}
- @Override public int size() {
+ @Override
+ public int size() {
return map().size();
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return map().isEmpty();
}
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
return map().containsKey(o);
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
if (contains(o)) {
map().remove(o);
return true;
@@ -3513,7 +3650,8 @@ public final class Maps {
return false;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
map().clear();
}
}
@@ -3622,10 +3760,7 @@ public final class Maps {
@Override
public NavigableSet<K> subSet(
- K fromElement,
- boolean fromInclusive,
- K toElement,
- boolean toInclusive) {
+ K fromElement, boolean fromInclusive, K toElement, boolean toInclusive) {
return map().subMap(fromElement, fromInclusive, toElement, toInclusive).navigableKeySet();
}
@@ -3656,7 +3791,7 @@ public final class Maps {
}
static class Values<K, V> extends AbstractCollection<V> {
- final Map<K, V> map;
+ @Weak final Map<K, V> map;
Values(Map<K, V> map) {
this.map = checkNotNull(map);
@@ -3666,11 +3801,13 @@ public final class Maps {
return map;
}
- @Override public Iterator<V> iterator() {
+ @Override
+ public Iterator<V> iterator() {
return valueIterator(map().entrySet().iterator());
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
try {
return super.remove(o);
} catch (UnsupportedOperationException e) {
@@ -3684,7 +3821,8 @@ public final class Maps {
}
}
- @Override public boolean removeAll(Collection<?> c) {
+ @Override
+ public boolean removeAll(Collection<?> c) {
try {
return super.removeAll(checkNotNull(c));
} catch (UnsupportedOperationException e) {
@@ -3698,7 +3836,8 @@ public final class Maps {
}
}
- @Override public boolean retainAll(Collection<?> c) {
+ @Override
+ public boolean retainAll(Collection<?> c) {
try {
return super.retainAll(checkNotNull(c));
} catch (UnsupportedOperationException e) {
@@ -3712,51 +3851,58 @@ public final class Maps {
}
}
- @Override public int size() {
+ @Override
+ public int size() {
return map().size();
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return map().isEmpty();
}
- @Override public boolean contains(@Nullable Object o) {
+ @Override
+ public boolean contains(@Nullable Object o) {
return map().containsValue(o);
}
- @Override public void clear() {
+ @Override
+ public void clear() {
map().clear();
}
}
- abstract static class EntrySet<K, V>
- extends Sets.ImprovedAbstractSet<Entry<K, V>> {
+ abstract static class EntrySet<K, V> extends Sets.ImprovedAbstractSet<Entry<K, V>> {
abstract Map<K, V> map();
- @Override public int size() {
+ @Override
+ public int size() {
return map().size();
}
- @Override public void clear() {
+ @Override
+ public void clear() {
map().clear();
}
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
if (o instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) o;
Object key = entry.getKey();
V value = Maps.safeGet(map(), key);
- return Objects.equal(value, entry.getValue())
- && (value != null || map().containsKey(key));
+ return Objects.equal(value, entry.getValue()) && (value != null || map().containsKey(key));
}
return false;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return map().isEmpty();
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
if (contains(o)) {
Entry<?, ?> entry = (Entry<?, ?>) o;
return map().keySet().remove(entry.getKey());
@@ -3764,7 +3910,8 @@ public final class Maps {
return false;
}
- @Override public boolean removeAll(Collection<?> c) {
+ @Override
+ public boolean removeAll(Collection<?> c) {
try {
return super.removeAll(checkNotNull(c));
} catch (UnsupportedOperationException e) {
@@ -3773,7 +3920,8 @@ public final class Maps {
}
}
- @Override public boolean retainAll(Collection<?> c) {
+ @Override
+ public boolean retainAll(Collection<?> c) {
try {
return super.retainAll(checkNotNull(c));
} catch (UnsupportedOperationException e) {
@@ -3908,7 +4056,8 @@ public final class Maps {
abstract Iterator<Entry<K, V>> entryIterator();
Set<Entry<K, V>> createEntrySet() {
- return new EntrySet<K, V>() {
+ @WeakOuter
+ class EntrySetImpl extends EntrySet<K, V> {
@Override
Map<K, V> map() {
return DescendingMap.this;
@@ -3918,7 +4067,8 @@ public final class Maps {
public Iterator<Entry<K, V>> iterator() {
return entryIterator();
}
- };
+ }
+ return new EntrySetImpl();
}
@Override
@@ -3940,9 +4090,8 @@ public final class Maps {
}
@Override
- public
- NavigableMap<K, V>
- subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+ public NavigableMap<K, V> subMap(
+ K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
return forward().subMap(toKey, toInclusive, fromKey, fromInclusive).descendingMap();
}
@@ -3981,4 +4130,16 @@ public final class Maps {
return standardToString();
}
}
+
+ /**
+ * Returns a map from the ith element of list to i.
+ */
+ static <E> ImmutableMap<E, Integer> indexMap(Collection<E> list) {
+ ImmutableMap.Builder<E, Integer> builder = new ImmutableMap.Builder<E, Integer>(list.size());
+ int i = 0;
+ for (E e : list) {
+ builder.put(e, i++);
+ }
+ return builder.build();
+ }
}
diff --git a/guava/src/com/google/common/collect/MinMaxPriorityQueue.java b/guava/src/com/google/common/collect/MinMaxPriorityQueue.java
index bb23f40..451eec8 100644
--- a/guava/src/com/google/common/collect/MinMaxPriorityQueue.java
+++ b/guava/src/com/google/common/collect/MinMaxPriorityQueue.java
@@ -25,6 +25,8 @@ import static com.google.common.collect.CollectPreconditions.checkRemove;
import com.google.common.annotations.Beta;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.math.IntMath;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.AbstractQueue;
import java.util.ArrayDeque;
@@ -42,8 +44,15 @@ import java.util.Queue;
/**
* A double-ended priority queue, which provides constant-time access to both
* its least element and its greatest element, as determined by the queue's
- * specified comparator. If no comparator is given at construction time, the
- * natural order of elements is used.
+ * specified comparator. If no comparator is given at creation time, the
+ * natural order of elements is used. If no maximum size is given at creation time,
+ * the queue is unbounded.
+ *
+ * <p>Usage example: <pre> {@code
+ *
+ * MinMaxPriorityQueue<User> users = MinMaxPriorityQueue.orderedBy(userComparator)
+ * .maximumSize(1000)
+ * .create();}</pre>
*
* <p>As a {@link Queue} it functions exactly as a {@link PriorityQueue}: its
* head element -- the implicit target of the methods {@link #peek()}, {@link
@@ -70,13 +79,18 @@ import java.util.Queue;
* <p><i>Performance notes:</i>
*
* <ul>
+ * <li>If you only access one end of the queue, and do use a maximum size,
+ * this class will perform significantly worse than a {@code PriorityQueue}
+ * with manual eviction above the maximum size. In many cases
+ * {@link Ordering#leastOf} may work for your use case with significantly
+ * improved (and asymptotically superior) performance.
* <li>The retrieval operations {@link #peek}, {@link #peekFirst}, {@link
- * #peekLast}, {@link #element}, and {@link #size} are constant-time
+ * #peekLast}, {@link #element}, and {@link #size} are constant-time.
* <li>The enqueing and dequeing operations ({@link #offer}, {@link #add}, and
* all the forms of {@link #poll} and {@link #remove()}) run in {@code
- * O(log n) time}
+ * O(log n) time}.
* <li>The {@link #remove(Object)} and {@link #contains} operations require
- * linear ({@code O(n)}) time
+ * linear ({@code O(n)}) time.
* <li>If you only access one end of the queue, and don't use a maximum size,
* this class is functionally equivalent to {@link PriorityQueue}, but
* significantly slower.
@@ -122,8 +136,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
* expectedSize} elements.
*/
public static Builder<Comparable> expectedSize(int expectedSize) {
- return new Builder<Comparable>(Ordering.natural())
- .expectedSize(expectedSize);
+ return new Builder<Comparable>(Ordering.natural()).expectedSize(expectedSize);
}
/**
@@ -134,8 +147,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
* the element that was just added.
*/
public static Builder<Comparable> maximumSize(int maximumSize) {
- return new Builder<Comparable>(Ordering.natural())
- .maximumSize(maximumSize);
+ return new Builder<Comparable>(Ordering.natural()).maximumSize(maximumSize);
}
/**
@@ -201,10 +213,10 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
* Builds a new min-max priority queue using the previously specified
* options, and having the given initial elements.
*/
- public <T extends B> MinMaxPriorityQueue<T> create(
- Iterable<? extends T> initialContents) {
- MinMaxPriorityQueue<T> queue = new MinMaxPriorityQueue<T>(
- this, initialQueueSize(expectedSize, maximumSize, initialContents));
+ public <T extends B> MinMaxPriorityQueue<T> create(Iterable<? extends T> initialContents) {
+ MinMaxPriorityQueue<T> queue =
+ new MinMaxPriorityQueue<T>(
+ this, initialQueueSize(expectedSize, maximumSize, initialContents));
for (T element : initialContents) {
queue.offer(element);
}
@@ -236,7 +248,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
this.queue = new Object[queueSize];
}
- @Override public int size() {
+ @Override
+ public int size() {
return size;
}
@@ -248,12 +261,14 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
*
* @return {@code true} always
*/
- @Override public boolean add(E element) {
+ @Override
+ public boolean add(E element) {
offer(element);
return true;
}
- @Override public boolean addAll(Collection<? extends E> newElements) {
+ @Override
+ public boolean addAll(Collection<? extends E> newElements) {
boolean modified = false;
for (E element : newElements) {
offer(element);
@@ -268,7 +283,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
* greatest element (according to its comparator), which may be {@code
* element} itself.
*/
- @Override public boolean offer(E element) {
+ @Override
+ public boolean offer(E element) {
checkNotNull(element);
modCount++;
int insertIndex = size++;
@@ -281,7 +297,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
return size <= maximumSize || pollLast() != element;
}
- @Override public E poll() {
+ @Override
+ public E poll() {
return isEmpty() ? null : removeAndGet(0);
}
@@ -290,7 +307,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
return (E) queue[index];
}
- @Override public E peek() {
+ @Override
+ public E peek() {
return isEmpty() ? null : elementData(0);
}
@@ -378,7 +396,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
* used by iterator.remove so as to visit elements during a traversal once and
* only once.
*/
- @VisibleForTesting MoveDesc<E> removeAt(int index) {
+ @VisibleForTesting
+ MoveDesc<E> removeAt(int index) {
checkPositionIndex(index, size);
modCount++;
size--;
@@ -387,8 +406,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
return null;
}
E actualLastElement = elementData(size);
- int lastElementAt = heapForIndex(size)
- .getCorrectLastElement(actualLastElement);
+ int lastElementAt = heapForIndex(size).getCorrectLastElement(actualLastElement);
E toTrickle = elementData(size);
queue[size] = null;
MoveDesc<E> changes = fillHole(index, toTrickle);
@@ -425,9 +443,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
// there.
return heap.tryCrossOverAndBubbleUp(index, vacated, toTrickle);
} else {
- return (bubbledTo < index)
- ? new MoveDesc<E>(toTrickle, elementData(index))
- : null;
+ return (bubbledTo < index) ? new MoveDesc<E>(toTrickle, elementData(index)) : null;
}
}
@@ -458,7 +474,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
private static final int EVEN_POWERS_OF_TWO = 0x55555555;
private static final int ODD_POWERS_OF_TWO = 0xaaaaaaaa;
- @VisibleForTesting static boolean isEvenLevel(int index) {
+ @VisibleForTesting
+ static boolean isEvenLevel(int index) {
int oneBased = index + 1;
checkState(oneBased > 0, "negative index");
return (oneBased & EVEN_POWERS_OF_TWO) > (oneBased & ODD_POWERS_OF_TWO);
@@ -470,7 +487,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
*
* TODO(kevinb): move to the test class?
*/
- @VisibleForTesting boolean isIntact() {
+ @VisibleForTesting
+ boolean isIntact() {
for (int i = 1; i < size; i++) {
if (!heapForIndex(i).verifyIndex(i)) {
return false;
@@ -485,9 +503,10 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
* array for storage, but for efficiency's sake they are stored interleaved on
* alternate heap levels in the same array (MMPQ.queue).
*/
+ @WeakOuter
private class Heap {
final Ordering<E> ordering;
- Heap otherHeap;
+ @Weak Heap otherHeap;
Heap(Ordering<E> ordering) {
this.ordering = ordering;
@@ -502,8 +521,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
* bubble up there. If it moved before {@code removeIndex} this method
* returns a pair as described in {@link #removeAt}.
*/
- MoveDesc<E> tryCrossOverAndBubbleUp(
- int removeIndex, int vacated, E toTrickle) {
+ MoveDesc<E> tryCrossOverAndBubbleUp(int removeIndex, int vacated, E toTrickle) {
int crossOver = crossOver(vacated, toTrickle);
if (crossOver == vacated) {
return null;
@@ -522,8 +540,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
parent = elementData(getParentIndex(removeIndex));
}
// bubble it up the opposite heap
- if (otherHeap.bubbleUpAlternatingLevels(crossOver, toTrickle)
- < removeIndex) {
+ if (otherHeap.bubbleUpAlternatingLevels(crossOver, toTrickle) < removeIndex) {
return new MoveDesc<E>(toTrickle, parent);
} else {
return null;
@@ -621,8 +638,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
// bubble up alternate levels, violating the invariant.
int grandparentIndex = getParentIndex(parentIndex);
int uncleIndex = getRightChildIndex(grandparentIndex);
- if (uncleIndex != parentIndex
- && getLeftChildIndex(uncleIndex) >= size) {
+ if (uncleIndex != parentIndex && getLeftChildIndex(uncleIndex) >= size) {
E uncleElement = elementData(uncleIndex);
if (ordering.compare(uncleElement, parentElement) < 0) {
parentIndex = uncleIndex;
@@ -653,8 +669,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
if (parentIndex != 0) {
int grandparentIndex = getParentIndex(parentIndex);
int uncleIndex = getRightChildIndex(grandparentIndex);
- if (uncleIndex != parentIndex
- && getLeftChildIndex(uncleIndex) >= size) {
+ if (uncleIndex != parentIndex && getLeftChildIndex(uncleIndex) >= size) {
E uncleElement = elementData(uncleIndex);
if (ordering.compare(uncleElement, actualLastElement) < 0) {
queue[uncleIndex] = actualLastElement;
@@ -676,8 +691,7 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
int minChildIndex = findMinChild(index);
// TODO(kevinb): split the && into two if's and move crossOverUp so it's
// only called when there's no child.
- if ((minChildIndex > 0)
- && (ordering.compare(elementData(minChildIndex), x) < 0)) {
+ if ((minChildIndex > 0) && (ordering.compare(elementData(minChildIndex), x) < 0)) {
queue[index] = elementData(minChildIndex);
queue[minChildIndex] = x;
return minChildIndex;
@@ -703,12 +717,10 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
}
private boolean verifyIndex(int i) {
- if ((getLeftChildIndex(i) < size)
- && (compareElements(i, getLeftChildIndex(i)) > 0)) {
+ if ((getLeftChildIndex(i) < size) && (compareElements(i, getLeftChildIndex(i)) > 0)) {
return false;
}
- if ((getRightChildIndex(i) < size)
- && (compareElements(i, getRightChildIndex(i)) > 0)) {
+ if ((getRightChildIndex(i) < size) && (compareElements(i, getRightChildIndex(i)) > 0)) {
return false;
}
if ((i > 0) && (compareElements(i, getParentIndex(i)) > 0)) {
@@ -753,13 +765,15 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
private E lastFromForgetMeNot;
private boolean canRemove;
- @Override public boolean hasNext() {
+ @Override
+ public boolean hasNext() {
checkModCount();
return (nextNotInSkipMe(cursor + 1) < size())
|| ((forgetMeNot != null) && !forgetMeNot.isEmpty());
}
- @Override public E next() {
+ @Override
+ public E next() {
checkModCount();
int tempCursor = nextNotInSkipMe(cursor + 1);
if (tempCursor < size()) {
@@ -774,11 +788,11 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
return lastFromForgetMeNot;
}
}
- throw new NoSuchElementException(
- "iterator moved past last element in queue.");
+ throw new NoSuchElementException("iterator moved past last element in queue.");
}
- @Override public void remove() {
+ @Override
+ public void remove() {
checkRemove(canRemove);
checkModCount();
canRemove = false;
@@ -863,18 +877,21 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
*
* @return an iterator over the elements contained in this collection
*/
- @Override public Iterator<E> iterator() {
+ @Override
+ public Iterator<E> iterator() {
return new QueueIterator();
}
- @Override public void clear() {
+ @Override
+ public void clear() {
for (int i = 0; i < size; i++) {
queue[i] = null;
}
size = 0;
}
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
Object[] copyTo = new Object[size];
System.arraycopy(queue, 0, copyTo, 0, size);
return copyTo;
@@ -889,7 +906,8 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
return minHeap.ordering;
}
- @VisibleForTesting int capacity() {
+ @VisibleForTesting
+ int capacity() {
return queue.length;
}
@@ -897,12 +915,14 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
private static final int DEFAULT_CAPACITY = 11;
- @VisibleForTesting static int initialQueueSize(int configuredExpectedSize,
- int maximumSize, Iterable<?> initialContents) {
+ @VisibleForTesting
+ static int initialQueueSize(
+ int configuredExpectedSize, int maximumSize, Iterable<?> initialContents) {
// Start with what they said, if they said it, otherwise DEFAULT_CAPACITY
- int result = (configuredExpectedSize == Builder.UNSET_EXPECTED_SIZE)
- ? DEFAULT_CAPACITY
- : configuredExpectedSize;
+ int result =
+ (configuredExpectedSize == Builder.UNSET_EXPECTED_SIZE)
+ ? DEFAULT_CAPACITY
+ : configuredExpectedSize;
// Enlarge to contain initial contents
if (initialContents instanceof Collection) {
@@ -926,9 +946,10 @@ public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
/** Returns ~2x the old capacity if small; ~1.5x otherwise. */
private int calculateNewCapacity() {
int oldCapacity = queue.length;
- int newCapacity = (oldCapacity < 64)
- ? (oldCapacity + 1) * 2
- : IntMath.checkedMultiply(oldCapacity / 2, 3);
+ int newCapacity =
+ (oldCapacity < 64)
+ ? (oldCapacity + 1) * 2
+ : IntMath.checkedMultiply(oldCapacity / 2, 3);
return capAtMaximumSize(newCapacity, maximumSize);
}
diff --git a/guava/src/com/google/common/collect/Multimap.java b/guava/src/com/google/common/collect/Multimap.java
index 074dc0d..9924dd1 100644
--- a/guava/src/com/google/common/collect/Multimap.java
+++ b/guava/src/com/google/common/collect/Multimap.java
@@ -120,8 +120,8 @@ import javax.annotation.Nullable;
* <li>There is no need to populate an empty collection before adding an entry
* with {@link #put put}.
* <li>{@code get} never returns {@code null}, only an empty collection.
- * <li>A key is contained in the multimap if and only if it maps to at least
- * one value. Any operation that causes a key to have zero associated
+ * <li>A key is contained in the multimap if and only if it maps to at least
+ * one value. Any operation that causes a key to have zero associated
* values has the effect of <i>removing</i> that key from the multimap.
* <li>The total entry count is available as {@link #size}.
* <li>Many complex operations become easier; for example, {@code
@@ -142,10 +142,10 @@ import javax.annotation.Nullable;
* to multimaps.
*
* <h3>Other Notes</h3>
- *
- * <p>As with {@code Map}, the behavior of a {@code Multimap} is not specified
- * if key objects already present in the multimap change in a manner that
- * affects {@code equals} comparisons. Use caution if mutable objects are used
+ *
+ * <p>As with {@code Map}, the behavior of a {@code Multimap} is not specified
+ * if key objects already present in the multimap change in a manner that
+ * affects {@code equals} comparisons. Use caution if mutable objects are used
* as keys in a {@code Multimap}.
*
* <p>All methods that modify the multimap are optional. The view collections
@@ -154,11 +154,11 @@ import javax.annotation.Nullable;
* UnsupportedOperationException}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
* {@code Multimap}</a>.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public interface Multimap<K, V> {
@@ -230,11 +230,11 @@ public interface Multimap<K, V> {
* Stores a key-value pair in this multimap for each of {@code values}, all
* using the same key, {@code key}. Equivalent to (but expected to be more
* efficient than): <pre> {@code
- *
+ *
* for (V value : values) {
* put(key, value);
* }}</pre>
- *
+ *
* <p>In particular, this is a no-op if {@code values} is empty.
*
* @return {@code true} if the multimap changed
@@ -252,8 +252,8 @@ public interface Multimap<K, V> {
/**
* Stores a collection of values with the same key, replacing any existing
* values for that key.
- *
- * <p>If {@code values} is empty, this is equivalent to
+ *
+ * <p>If {@code values} is empty, this is equivalent to
* {@link #removeAll(Object) removeAll(key)}.
*
* @return the collection of replaced values, or an empty collection if no
@@ -265,10 +265,10 @@ public interface Multimap<K, V> {
/**
* Removes all values associated with the key {@code key}.
- *
+ *
* <p>Once this method returns, {@code key} will not be mapped to any values,
* so it will not appear in {@link #keySet()}, {@link #asMap()}, or any other
- * views.
+ * views.
*
* @return the values that were removed (possibly empty). The returned
* collection <i>may</i> be modifiable, but updating it will have no
@@ -286,7 +286,7 @@ public interface Multimap<K, V> {
/**
* Returns a view collection of the values associated with {@code key} in this
- * multimap, if any. Note that when {@code containsKey(key)} is false, this
+ * multimap, if any. Note that when {@code containsKey(key)} is false, this
* returns an empty collection, not {@code null}.
*
* <p>Changes to the returned collection will update the underlying multimap,
@@ -382,7 +382,7 @@ public interface Multimap<K, V> {
* not have the same hash codes, depending on the implementation. For
* example, two {@link SetMultimap} instances with the same key-value
* mappings will have the same {@code hashCode}, but the {@code hashCode}
- * of {@link ListMultimap} instances depends on the ordering of the values
+ * of {@link ListMultimap} instances depends on the ordering of the values
* for each key.
*/
@Override
diff --git a/guava/src/com/google/common/collect/MultimapBuilder.java b/guava/src/com/google/common/collect/MultimapBuilder.java
index 89c796c..97738ef 100644
--- a/guava/src/com/google/common/collect/MultimapBuilder.java
+++ b/guava/src/com/google/common/collect/MultimapBuilder.java
@@ -18,6 +18,7 @@ package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
+import static com.google.common.collect.Maps.newLinkedHashMapWithExpectedSize;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
@@ -41,6 +42,8 @@ import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
+import javax.annotation.CheckReturnValue;
+
/**
* A builder for a multimap implementation that allows customization of the backing map and value
* collection implementations used in a particular multimap.
@@ -68,6 +71,7 @@ import java.util.TreeSet;
*/
@Beta
@GwtCompatible
+ at CheckReturnValue
public abstract class MultimapBuilder<K0, V0> {
/*
* Leaving K and V as upper bounds rather than the actual key and value types allows type
@@ -96,7 +100,7 @@ public abstract class MultimapBuilder<K0, V0> {
return new MultimapBuilderWithKeys<Object>() {
@Override
<K, V> Map<K, Collection<V>> createMap() {
- return new HashMap<K, Collection<V>>(expectedKeys);
+ return Maps.newHashMapWithExpectedSize(expectedKeys);
}
};
}
@@ -127,7 +131,7 @@ public abstract class MultimapBuilder<K0, V0> {
return new MultimapBuilderWithKeys<Object>() {
@Override
<K, V> Map<K, Collection<V>> createMap() {
- return new LinkedHashMap<K, Collection<V>>(expectedKeys);
+ return newLinkedHashMapWithExpectedSize(expectedKeys);
}
};
}
@@ -225,7 +229,7 @@ public abstract class MultimapBuilder<K0, V0> {
@Override
public Set<V> get() {
- return new HashSet<V>(expectedValuesPerKey);
+ return Sets.newHashSetWithExpectedSize(expectedValuesPerKey);
}
}
@@ -238,7 +242,7 @@ public abstract class MultimapBuilder<K0, V0> {
@Override
public Set<V> get() {
- return new LinkedHashSet<V>(expectedValuesPerKey);
+ return Sets.newLinkedHashSetWithExpectedSize(expectedValuesPerKey);
}
}
@@ -316,8 +320,7 @@ public abstract class MultimapBuilder<K0, V0> {
@Override
public <K extends K0, V> ListMultimap<K, V> build() {
return Multimaps.newListMultimap(
- MultimapBuilderWithKeys.this.<K, V>createMap(),
- LinkedListSupplier.<V>instance());
+ MultimapBuilderWithKeys.this.<K, V>createMap(), LinkedListSupplier.<V>instance());
}
};
}
@@ -392,8 +395,7 @@ public abstract class MultimapBuilder<K0, V0> {
@Override
public <K extends K0, V extends V0> SortedSetMultimap<K, V> build() {
return Multimaps.newSortedSetMultimap(
- MultimapBuilderWithKeys.this.<K, V>createMap(),
- new TreeSetSupplier<V>(comparator));
+ MultimapBuilderWithKeys.this.<K, V>createMap(), new TreeSetSupplier<V>(comparator));
}
};
}
@@ -411,9 +413,7 @@ public abstract class MultimapBuilder<K0, V0> {
// (their subclasses are inaccessible)
@SuppressWarnings({"unchecked", "rawtypes"})
Supplier<Set<V>> factory = (Supplier) new EnumSetSupplier<V0>(valueClass);
- return Multimaps.newSetMultimap(
- MultimapBuilderWithKeys.this.<K, V>createMap(),
- factory);
+ return Multimaps.newSetMultimap(MultimapBuilderWithKeys.this.<K, V>createMap(), factory);
}
};
}
diff --git a/guava/src/com/google/common/collect/Multimaps.java b/guava/src/com/google/common/collect/Multimaps.java
index 14c8564..62cd1f3 100644
--- a/guava/src/com/google/common/collect/Multimaps.java
+++ b/guava/src/com/google/common/collect/Multimaps.java
@@ -28,6 +28,8 @@ import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.collect.Maps.EntryTransformer;
+import com.google.j2objc.annotations.Weak;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -46,20 +48,21 @@ import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Provides static methods acting on or generating a {@code Multimap}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Multimaps">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#multimaps">
* {@code Multimaps}</a>.
*
* @author Jared Levy
* @author Robert Konigsberg
* @author Mike Bostock
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Multimaps {
@@ -108,21 +111,21 @@ public final class Multimaps {
* values for a given key
* @throws IllegalArgumentException if {@code map} is not empty
*/
- public static <K, V> Multimap<K, V> newMultimap(Map<K, Collection<V>> map,
- final Supplier<? extends Collection<V>> factory) {
+ public static <K, V> Multimap<K, V> newMultimap(
+ Map<K, Collection<V>> map, final Supplier<? extends Collection<V>> factory) {
return new CustomMultimap<K, V>(map, factory);
}
private static class CustomMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
transient Supplier<? extends Collection<V>> factory;
- CustomMultimap(Map<K, Collection<V>> map,
- Supplier<? extends Collection<V>> factory) {
+ CustomMultimap(Map<K, Collection<V>> map, Supplier<? extends Collection<V>> factory) {
super(map);
this.factory = checkNotNull(factory);
}
- @Override protected Collection<V> createCollection() {
+ @Override
+ protected Collection<V> createCollection() {
return factory.get();
}
@@ -139,8 +142,7 @@ public final class Multimaps {
@GwtIncompatible("java.io.ObjectInputStream")
@SuppressWarnings("unchecked") // reading data stored by writeObject
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
factory = (Supplier<? extends Collection<V>>) stream.readObject();
Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
@@ -194,17 +196,16 @@ public final class Multimaps {
return new CustomListMultimap<K, V>(map, factory);
}
- private static class CustomListMultimap<K, V>
- extends AbstractListMultimap<K, V> {
+ private static class CustomListMultimap<K, V> extends AbstractListMultimap<K, V> {
transient Supplier<? extends List<V>> factory;
- CustomListMultimap(Map<K, Collection<V>> map,
- Supplier<? extends List<V>> factory) {
+ CustomListMultimap(Map<K, Collection<V>> map, Supplier<? extends List<V>> factory) {
super(map);
this.factory = checkNotNull(factory);
}
- @Override protected List<V> createCollection() {
+ @Override
+ protected List<V> createCollection() {
return factory.get();
}
@@ -218,8 +219,7 @@ public final class Multimaps {
@GwtIncompatible("java.io.ObjectInputStream")
@SuppressWarnings("unchecked") // reading data stored by writeObject
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
factory = (Supplier<? extends List<V>>) stream.readObject();
Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
@@ -272,17 +272,16 @@ public final class Multimaps {
return new CustomSetMultimap<K, V>(map, factory);
}
- private static class CustomSetMultimap<K, V>
- extends AbstractSetMultimap<K, V> {
+ private static class CustomSetMultimap<K, V> extends AbstractSetMultimap<K, V> {
transient Supplier<? extends Set<V>> factory;
- CustomSetMultimap(Map<K, Collection<V>> map,
- Supplier<? extends Set<V>> factory) {
+ CustomSetMultimap(Map<K, Collection<V>> map, Supplier<? extends Set<V>> factory) {
super(map);
this.factory = checkNotNull(factory);
}
- @Override protected Set<V> createCollection() {
+ @Override
+ protected Set<V> createCollection() {
return factory.get();
}
@@ -296,8 +295,7 @@ public final class Multimaps {
@GwtIncompatible("java.io.ObjectInputStream")
@SuppressWarnings("unchecked") // reading data stored by writeObject
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
factory = (Supplier<? extends Set<V>>) stream.readObject();
Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject();
@@ -345,28 +343,27 @@ public final class Multimaps {
* @throws IllegalArgumentException if {@code map} is not empty
*/
public static <K, V> SortedSetMultimap<K, V> newSortedSetMultimap(
- Map<K, Collection<V>> map,
- final Supplier<? extends SortedSet<V>> factory) {
+ Map<K, Collection<V>> map, final Supplier<? extends SortedSet<V>> factory) {
return new CustomSortedSetMultimap<K, V>(map, factory);
}
- private static class CustomSortedSetMultimap<K, V>
- extends AbstractSortedSetMultimap<K, V> {
+ private static class CustomSortedSetMultimap<K, V> extends AbstractSortedSetMultimap<K, V> {
transient Supplier<? extends SortedSet<V>> factory;
transient Comparator<? super V> valueComparator;
- CustomSortedSetMultimap(Map<K, Collection<V>> map,
- Supplier<? extends SortedSet<V>> factory) {
+ CustomSortedSetMultimap(Map<K, Collection<V>> map, Supplier<? extends SortedSet<V>> factory) {
super(map);
this.factory = checkNotNull(factory);
valueComparator = factory.get().comparator();
}
- @Override protected SortedSet<V> createCollection() {
+ @Override
+ protected SortedSet<V> createCollection() {
return factory.get();
}
- @Override public Comparator<? super V> valueComparator() {
+ @Override
+ public Comparator<? super V> valueComparator() {
return valueComparator;
}
@@ -380,8 +377,7 @@ public final class Multimaps {
@GwtIncompatible("java.io.ObjectInputStream")
@SuppressWarnings("unchecked") // reading data stored by writeObject
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
factory = (Supplier<? extends SortedSet<V>>) stream.readObject();
valueComparator = factory.get().comparator();
@@ -446,8 +442,7 @@ public final class Multimaps {
* @param multimap the multimap to be wrapped in a synchronized view
* @return a synchronized view of the specified multimap
*/
- public static <K, V> Multimap<K, V> synchronizedMultimap(
- Multimap<K, V> multimap) {
+ public static <K, V> Multimap<K, V> synchronizedMultimap(Multimap<K, V> multimap) {
return Synchronized.multimap(multimap, null);
}
@@ -468,10 +463,8 @@ public final class Multimaps {
* returned
* @return an unmodifiable view of the specified multimap
*/
- public static <K, V> Multimap<K, V> unmodifiableMultimap(
- Multimap<K, V> delegate) {
- if (delegate instanceof UnmodifiableMultimap ||
- delegate instanceof ImmutableMultimap) {
+ public static <K, V> Multimap<K, V> unmodifiableMultimap(Multimap<K, V> delegate) {
+ if (delegate instanceof UnmodifiableMultimap || delegate instanceof ImmutableMultimap) {
return delegate;
}
return new UnmodifiableMultimap<K, V>(delegate);
@@ -483,13 +476,13 @@ public final class Multimaps {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <K, V> Multimap<K, V> unmodifiableMultimap(
- ImmutableMultimap<K, V> delegate) {
+ @Deprecated
+ public static <K, V> Multimap<K, V> unmodifiableMultimap(ImmutableMultimap<K, V> delegate) {
return checkNotNull(delegate);
}
- private static class UnmodifiableMultimap<K, V>
- extends ForwardingMultimap<K, V> implements Serializable {
+ private static class UnmodifiableMultimap<K, V> extends ForwardingMultimap<K, V>
+ implements Serializable {
final Multimap<K, V> delegate;
transient Collection<Entry<K, V>> entries;
transient Multiset<K> keys;
@@ -501,29 +494,36 @@ public final class Multimaps {
this.delegate = checkNotNull(delegate);
}
- @Override protected Multimap<K, V> delegate() {
+ @Override
+ protected Multimap<K, V> delegate() {
return delegate;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
throw new UnsupportedOperationException();
}
- @Override public Map<K, Collection<V>> asMap() {
+ @Override
+ public Map<K, Collection<V>> asMap() {
Map<K, Collection<V>> result = map;
if (result == null) {
- result = map = Collections.unmodifiableMap(
- Maps.transformValues(delegate.asMap(), new Function<Collection<V>, Collection<V>>() {
- @Override
- public Collection<V> apply(Collection<V> collection) {
- return unmodifiableValueCollection(collection);
- }
- }));
+ result = map =
+ Collections.unmodifiableMap(
+ Maps.transformValues(
+ delegate.asMap(),
+ new Function<Collection<V>, Collection<V>>() {
+ @Override
+ public Collection<V> apply(Collection<V> collection) {
+ return unmodifiableValueCollection(collection);
+ }
+ }));
}
return result;
}
- @Override public Collection<Entry<K, V>> entries() {
+ @Override
+ public Collection<Entry<K, V>> entries() {
Collection<Entry<K, V>> result = entries;
if (result == null) {
entries = result = unmodifiableEntries(delegate.entries());
@@ -531,11 +531,13 @@ public final class Multimaps {
return result;
}
- @Override public Collection<V> get(K key) {
+ @Override
+ public Collection<V> get(K key) {
return unmodifiableValueCollection(delegate.get(key));
}
- @Override public Multiset<K> keys() {
+ @Override
+ public Multiset<K> keys() {
Multiset<K> result = keys;
if (result == null) {
keys = result = Multisets.unmodifiableMultiset(delegate.keys());
@@ -543,7 +545,8 @@ public final class Multimaps {
return result;
}
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
Set<K> result = keySet;
if (result == null) {
keySet = result = Collections.unmodifiableSet(delegate.keySet());
@@ -551,11 +554,13 @@ public final class Multimaps {
return result;
}
- @Override public boolean put(K key, V value) {
+ @Override
+ public boolean put(K key, V value) {
throw new UnsupportedOperationException();
}
- @Override public boolean putAll(K key, Iterable<? extends V> values) {
+ @Override
+ public boolean putAll(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
@@ -564,20 +569,23 @@ public final class Multimaps {
throw new UnsupportedOperationException();
}
- @Override public boolean remove(Object key, Object value) {
+ @Override
+ public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
}
- @Override public Collection<V> removeAll(Object key) {
+ @Override
+ public Collection<V> removeAll(Object key) {
throw new UnsupportedOperationException();
}
- @Override public Collection<V> replaceValues(
- K key, Iterable<? extends V> values) {
+ @Override
+ public Collection<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
- @Override public Collection<V> values() {
+ @Override
+ public Collection<V> values() {
Collection<V> result = values;
if (result == null) {
values = result = Collections.unmodifiableCollection(delegate.values());
@@ -588,77 +596,104 @@ public final class Multimaps {
private static final long serialVersionUID = 0;
}
- private static class UnmodifiableListMultimap<K, V>
- extends UnmodifiableMultimap<K, V> implements ListMultimap<K, V> {
+ private static class UnmodifiableListMultimap<K, V> extends UnmodifiableMultimap<K, V>
+ implements ListMultimap<K, V> {
UnmodifiableListMultimap(ListMultimap<K, V> delegate) {
super(delegate);
}
- @Override public ListMultimap<K, V> delegate() {
+
+ @Override
+ public ListMultimap<K, V> delegate() {
return (ListMultimap<K, V>) super.delegate();
}
- @Override public List<V> get(K key) {
+
+ @Override
+ public List<V> get(K key) {
return Collections.unmodifiableList(delegate().get(key));
}
- @Override public List<V> removeAll(Object key) {
+
+ @Override
+ public List<V> removeAll(Object key) {
throw new UnsupportedOperationException();
}
- @Override public List<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public List<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
+
private static final long serialVersionUID = 0;
}
- private static class UnmodifiableSetMultimap<K, V>
- extends UnmodifiableMultimap<K, V> implements SetMultimap<K, V> {
+ private static class UnmodifiableSetMultimap<K, V> extends UnmodifiableMultimap<K, V>
+ implements SetMultimap<K, V> {
UnmodifiableSetMultimap(SetMultimap<K, V> delegate) {
super(delegate);
}
- @Override public SetMultimap<K, V> delegate() {
+
+ @Override
+ public SetMultimap<K, V> delegate() {
return (SetMultimap<K, V>) super.delegate();
}
- @Override public Set<V> get(K key) {
+
+ @Override
+ public Set<V> get(K key) {
/*
* Note that this doesn't return a SortedSet when delegate is a
* SortedSetMultiset, unlike (SortedSet<V>) super.get().
*/
return Collections.unmodifiableSet(delegate().get(key));
}
- @Override public Set<Map.Entry<K, V>> entries() {
+
+ @Override
+ public Set<Map.Entry<K, V>> entries() {
return Maps.unmodifiableEntrySet(delegate().entries());
}
- @Override public Set<V> removeAll(Object key) {
+
+ @Override
+ public Set<V> removeAll(Object key) {
throw new UnsupportedOperationException();
}
- @Override public Set<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public Set<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
+
private static final long serialVersionUID = 0;
}
- private static class UnmodifiableSortedSetMultimap<K, V>
- extends UnmodifiableSetMultimap<K, V> implements SortedSetMultimap<K, V> {
+ private static class UnmodifiableSortedSetMultimap<K, V> extends UnmodifiableSetMultimap<K, V>
+ implements SortedSetMultimap<K, V> {
UnmodifiableSortedSetMultimap(SortedSetMultimap<K, V> delegate) {
super(delegate);
}
- @Override public SortedSetMultimap<K, V> delegate() {
+
+ @Override
+ public SortedSetMultimap<K, V> delegate() {
return (SortedSetMultimap<K, V>) super.delegate();
}
- @Override public SortedSet<V> get(K key) {
+
+ @Override
+ public SortedSet<V> get(K key) {
return Collections.unmodifiableSortedSet(delegate().get(key));
}
- @Override public SortedSet<V> removeAll(Object key) {
+
+ @Override
+ public SortedSet<V> removeAll(Object key) {
throw new UnsupportedOperationException();
}
- @Override public SortedSet<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
throw new UnsupportedOperationException();
}
+
@Override
public Comparator<? super V> valueComparator() {
return delegate().valueComparator();
}
+
private static final long serialVersionUID = 0;
}
@@ -674,8 +709,7 @@ public final class Multimaps {
* @param multimap the multimap to be wrapped
* @return a synchronized view of the specified multimap
*/
- public static <K, V> SetMultimap<K, V> synchronizedSetMultimap(
- SetMultimap<K, V> multimap) {
+ public static <K, V> SetMultimap<K, V> synchronizedSetMultimap(SetMultimap<K, V> multimap) {
return Synchronized.setMultimap(multimap, null);
}
@@ -697,10 +731,8 @@ public final class Multimaps {
* returned
* @return an unmodifiable view of the specified multimap
*/
- public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
- SetMultimap<K, V> delegate) {
- if (delegate instanceof UnmodifiableSetMultimap ||
- delegate instanceof ImmutableSetMultimap) {
+ public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(SetMultimap<K, V> delegate) {
+ if (delegate instanceof UnmodifiableSetMultimap || delegate instanceof ImmutableSetMultimap) {
return delegate;
}
return new UnmodifiableSetMultimap<K, V>(delegate);
@@ -712,7 +744,8 @@ public final class Multimaps {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
+ @Deprecated
+ public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(
ImmutableSetMultimap<K, V> delegate) {
return checkNotNull(delegate);
}
@@ -729,8 +762,8 @@ public final class Multimaps {
* @param multimap the multimap to be wrapped
* @return a synchronized view of the specified multimap
*/
- public static <K, V> SortedSetMultimap<K, V>
- synchronizedSortedSetMultimap(SortedSetMultimap<K, V> multimap) {
+ public static <K, V> SortedSetMultimap<K, V> synchronizedSortedSetMultimap(
+ SortedSetMultimap<K, V> multimap) {
return Synchronized.sortedSetMultimap(multimap, null);
}
@@ -769,8 +802,7 @@ public final class Multimaps {
* @param multimap the multimap to be wrapped
* @return a synchronized view of the specified multimap
*/
- public static <K, V> ListMultimap<K, V> synchronizedListMultimap(
- ListMultimap<K, V> multimap) {
+ public static <K, V> ListMultimap<K, V> synchronizedListMultimap(ListMultimap<K, V> multimap) {
return Synchronized.listMultimap(multimap, null);
}
@@ -792,10 +824,8 @@ public final class Multimaps {
* returned
* @return an unmodifiable view of the specified multimap
*/
- public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
- ListMultimap<K, V> delegate) {
- if (delegate instanceof UnmodifiableListMultimap ||
- delegate instanceof ImmutableListMultimap) {
+ public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(ListMultimap<K, V> delegate) {
+ if (delegate instanceof UnmodifiableListMultimap || delegate instanceof ImmutableListMultimap) {
return delegate;
}
return new UnmodifiableListMultimap<K, V>(delegate);
@@ -807,7 +837,8 @@ public final class Multimaps {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
+ @Deprecated
+ public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(
ImmutableListMultimap<K, V> delegate) {
return checkNotNull(delegate);
}
@@ -820,8 +851,7 @@ public final class Multimaps {
* @param collection the collection for which to return an unmodifiable view
* @return an unmodifiable view of the collection
*/
- private static <V> Collection<V> unmodifiableValueCollection(
- Collection<V> collection) {
+ private static <V> Collection<V> unmodifiableValueCollection(Collection<V> collection) {
if (collection instanceof SortedSet) {
return Collections.unmodifiableSortedSet((SortedSet<V>) collection);
} else if (collection instanceof Set) {
@@ -846,8 +876,7 @@ public final class Multimaps {
if (entries instanceof Set) {
return Maps.unmodifiableEntrySet((Set<Entry<K, V>>) entries);
}
- return new Maps.UnmodifiableEntries<K, V>(
- Collections.unmodifiableCollection(entries));
+ return new Maps.UnmodifiableEntries<K, V>(Collections.unmodifiableCollection(entries));
}
/**
@@ -886,8 +915,7 @@ public final class Multimaps {
@Beta
@SuppressWarnings("unchecked")
// safe by specification of SortedSetMultimap.asMap()
- public static <K, V> Map<K, SortedSet<V>> asMap(
- SortedSetMultimap<K, V> multimap) {
+ public static <K, V> Map<K, SortedSet<V>> asMap(SortedSetMultimap<K, V> multimap) {
return (Map<K, SortedSet<V>>) (Map<K, ?>) multimap.asMap();
}
@@ -924,8 +952,8 @@ public final class Multimaps {
}
/** @see Multimaps#forMap */
- private static class MapMultimap<K, V>
- extends AbstractMultimap<K, V> implements SetMultimap<K, V>, Serializable {
+ private static class MapMultimap<K, V> extends AbstractMultimap<K, V>
+ implements SetMultimap<K, V>, Serializable {
final Map<K, V> map;
MapMultimap(Map<K, V> map) {
@@ -955,7 +983,8 @@ public final class Multimaps {
@Override
public Set<V> get(final K key) {
return new Sets.ImprovedAbstractSet<V>() {
- @Override public Iterator<V> iterator() {
+ @Override
+ public Iterator<V> iterator() {
return new Iterator<V>() {
int i;
@@ -982,7 +1011,8 @@ public final class Multimaps {
};
}
- @Override public int size() {
+ @Override
+ public int size() {
return map.containsKey(key) ? 1 : 0;
}
};
@@ -1042,7 +1072,7 @@ public final class Multimaps {
public Set<Entry<K, V>> entries() {
return map.entrySet();
}
-
+
@Override
Iterator<Entry<K, V>> entryIterator() {
return map.entrySet().iterator();
@@ -1053,10 +1083,11 @@ public final class Multimaps {
return new AsMap<K, V>(this);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return map.hashCode();
}
-
+
private static final long serialVersionUID = 7845222491160860175L;
}
@@ -1167,25 +1198,23 @@ public final class Multimaps {
* @since 7.0
*/
public static <K, V1, V2> Multimap<K, V2> transformEntries(
- Multimap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ Multimap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
return new TransformedEntriesMultimap<K, V1, V2>(fromMap, transformer);
}
- private static class TransformedEntriesMultimap<K, V1, V2>
- extends AbstractMultimap<K, V2> {
+ private static class TransformedEntriesMultimap<K, V1, V2> extends AbstractMultimap<K, V2> {
final Multimap<K, V1> fromMultimap;
final EntryTransformer<? super K, ? super V1, V2> transformer;
- TransformedEntriesMultimap(Multimap<K, V1> fromMultimap,
+ TransformedEntriesMultimap(
+ Multimap<K, V1> fromMultimap,
final EntryTransformer<? super K, ? super V1, V2> transformer) {
this.fromMultimap = checkNotNull(fromMultimap);
this.transformer = checkNotNull(transformer);
}
Collection<V2> transform(K key, Collection<V1> values) {
- Function<? super V1, V2> function =
- Maps.asValueToValueFunction(transformer, key);
+ Function<? super V1, V2> function = Maps.asValueToValueFunction(transformer, key);
if (values instanceof List) {
return Lists.transform((List<V1>) values, function);
} else {
@@ -1195,77 +1224,89 @@ public final class Multimaps {
@Override
Map<K, Collection<V2>> createAsMap() {
- return Maps.transformEntries(fromMultimap.asMap(),
+ return Maps.transformEntries(
+ fromMultimap.asMap(),
new EntryTransformer<K, Collection<V1>, Collection<V2>>() {
- @Override public Collection<V2> transformEntry(
- K key, Collection<V1> value) {
- return transform(key, value);
- }
- });
+ @Override
+ public Collection<V2> transformEntry(K key, Collection<V1> value) {
+ return transform(key, value);
+ }
+ });
}
- @Override public void clear() {
+ @Override
+ public void clear() {
fromMultimap.clear();
}
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return fromMultimap.containsKey(key);
}
@Override
Iterator<Entry<K, V2>> entryIterator() {
- return Iterators.transform(fromMultimap.entries().iterator(),
- Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
+ return Iterators.transform(
+ fromMultimap.entries().iterator(), Maps.<K, V1, V2>asEntryToEntryFunction(transformer));
}
- @Override public Collection<V2> get(final K key) {
+ @Override
+ public Collection<V2> get(final K key) {
return transform(key, fromMultimap.get(key));
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return fromMultimap.isEmpty();
}
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
return fromMultimap.keySet();
}
- @Override public Multiset<K> keys() {
+ @Override
+ public Multiset<K> keys() {
return fromMultimap.keys();
}
- @Override public boolean put(K key, V2 value) {
+ @Override
+ public boolean put(K key, V2 value) {
throw new UnsupportedOperationException();
}
- @Override public boolean putAll(K key, Iterable<? extends V2> values) {
+ @Override
+ public boolean putAll(K key, Iterable<? extends V2> values) {
throw new UnsupportedOperationException();
}
- @Override public boolean putAll(
- Multimap<? extends K, ? extends V2> multimap) {
+ @Override
+ public boolean putAll(Multimap<? extends K, ? extends V2> multimap) {
throw new UnsupportedOperationException();
}
@SuppressWarnings("unchecked")
- @Override public boolean remove(Object key, Object value) {
+ @Override
+ public boolean remove(Object key, Object value) {
return get((K) key).remove(value);
}
@SuppressWarnings("unchecked")
- @Override public Collection<V2> removeAll(Object key) {
+ @Override
+ public Collection<V2> removeAll(Object key) {
return transform((K) key, fromMultimap.removeAll(key));
}
- @Override public Collection<V2> replaceValues(
- K key, Iterable<? extends V2> values) {
+ @Override
+ public Collection<V2> replaceValues(K key, Iterable<? extends V2> values) {
throw new UnsupportedOperationException();
}
- @Override public int size() {
+ @Override
+ public int size() {
return fromMultimap.size();
}
-
+
@Override
Collection<V2> createValues() {
return Collections2.transform(
@@ -1315,8 +1356,7 @@ public final class Multimaps {
* @since 7.0
*/
public static <K, V1, V2> ListMultimap<K, V2> transformValues(
- ListMultimap<K, V1> fromMultimap,
- final Function<? super V1, V2> function) {
+ ListMultimap<K, V1> fromMultimap, final Function<? super V1, V2> function) {
checkNotNull(function);
EntryTransformer<K, V1, V2> transformer = Maps.asEntryTransformer(function);
return transformEntries(fromMultimap, transformer);
@@ -1375,35 +1415,36 @@ public final class Multimaps {
* @since 7.0
*/
public static <K, V1, V2> ListMultimap<K, V2> transformEntries(
- ListMultimap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ ListMultimap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
return new TransformedEntriesListMultimap<K, V1, V2>(fromMap, transformer);
}
private static final class TransformedEntriesListMultimap<K, V1, V2>
- extends TransformedEntriesMultimap<K, V1, V2>
- implements ListMultimap<K, V2> {
+ extends TransformedEntriesMultimap<K, V1, V2> implements ListMultimap<K, V2> {
- TransformedEntriesListMultimap(ListMultimap<K, V1> fromMultimap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ TransformedEntriesListMultimap(
+ ListMultimap<K, V1> fromMultimap, EntryTransformer<? super K, ? super V1, V2> transformer) {
super(fromMultimap, transformer);
}
- @Override List<V2> transform(K key, Collection<V1> values) {
+ @Override
+ List<V2> transform(K key, Collection<V1> values) {
return Lists.transform((List<V1>) values, Maps.asValueToValueFunction(transformer, key));
}
- @Override public List<V2> get(K key) {
+ @Override
+ public List<V2> get(K key) {
return transform(key, fromMultimap.get(key));
}
@SuppressWarnings("unchecked")
- @Override public List<V2> removeAll(Object key) {
+ @Override
+ public List<V2> removeAll(Object key) {
return transform((K) key, fromMultimap.removeAll(key));
}
- @Override public List<V2> replaceValues(
- K key, Iterable<? extends V2> values) {
+ @Override
+ public List<V2> replaceValues(K key, Iterable<? extends V2> values) {
throw new UnsupportedOperationException();
}
}
@@ -1501,8 +1542,7 @@ public final class Multimaps {
public static <K, V> ImmutableListMultimap<K, V> index(
Iterator<V> values, Function<? super V, K> keyFunction) {
checkNotNull(keyFunction);
- ImmutableListMultimap.Builder<K, V> builder
- = ImmutableListMultimap.builder();
+ ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder();
while (values.hasNext()) {
V value = values.next();
checkNotNull(value, values);
@@ -1512,18 +1552,18 @@ public final class Multimaps {
}
static class Keys<K, V> extends AbstractMultiset<K> {
- final Multimap<K, V> multimap;
-
+ @Weak final Multimap<K, V> multimap;
+
Keys(Multimap<K, V> multimap) {
this.multimap = multimap;
}
- @Override Iterator<Multiset.Entry<K>> entryIterator() {
+ @Override
+ Iterator<Multiset.Entry<K>> entryIterator() {
return new TransformedIterator<Map.Entry<K, Collection<V>>, Multiset.Entry<K>>(
multimap.asMap().entrySet().iterator()) {
@Override
- Multiset.Entry<K> transform(
- final Map.Entry<K, Collection<V>> backingEntry) {
+ Multiset.Entry<K> transform(final Map.Entry<K, Collection<V>> backingEntry) {
return new Multisets.AbstractEntry<K>() {
@Override
public K getElement() {
@@ -1539,32 +1579,40 @@ public final class Multimaps {
};
}
- @Override int distinctElements() {
+ @Override
+ int distinctElements() {
return multimap.asMap().size();
}
- @Override Set<Multiset.Entry<K>> createEntrySet() {
+ @Override
+ Set<Multiset.Entry<K>> createEntrySet() {
return new KeysEntrySet();
}
+ @WeakOuter
class KeysEntrySet extends Multisets.EntrySet<K> {
- @Override Multiset<K> multiset() {
+ @Override
+ Multiset<K> multiset() {
return Keys.this;
}
- @Override public Iterator<Multiset.Entry<K>> iterator() {
+ @Override
+ public Iterator<Multiset.Entry<K>> iterator() {
return entryIterator();
}
- @Override public int size() {
+ @Override
+ public int size() {
return distinctElements();
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return multimap.isEmpty();
}
- @Override public boolean contains(@Nullable Object o) {
+ @Override
+ public boolean contains(@Nullable Object o) {
if (o instanceof Multiset.Entry) {
Multiset.Entry<?> entry = (Multiset.Entry<?>) o;
Collection<V> collection = multimap.asMap().get(entry.getElement());
@@ -1573,7 +1621,8 @@ public final class Multimaps {
return false;
}
- @Override public boolean remove(@Nullable Object o) {
+ @Override
+ public boolean remove(@Nullable Object o) {
if (o instanceof Multiset.Entry) {
Multiset.Entry<?> entry = (Multiset.Entry<?>) o;
Collection<V> collection = multimap.asMap().get(entry.getElement());
@@ -1586,20 +1635,24 @@ public final class Multimaps {
}
}
- @Override public boolean contains(@Nullable Object element) {
+ @Override
+ public boolean contains(@Nullable Object element) {
return multimap.containsKey(element);
}
- @Override public Iterator<K> iterator() {
+ @Override
+ public Iterator<K> iterator() {
return Maps.keyIterator(multimap.entries().iterator());
}
- @Override public int count(@Nullable Object element) {
+ @Override
+ public int count(@Nullable Object element) {
Collection<V> values = Maps.safeGet(multimap.asMap(), element);
return (values == null) ? 0 : values.size();
}
- @Override public int remove(@Nullable Object element, int occurrences) {
+ @Override
+ public int remove(@Nullable Object element, int occurrences) {
checkNonnegative(occurrences, "occurrences");
if (occurrences == 0) {
return count(element);
@@ -1624,11 +1677,13 @@ public final class Multimaps {
return oldCount;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
multimap.clear();
}
- @Override public Set<K> elementSet() {
+ @Override
+ public Set<K> elementSet() {
return multimap.keySet();
}
}
@@ -1636,15 +1691,16 @@ public final class Multimaps {
/**
* A skeleton implementation of {@link Multimap#entries()}.
*/
- abstract static class Entries<K, V> extends
- AbstractCollection<Map.Entry<K, V>> {
+ abstract static class Entries<K, V> extends AbstractCollection<Map.Entry<K, V>> {
abstract Multimap<K, V> multimap();
- @Override public int size() {
+ @Override
+ public int size() {
return multimap().size();
}
- @Override public boolean contains(@Nullable Object o) {
+ @Override
+ public boolean contains(@Nullable Object o) {
if (o instanceof Map.Entry) {
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
return multimap().containsEntry(entry.getKey(), entry.getValue());
@@ -1652,7 +1708,8 @@ public final class Multimaps {
return false;
}
- @Override public boolean remove(@Nullable Object o) {
+ @Override
+ public boolean remove(@Nullable Object o) {
if (o instanceof Map.Entry) {
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
return multimap().remove(entry.getKey(), entry.getValue());
@@ -1660,7 +1717,8 @@ public final class Multimaps {
return false;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
multimap().clear();
}
}
@@ -1668,19 +1726,20 @@ public final class Multimaps {
/**
* A skeleton implementation of {@link Multimap#asMap()}.
*/
- static final class AsMap<K, V> extends
- Maps.ImprovedAbstractMap<K, Collection<V>> {
- private final Multimap<K, V> multimap;
-
+ static final class AsMap<K, V> extends Maps.ViewCachingAbstractMap<K, Collection<V>> {
+ @Weak private final Multimap<K, V> multimap;
+
AsMap(Multimap<K, V> multimap) {
this.multimap = checkNotNull(multimap);
}
- @Override public int size() {
+ @Override
+ public int size() {
return multimap.keySet().size();
}
- @Override protected Set<Entry<K, Collection<V>>> createEntrySet() {
+ @Override
+ protected Set<Entry<K, Collection<V>>> createEntrySet() {
return new EntrySet();
}
@@ -1688,21 +1747,27 @@ public final class Multimaps {
multimap.keySet().remove(key);
}
+ @WeakOuter
class EntrySet extends Maps.EntrySet<K, Collection<V>> {
- @Override Map<K, Collection<V>> map() {
+ @Override
+ Map<K, Collection<V>> map() {
return AsMap.this;
}
- @Override public Iterator<Entry<K, Collection<V>>> iterator() {
- return Maps.asMapEntryIterator(multimap.keySet(), new Function<K, Collection<V>>() {
- @Override
- public Collection<V> apply(K key) {
- return multimap.get(key);
- }
- });
+ @Override
+ public Iterator<Entry<K, Collection<V>>> iterator() {
+ return Maps.asMapEntryIterator(
+ multimap.keySet(),
+ new Function<K, Collection<V>>() {
+ @Override
+ public Collection<V> apply(K key) {
+ return multimap.get(key);
+ }
+ });
}
- @Override public boolean remove(Object o) {
+ @Override
+ public boolean remove(Object o) {
if (!contains(o)) {
return false;
}
@@ -1713,27 +1778,33 @@ public final class Multimaps {
}
@SuppressWarnings("unchecked")
- @Override public Collection<V> get(Object key) {
+ @Override
+ public Collection<V> get(Object key) {
return containsKey(key) ? multimap.get((K) key) : null;
}
- @Override public Collection<V> remove(Object key) {
+ @Override
+ public Collection<V> remove(Object key) {
return containsKey(key) ? multimap.removeAll(key) : null;
}
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
return multimap.keySet();
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return multimap.isEmpty();
}
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return multimap.containsKey(key);
}
- @Override public void clear() {
+ @Override
+ public void clear() {
multimap.clear();
}
}
@@ -1768,6 +1839,7 @@ public final class Multimaps {
*
* @since 11.0
*/
+ @CheckReturnValue
public static <K, V> Multimap<K, V> filterKeys(
Multimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
if (unfiltered instanceof SetMultimap) {
@@ -1776,8 +1848,8 @@ public final class Multimaps {
return filterKeys((ListMultimap<K, V>) unfiltered, keyPredicate);
} else if (unfiltered instanceof FilteredKeyMultimap) {
FilteredKeyMultimap<K, V> prev = (FilteredKeyMultimap<K, V>) unfiltered;
- return new FilteredKeyMultimap<K, V>(prev.unfiltered,
- Predicates.and(prev.keyPredicate, keyPredicate));
+ return new FilteredKeyMultimap<K, V>(
+ prev.unfiltered, Predicates.and(prev.keyPredicate, keyPredicate));
} else if (unfiltered instanceof FilteredMultimap) {
FilteredMultimap<K, V> prev = (FilteredMultimap<K, V>) unfiltered;
return filterFiltered(prev, Maps.<K>keyPredicateOnEntries(keyPredicate));
@@ -1785,7 +1857,7 @@ public final class Multimaps {
return new FilteredKeyMultimap<K, V>(unfiltered, keyPredicate);
}
}
-
+
/**
* Returns a multimap containing the mappings in {@code unfiltered} whose keys
* satisfy a predicate. The returned multimap is a live view of
@@ -1816,12 +1888,13 @@ public final class Multimaps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> SetMultimap<K, V> filterKeys(
SetMultimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
if (unfiltered instanceof FilteredKeySetMultimap) {
FilteredKeySetMultimap<K, V> prev = (FilteredKeySetMultimap<K, V>) unfiltered;
- return new FilteredKeySetMultimap<K, V>(prev.unfiltered(),
- Predicates.and(prev.keyPredicate, keyPredicate));
+ return new FilteredKeySetMultimap<K, V>(
+ prev.unfiltered(), Predicates.and(prev.keyPredicate, keyPredicate));
} else if (unfiltered instanceof FilteredSetMultimap) {
FilteredSetMultimap<K, V> prev = (FilteredSetMultimap<K, V>) unfiltered;
return filterFiltered(prev, Maps.<K>keyPredicateOnEntries(keyPredicate));
@@ -1829,7 +1902,7 @@ public final class Multimaps {
return new FilteredKeySetMultimap<K, V>(unfiltered, keyPredicate);
}
}
-
+
/**
* Returns a multimap containing the mappings in {@code unfiltered} whose keys
* satisfy a predicate. The returned multimap is a live view of
@@ -1860,12 +1933,13 @@ public final class Multimaps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> ListMultimap<K, V> filterKeys(
ListMultimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
if (unfiltered instanceof FilteredKeyListMultimap) {
FilteredKeyListMultimap<K, V> prev = (FilteredKeyListMultimap<K, V>) unfiltered;
- return new FilteredKeyListMultimap<K, V>(prev.unfiltered(),
- Predicates.and(prev.keyPredicate, keyPredicate));
+ return new FilteredKeyListMultimap<K, V>(
+ prev.unfiltered(), Predicates.and(prev.keyPredicate, keyPredicate));
} else {
return new FilteredKeyListMultimap<K, V>(unfiltered, keyPredicate);
}
@@ -1901,11 +1975,12 @@ public final class Multimaps {
*
* @since 11.0
*/
+ @CheckReturnValue
public static <K, V> Multimap<K, V> filterValues(
Multimap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
}
-
+
/**
* Returns a multimap containing the mappings in {@code unfiltered} whose values
* satisfy a predicate. The returned multimap is a live view of
@@ -1936,6 +2011,7 @@ public final class Multimaps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> SetMultimap<K, V> filterValues(
SetMultimap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate));
@@ -1969,6 +2045,7 @@ public final class Multimaps {
*
* @since 11.0
*/
+ @CheckReturnValue
public static <K, V> Multimap<K, V> filterEntries(
Multimap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
checkNotNull(entryPredicate);
@@ -1979,7 +2056,7 @@ public final class Multimaps {
? filterFiltered((FilteredMultimap<K, V>) unfiltered, entryPredicate)
: new FilteredEntryMultimap<K, V>(checkNotNull(unfiltered), entryPredicate);
}
-
+
/**
* Returns a multimap containing the mappings in {@code unfiltered} that
* satisfy a predicate. The returned multimap is a live view of
@@ -2008,6 +2085,7 @@ public final class Multimaps {
*
* @since 14.0
*/
+ @CheckReturnValue
public static <K, V> SetMultimap<K, V> filterEntries(
SetMultimap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
checkNotNull(entryPredicate);
@@ -2023,10 +2101,9 @@ public final class Multimaps {
* operations would fail. This method combines the predicates to avoid that
* problem.
*/
- private static <K, V> Multimap<K, V> filterFiltered(FilteredMultimap<K, V> multimap,
- Predicate<? super Entry<K, V>> entryPredicate) {
- Predicate<Entry<K, V>> predicate
- = Predicates.and(multimap.entryPredicate(), entryPredicate);
+ private static <K, V> Multimap<K, V> filterFiltered(
+ FilteredMultimap<K, V> multimap, Predicate<? super Entry<K, V>> entryPredicate) {
+ Predicate<Entry<K, V>> predicate = Predicates.and(multimap.entryPredicate(), entryPredicate);
return new FilteredEntryMultimap<K, V>(multimap.unfiltered(), predicate);
}
@@ -2037,13 +2114,11 @@ public final class Multimaps {
* avoid that problem.
*/
private static <K, V> SetMultimap<K, V> filterFiltered(
- FilteredSetMultimap<K, V> multimap,
- Predicate<? super Entry<K, V>> entryPredicate) {
- Predicate<Entry<K, V>> predicate
- = Predicates.and(multimap.entryPredicate(), entryPredicate);
+ FilteredSetMultimap<K, V> multimap, Predicate<? super Entry<K, V>> entryPredicate) {
+ Predicate<Entry<K, V>> predicate = Predicates.and(multimap.entryPredicate(), entryPredicate);
return new FilteredEntrySetMultimap<K, V>(multimap.unfiltered(), predicate);
}
-
+
static boolean equalsImpl(Multimap<?, ?> multimap, @Nullable Object object) {
if (object == multimap) {
return true;
diff --git a/guava/src/com/google/common/collect/Multiset.java b/guava/src/com/google/common/collect/Multiset.java
index b29b689..940a216 100644
--- a/guava/src/com/google/common/collect/Multiset.java
+++ b/guava/src/com/google/common/collect/Multiset.java
@@ -77,13 +77,13 @@ import javax.annotation.Nullable;
* may wish to use {@link com.google.common.util.concurrent.AtomicLongMap}
* instead. Note, however, that unlike {@code Multiset}, {@code AtomicLongMap}
* does not automatically remove zeros.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
* {@code Multiset}</a>.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public interface Multiset<E> extends Collection<E> {
@@ -229,7 +229,7 @@ public interface Multiset<E> extends Collection<E> {
* snapshots. Note that this type is unrelated to the similarly-named type
* {@code Map.Entry}.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
interface Entry<E> {
@@ -380,6 +380,9 @@ public interface Multiset<E> extends Collection<E> {
* always increment the count of the element, and the overall size of the
* collection, by one.
*
+ * <p>To both add the element and obtain the previous count of that element,
+ * use {@link #add(E, int) add}{@code (element, 1)} instead.
+ *
* @param element the element to add one occurrence of; may be null only if
* explicitly allowed by the implementation
* @return {@code true} always, since this call is required to modify the
@@ -400,6 +403,9 @@ public interface Multiset<E> extends Collection<E> {
* <b>may not</b> throw an exception in response to {@code element} being null
* or of the wrong type.
*
+ * <p>To both remove the element and obtain the previous count of that element,
+ * use {@link #remove(E, int) remove}{@code (element, 1)} instead.
+ *
* @param element the element to remove one occurrence of
* @return {@code true} if an occurrence was found and removed
*/
@@ -413,10 +419,10 @@ public interface Multiset<E> extends Collection<E> {
* {@code c}, and only cares whether or not an element appears at all.
* If you wish to remove one occurrence in this multiset for every occurrence
* in {@code c}, see {@link Multisets#removeOccurrences(Multiset, Multiset)}.
- *
+ *
* <p>This method refines {@link Collection#removeAll} to further specify that
* it <b>may not</b> throw an exception in response to any of {@code elements}
- * being null or of the wrong type.
+ * being null or of the wrong type.
*/
@Override
boolean removeAll(Collection<?> c);
@@ -428,11 +434,11 @@ public interface Multiset<E> extends Collection<E> {
* {@code c}, and only cares whether or not an element appears at all.
* If you wish to remove one occurrence in this multiset for every occurrence
* in {@code c}, see {@link Multisets#retainOccurrences(Multiset, Multiset)}.
- *
+ *
* <p>This method refines {@link Collection#retainAll} to further specify that
* it <b>may not</b> throw an exception in response to any of {@code elements}
* being null or of the wrong type.
- *
+ *
* @see Multisets#retainOccurrences(Multiset, Multiset)
*/
@Override
diff --git a/guava/src/com/google/common/collect/Multisets.java b/guava/src/com/google/common/collect/Multisets.java
index 2ce27a5..2f4d184 100644
--- a/guava/src/com/google/common/collect/Multisets.java
+++ b/guava/src/com/google/common/collect/Multisets.java
@@ -37,6 +37,7 @@ import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -44,13 +45,13 @@ import javax.annotation.Nullable;
* Multiset} instances.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Multisets">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#multisets">
* {@code Multisets}</a>.
*
* @author Kevin Bourrillion
* @author Mike Bostock
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public final class Multisets {
@@ -69,10 +70,8 @@ public final class Multisets {
* generated
* @return an unmodifiable view of the multiset
*/
- public static <E> Multiset<E> unmodifiableMultiset(
- Multiset<? extends E> multiset) {
- if (multiset instanceof UnmodifiableMultiset ||
- multiset instanceof ImmutableMultiset) {
+ public static <E> Multiset<E> unmodifiableMultiset(Multiset<? extends E> multiset) {
+ if (multiset instanceof UnmodifiableMultiset || multiset instanceof ImmutableMultiset) {
// Since it's unmodifiable, the covariant cast is safe
@SuppressWarnings("unchecked")
Multiset<E> result = (Multiset<E>) multiset;
@@ -87,13 +86,12 @@ public final class Multisets {
* @deprecated no need to use this
* @since 10.0
*/
- @Deprecated public static <E> Multiset<E> unmodifiableMultiset(
- ImmutableMultiset<E> multiset) {
+ @Deprecated
+ public static <E> Multiset<E> unmodifiableMultiset(ImmutableMultiset<E> multiset) {
return checkNotNull(multiset);
}
- static class UnmodifiableMultiset<E>
- extends ForwardingMultiset<E> implements Serializable {
+ static class UnmodifiableMultiset<E> extends ForwardingMultiset<E> implements Serializable {
final Multiset<? extends E> delegate;
UnmodifiableMultiset(Multiset<? extends E> delegate) {
@@ -101,7 +99,8 @@ public final class Multisets {
}
@SuppressWarnings("unchecked")
- @Override protected Multiset<E> delegate() {
+ @Override
+ protected Multiset<E> delegate() {
// This is safe because all non-covariant methods are overriden
return (Multiset<E>) delegate;
}
@@ -121,7 +120,8 @@ public final class Multisets {
transient Set<Multiset.Entry<E>> entrySet;
@SuppressWarnings("unchecked")
- @Override public Set<Multiset.Entry<E>> entrySet() {
+ @Override
+ public Set<Multiset.Entry<E>> entrySet() {
Set<Multiset.Entry<E>> es = entrySet;
return (es == null)
// Safe because the returned set is made unmodifiable and Entry
@@ -131,48 +131,59 @@ public final class Multisets {
}
@SuppressWarnings("unchecked")
- @Override public Iterator<E> iterator() {
+ @Override
+ public Iterator<E> iterator() {
// Safe because the returned Iterator is made unmodifiable
return (Iterator<E>) Iterators.unmodifiableIterator(delegate.iterator());
}
- @Override public boolean add(E element) {
+ @Override
+ public boolean add(E element) {
throw new UnsupportedOperationException();
}
- @Override public int add(E element, int occurences) {
+ @Override
+ public int add(E element, int occurences) {
throw new UnsupportedOperationException();
}
- @Override public boolean addAll(Collection<? extends E> elementsToAdd) {
+ @Override
+ public boolean addAll(Collection<? extends E> elementsToAdd) {
throw new UnsupportedOperationException();
}
- @Override public boolean remove(Object element) {
+ @Override
+ public boolean remove(Object element) {
throw new UnsupportedOperationException();
}
- @Override public int remove(Object element, int occurrences) {
+ @Override
+ public int remove(Object element, int occurrences) {
throw new UnsupportedOperationException();
}
- @Override public boolean removeAll(Collection<?> elementsToRemove) {
+ @Override
+ public boolean removeAll(Collection<?> elementsToRemove) {
throw new UnsupportedOperationException();
}
- @Override public boolean retainAll(Collection<?> elementsToRetain) {
+ @Override
+ public boolean retainAll(Collection<?> elementsToRetain) {
throw new UnsupportedOperationException();
}
- @Override public void clear() {
+ @Override
+ public void clear() {
throw new UnsupportedOperationException();
}
- @Override public int setCount(E element, int count) {
+ @Override
+ public int setCount(E element, int count) {
throw new UnsupportedOperationException();
}
- @Override public boolean setCount(E element, int oldCount, int newCount) {
+ @Override
+ public boolean setCount(E element, int oldCount, int newCount) {
throw new UnsupportedOperationException();
}
@@ -194,8 +205,7 @@ public final class Multisets {
* @since 11.0
*/
@Beta
- public static <E> SortedMultiset<E> unmodifiableSortedMultiset(
- SortedMultiset<E> sortedMultiset) {
+ public static <E> SortedMultiset<E> unmodifiableSortedMultiset(SortedMultiset<E> sortedMultiset) {
// it's in its own file so it can be emulated for GWT
return new UnmodifiableSortedMultiset<E>(checkNotNull(sortedMultiset));
}
@@ -212,10 +222,9 @@ public final class Multisets {
return new ImmutableEntry<E>(e, n);
}
- static final class ImmutableEntry<E> extends AbstractEntry<E> implements
- Serializable {
- @Nullable final E element;
- final int count;
+ static class ImmutableEntry<E> extends AbstractEntry<E> implements Serializable {
+ @Nullable private final E element;
+ private final int count;
ImmutableEntry(@Nullable E element, int count) {
this.element = element;
@@ -224,15 +233,20 @@ public final class Multisets {
}
@Override
- @Nullable public E getElement() {
+ @Nullable
+ public final E getElement() {
return element;
}
@Override
- public int getCount() {
+ public final int getCount() {
return count;
}
+ public ImmutableEntry<E> nextInBucket() {
+ return null;
+ }
+
private static final long serialVersionUID = 0;
}
@@ -263,13 +277,13 @@ public final class Multisets {
* @since 14.0
*/
@Beta
+ @CheckReturnValue
public static <E> Multiset<E> filter(Multiset<E> unfiltered, Predicate<? super E> predicate) {
if (unfiltered instanceof FilteredMultiset) {
// Support clear(), removeAll(), and retainAll() when filtering a filtered
// collection.
FilteredMultiset<E> filtered = (FilteredMultiset<E>) unfiltered;
- Predicate<E> combinedPredicate
- = Predicates.<E>and(filtered.predicate, predicate);
+ Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
return new FilteredMultiset<E>(filtered.unfiltered, combinedPredicate);
}
return new FilteredMultiset<E>(unfiltered, predicate);
@@ -296,12 +310,14 @@ public final class Multisets {
@Override
Set<Entry<E>> createEntrySet() {
- return Sets.filter(unfiltered.entrySet(), new Predicate<Entry<E>>() {
- @Override
- public boolean apply(Entry<E> entry) {
- return predicate.apply(entry.getElement());
- }
- });
+ return Sets.filter(
+ unfiltered.entrySet(),
+ new Predicate<Entry<E>>() {
+ @Override
+ public boolean apply(Entry<E> entry) {
+ return predicate.apply(entry.getElement());
+ }
+ });
}
@Override
@@ -327,8 +343,8 @@ public final class Multisets {
@Override
public int add(@Nullable E element, int occurrences) {
- checkArgument(predicate.apply(element),
- "Element %s does not match predicate %s", element, predicate);
+ checkArgument(
+ predicate.apply(element), "Element %s does not match predicate %s", element, predicate);
return unfiltered.add(element, occurrences);
}
@@ -405,11 +421,9 @@ public final class Multisets {
@Override
Iterator<Entry<E>> entryIterator() {
- final Iterator<? extends Entry<? extends E>> iterator1
- = multiset1.entrySet().iterator();
- final Iterator<? extends Entry<? extends E>> iterator2
- = multiset2.entrySet().iterator();
- // TODO(user): consider making the entries live views
+ final Iterator<? extends Entry<? extends E>> iterator1 = multiset1.entrySet().iterator();
+ final Iterator<? extends Entry<? extends E>> iterator2 = multiset2.entrySet().iterator();
+ // TODO(lowasser): consider making the entries live views
return new AbstractIterator<Entry<E>>() {
@Override
protected Entry<E> computeNext() {
@@ -466,14 +480,13 @@ public final class Multisets {
@Override
Set<E> createElementSet() {
- return Sets.intersection(
- multiset1.elementSet(), multiset2.elementSet());
+ return Sets.intersection(multiset1.elementSet(), multiset2.elementSet());
}
@Override
Iterator<Entry<E>> entryIterator() {
final Iterator<Entry<E>> iterator1 = multiset1.entrySet().iterator();
- // TODO(user): consider making the entries live views
+ // TODO(lowasser): consider making the entries live views
return new AbstractIterator<Entry<E>>() {
@Override
protected Entry<E> computeNext() {
@@ -518,7 +531,7 @@ public final class Multisets {
checkNotNull(multiset1);
checkNotNull(multiset2);
- // TODO(user): consider making the entries live views
+ // TODO(lowasser): consider making the entries live views
return new AbstractMultiset<E>() {
@Override
public boolean contains(@Nullable Object element) {
@@ -547,10 +560,8 @@ public final class Multisets {
@Override
Iterator<Entry<E>> entryIterator() {
- final Iterator<? extends Entry<? extends E>> iterator1
- = multiset1.entrySet().iterator();
- final Iterator<? extends Entry<? extends E>> iterator2
- = multiset2.entrySet().iterator();
+ final Iterator<? extends Entry<? extends E>> iterator1 = multiset1.entrySet().iterator();
+ final Iterator<? extends Entry<? extends E>> iterator2 = multiset2.entrySet().iterator();
return new AbstractIterator<Entry<E>>() {
@Override
protected Entry<E> computeNext() {
@@ -600,13 +611,12 @@ public final class Multisets {
checkNotNull(multiset1);
checkNotNull(multiset2);
- // TODO(user): consider making the entries live views
+ // TODO(lowasser): consider making the entries live views
return new AbstractMultiset<E>() {
@Override
public int count(@Nullable Object element) {
int count1 = multiset1.count(element);
- return (count1 == 0) ? 0 :
- Math.max(0, count1 - multiset2.count(element));
+ return (count1 == 0) ? 0 : Math.max(0, count1 - multiset2.count(element));
}
@Override
@@ -641,8 +651,7 @@ public final class Multisets {
*
* @since 10.0
*/
- public static boolean containsOccurrences(
- Multiset<?> superMultiset, Multiset<?> subMultiset) {
+ public static boolean containsOccurrences(Multiset<?> superMultiset, Multiset<?> subMultiset) {
checkNotNull(superMultiset);
checkNotNull(subMultiset);
for (Entry<?> entry : subMultiset.entrySet()) {
@@ -673,8 +682,8 @@ public final class Multisets {
* of this operation
* @since 10.0
*/
- public static boolean retainOccurrences(Multiset<?> multisetToModify,
- Multiset<?> multisetToRetain) {
+ public static boolean retainOccurrences(
+ Multiset<?> multisetToModify, Multiset<?> multisetToRetain) {
return retainOccurrencesImpl(multisetToModify, multisetToRetain);
}
@@ -709,7 +718,7 @@ public final class Multisets {
* <p>Equivalently, this method modifies {@code multisetToModify} so that
* {@code multisetToModify.count(e)} is set to
* {@code Math.max(0, multisetToModify.count(e) -
- * occurrencesToRemove.count(e))}.
+ * Iterables.frequency(occurrencesToRemove, e))}.
*
* <p>This is <i>not</i> the same as {@code multisetToModify.}
* {@link Multiset#removeAll removeAll}{@code (occurrencesToRemove)}, which
@@ -729,37 +738,50 @@ public final class Multisets {
public static boolean removeOccurrences(
Multiset<?> multisetToModify, Iterable<?> occurrencesToRemove) {
if (occurrencesToRemove instanceof Multiset) {
- return removeOccurrencesImpl(
- multisetToModify, (Multiset<?>) occurrencesToRemove);
+ return removeOccurrences(multisetToModify, (Multiset<?>) occurrencesToRemove);
} else {
- return removeOccurrencesImpl(multisetToModify, occurrencesToRemove);
- }
- }
-
- private static boolean removeOccurrencesImpl(
- Multiset<?> multisetToModify, Iterable<?> occurrencesToRemove) {
- checkNotNull(multisetToModify);
- checkNotNull(occurrencesToRemove);
- boolean changed = false;
- for (Object o : occurrencesToRemove) {
- changed |= multisetToModify.remove(o);
+ checkNotNull(multisetToModify);
+ checkNotNull(occurrencesToRemove);
+ boolean changed = false;
+ for (Object o : occurrencesToRemove) {
+ changed |= multisetToModify.remove(o);
+ }
+ return changed;
}
- return changed;
}
/**
- * Delegate that cares about the element types in multisetToModify.
+ * For each occurrence of an element {@code e} in {@code occurrencesToRemove},
+ * removes one occurrence of {@code e} in {@code multisetToModify}.
+ *
+ * <p>Equivalently, this method modifies {@code multisetToModify} so that
+ * {@code multisetToModify.count(e)} is set to
+ * {@code Math.max(0, multisetToModify.count(e) -
+ * occurrencesToRemove.count(e))}.
+ *
+ * <p>This is <i>not</i> the same as {@code multisetToModify.}
+ * {@link Multiset#removeAll removeAll}{@code (occurrencesToRemove)}, which
+ * removes all occurrences of elements that appear in
+ * {@code occurrencesToRemove}. However, this operation <i>is</i> equivalent
+ * to, albeit sometimes more efficient than, the following: <pre> {@code
+ *
+ * for (E e : occurrencesToRemove) {
+ * multisetToModify.remove(e);
+ * }}</pre>
+ *
+ * @return {@code true} if {@code multisetToModify} was changed as a result of
+ * this operation
+ * @since 10.0 (missing in 18.0 when only the overload taking an {@code Iterable} was present)
*/
- private static <E> boolean removeOccurrencesImpl(
- Multiset<E> multisetToModify, Multiset<?> occurrencesToRemove) {
- // TODO(user): generalize to removing an Iterable, perhaps
+ public static boolean removeOccurrences(
+ Multiset<?> multisetToModify, Multiset<?> occurrencesToRemove) {
checkNotNull(multisetToModify);
checkNotNull(occurrencesToRemove);
boolean changed = false;
- Iterator<Entry<E>> entryIterator = multisetToModify.entrySet().iterator();
+ Iterator<? extends Entry<?>> entryIterator = multisetToModify.entrySet().iterator();
while (entryIterator.hasNext()) {
- Entry<E> entry = entryIterator.next();
+ Entry<?> entry = entryIterator.next();
int removeCount = occurrencesToRemove.count(entry.getElement());
if (removeCount >= entry.getCount()) {
entryIterator.remove();
@@ -781,7 +803,8 @@ public final class Multisets {
* Indicates whether an object equals this entry, following the behavior
* specified in {@link Multiset.Entry#equals}.
*/
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object instanceof Multiset.Entry) {
Multiset.Entry<?> that = (Multiset.Entry<?>) object;
return this.getCount() == that.getCount()
@@ -794,7 +817,8 @@ public final class Multisets {
* Return this entry's hash code, following the behavior specified in
* {@link Multiset.Entry#hashCode}.
*/
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
E e = getElement();
return ((e == null) ? 0 : e.hashCode()) ^ getCount();
}
@@ -806,7 +830,8 @@ public final class Multisets {
* " x " (space, x and space) followed by the count. Elements and counts are
* converted to strings as by {@code String.valueOf}.
*/
- @Override public String toString() {
+ @Override
+ public String toString() {
String text = String.valueOf(getElement());
int n = getCount();
return (n == 1) ? text : (text + " x " + n);
@@ -828,8 +853,7 @@ public final class Multisets {
* when passed unequal elements.
*/
- if (multiset.size() != that.size()
- || multiset.entrySet().size() != that.entrySet().size()) {
+ if (multiset.size() != that.size() || multiset.entrySet().size() != that.entrySet().size()) {
return false;
}
for (Entry<?> entry : that.entrySet()) {
@@ -845,8 +869,7 @@ public final class Multisets {
/**
* An implementation of {@link Multiset#addAll}.
*/
- static <E> boolean addAllImpl(
- Multiset<E> self, Collection<? extends E> elements) {
+ static <E> boolean addAllImpl(Multiset<E> self, Collection<? extends E> elements) {
if (elements.isEmpty()) {
return false;
}
@@ -864,10 +887,11 @@ public final class Multisets {
/**
* An implementation of {@link Multiset#removeAll}.
*/
- static boolean removeAllImpl(
- Multiset<?> self, Collection<?> elementsToRemove) {
- Collection<?> collection = (elementsToRemove instanceof Multiset)
- ? ((Multiset<?>) elementsToRemove).elementSet() : elementsToRemove;
+ static boolean removeAllImpl(Multiset<?> self, Collection<?> elementsToRemove) {
+ Collection<?> collection =
+ (elementsToRemove instanceof Multiset)
+ ? ((Multiset<?>) elementsToRemove).elementSet()
+ : elementsToRemove;
return self.elementSet().removeAll(collection);
}
@@ -875,11 +899,12 @@ public final class Multisets {
/**
* An implementation of {@link Multiset#retainAll}.
*/
- static boolean retainAllImpl(
- Multiset<?> self, Collection<?> elementsToRetain) {
+ static boolean retainAllImpl(Multiset<?> self, Collection<?> elementsToRetain) {
checkNotNull(elementsToRetain);
- Collection<?> collection = (elementsToRetain instanceof Multiset)
- ? ((Multiset<?>) elementsToRetain).elementSet() : elementsToRetain;
+ Collection<?> collection =
+ (elementsToRetain instanceof Multiset)
+ ? ((Multiset<?>) elementsToRetain).elementSet()
+ : elementsToRetain;
return self.elementSet().retainAll(collection);
}
@@ -905,8 +930,7 @@ public final class Multisets {
/**
* An implementation of {@link Multiset#setCount(Object, int, int)}.
*/
- static <E> boolean setCountImpl(
- Multiset<E> self, E element, int oldCount, int newCount) {
+ static <E> boolean setCountImpl(Multiset<E> self, E element, int oldCount, int newCount) {
checkNonnegative(oldCount, "oldCount");
checkNonnegative(newCount, "newCount");
@@ -921,23 +945,28 @@ public final class Multisets {
abstract static class ElementSet<E> extends Sets.ImprovedAbstractSet<E> {
abstract Multiset<E> multiset();
- @Override public void clear() {
+ @Override
+ public void clear() {
multiset().clear();
}
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
return multiset().contains(o);
}
- @Override public boolean containsAll(Collection<?> c) {
+ @Override
+ public boolean containsAll(Collection<?> c) {
return multiset().containsAll(c);
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return multiset().isEmpty();
}
- @Override public Iterator<E> iterator() {
+ @Override
+ public Iterator<E> iterator() {
return new TransformedIterator<Entry<E>, E>(multiset().entrySet().iterator()) {
@Override
E transform(Entry<E> entry) {
@@ -948,15 +977,11 @@ public final class Multisets {
@Override
public boolean remove(Object o) {
- int count = multiset().count(o);
- if (count > 0) {
- multiset().remove(o, count);
- return true;
- }
- return false;
+ return multiset().remove(o, Integer.MAX_VALUE) > 0;
}
- @Override public int size() {
+ @Override
+ public int size() {
return multiset().entrySet().size();
}
}
@@ -964,7 +989,8 @@ public final class Multisets {
abstract static class EntrySet<E> extends Sets.ImprovedAbstractSet<Entry<E>> {
abstract Multiset<E> multiset();
- @Override public boolean contains(@Nullable Object o) {
+ @Override
+ public boolean contains(@Nullable Object o) {
if (o instanceof Entry) {
/*
* The GWT compiler wrongly issues a warning here.
@@ -976,14 +1002,14 @@ public final class Multisets {
}
int count = multiset().count(entry.getElement());
return count == entry.getCount();
-
}
return false;
}
// GWT compiler warning; see contains().
@SuppressWarnings("cast")
- @Override public boolean remove(Object object) {
+ @Override
+ public boolean remove(Object object) {
if (object instanceof Multiset.Entry) {
Entry<?> entry = (Entry<?>) object;
Object element = entry.getElement();
@@ -998,7 +1024,8 @@ public final class Multisets {
return false;
}
- @Override public void clear() {
+ @Override
+ public void clear() {
multiset().clear();
}
}
@@ -1007,22 +1034,23 @@ public final class Multisets {
* An implementation of {@link Multiset#iterator}.
*/
static <E> Iterator<E> iteratorImpl(Multiset<E> multiset) {
- return new MultisetIteratorImpl<E>(
- multiset, multiset.entrySet().iterator());
+ return new MultisetIteratorImpl<E>(multiset, multiset.entrySet().iterator());
}
static final class MultisetIteratorImpl<E> implements Iterator<E> {
private final Multiset<E> multiset;
private final Iterator<Entry<E>> entryIterator;
private Entry<E> currentEntry;
+
/** Count of subsequent elements equal to current element */
private int laterCount;
+
/** Count of all elements equal to current element */
private int totalCount;
+
private boolean canRemove;
- MultisetIteratorImpl(
- Multiset<E> multiset, Iterator<Entry<E>> entryIterator) {
+ MultisetIteratorImpl(Multiset<E> multiset, Iterator<Entry<E>> entryIterator) {
this.multiset = multiset;
this.entryIterator = entryIterator;
}
@@ -1077,12 +1105,13 @@ public final class Multisets {
return (Multiset<T>) iterable;
}
- private static final Ordering<Entry<?>> DECREASING_COUNT_ORDERING = new Ordering<Entry<?>>() {
- @Override
- public int compare(Entry<?> entry1, Entry<?> entry2) {
- return Ints.compare(entry2.getCount(), entry1.getCount());
- }
- };
+ private static final Ordering<Entry<?>> DECREASING_COUNT_ORDERING =
+ new Ordering<Entry<?>>() {
+ @Override
+ public int compare(Entry<?> entry1, Entry<?> entry2) {
+ return Ints.compare(entry2.getCount(), entry1.getCount());
+ }
+ };
/**
* Returns a copy of {@code multiset} as an {@link ImmutableMultiset} whose iteration order is
diff --git a/guava/src/com/google/common/collect/MutableClassToInstanceMap.java b/guava/src/com/google/common/collect/MutableClassToInstanceMap.java
index c723cea..4b4d771 100644
--- a/guava/src/com/google/common/collect/MutableClassToInstanceMap.java
+++ b/guava/src/com/google/common/collect/MutableClassToInstanceMap.java
@@ -25,16 +25,15 @@ import java.util.Map;
/**
* A mutable class-to-instance map backed by an arbitrary user-provided map.
* See also {@link ImmutableClassToInstanceMap}.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#ClassToInstanceMap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#classtoinstancemap">
* {@code ClassToInstanceMap}</a>.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
-public final class MutableClassToInstanceMap<B>
- extends ConstrainedMap<Class<? extends B>, B>
+public final class MutableClassToInstanceMap<B> extends ConstrainedMap<Class<? extends B>, B>
implements ClassToInstanceMap<B> {
/**
@@ -42,8 +41,7 @@ public final class MutableClassToInstanceMap<B>
* HashMap} using the default initial capacity and load factor.
*/
public static <B> MutableClassToInstanceMap<B> create() {
- return new MutableClassToInstanceMap<B>(
- new HashMap<Class<? extends B>, B>());
+ return new MutableClassToInstanceMap<B>(new HashMap<Class<? extends B>, B>());
}
/**
@@ -51,8 +49,7 @@ public final class MutableClassToInstanceMap<B>
* empty {@code backingMap}. The caller surrenders control of the backing map,
* and thus should not allow any direct references to it to remain accessible.
*/
- public static <B> MutableClassToInstanceMap<B> create(
- Map<Class<? extends B>, B> backingMap) {
+ public static <B> MutableClassToInstanceMap<B> create(Map<Class<? extends B>, B> backingMap) {
return new MutableClassToInstanceMap<B>(backingMap);
}
@@ -60,13 +57,13 @@ public final class MutableClassToInstanceMap<B>
super(delegate, VALUE_CAN_BE_CAST_TO_KEY);
}
- private static final MapConstraint<Class<?>, Object> VALUE_CAN_BE_CAST_TO_KEY
- = new MapConstraint<Class<?>, Object>() {
- @Override
- public void checkKeyValue(Class<?> key, Object value) {
- cast(key, value);
- }
- };
+ private static final MapConstraint<Class<?>, Object> VALUE_CAN_BE_CAST_TO_KEY =
+ new MapConstraint<Class<?>, Object>() {
+ @Override
+ public void checkKeyValue(Class<?> key, Object value) {
+ cast(key, value);
+ }
+ };
@Override
public <T extends B> T putInstance(Class<T> type, T value) {
diff --git a/guava/src/com/google/common/collect/NaturalOrdering.java b/guava/src/com/google/common/collect/NaturalOrdering.java
index a4c240f..fbacf01 100644
--- a/guava/src/com/google/common/collect/NaturalOrdering.java
+++ b/guava/src/com/google/common/collect/NaturalOrdering.java
@@ -25,17 +25,18 @@ import java.io.Serializable;
/** An ordering that uses the natural order of the values. */
@GwtCompatible(serializable = true)
@SuppressWarnings("unchecked") // TODO(kevinb): the right way to explain this??
-final class NaturalOrdering
- extends Ordering<Comparable> implements Serializable {
+final class NaturalOrdering extends Ordering<Comparable> implements Serializable {
static final NaturalOrdering INSTANCE = new NaturalOrdering();
- @Override public int compare(Comparable left, Comparable right) {
+ @Override
+ public int compare(Comparable left, Comparable right) {
checkNotNull(left); // for GWT
checkNotNull(right);
return left.compareTo(right);
}
- @Override public <S extends Comparable> Ordering<S> reverse() {
+ @Override
+ public <S extends Comparable> Ordering<S> reverse() {
return (Ordering<S>) ReverseNaturalOrdering.INSTANCE;
}
@@ -44,7 +45,8 @@ final class NaturalOrdering
return INSTANCE;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Ordering.natural()";
}
diff --git a/guava/src/com/google/common/collect/NullsFirstOrdering.java b/guava/src/com/google/common/collect/NullsFirstOrdering.java
index 2e8a3ac..28d8fec 100644
--- a/guava/src/com/google/common/collect/NullsFirstOrdering.java
+++ b/guava/src/com/google/common/collect/NullsFirstOrdering.java
@@ -31,7 +31,8 @@ final class NullsFirstOrdering<T> extends Ordering<T> implements Serializable {
this.ordering = ordering;
}
- @Override public int compare(@Nullable T left, @Nullable T right) {
+ @Override
+ public int compare(@Nullable T left, @Nullable T right) {
if (left == right) {
return 0;
}
@@ -44,21 +45,25 @@ final class NullsFirstOrdering<T> extends Ordering<T> implements Serializable {
return ordering.compare(left, right);
}
- @Override public <S extends T> Ordering<S> reverse() {
+ @Override
+ public <S extends T> Ordering<S> reverse() {
// ordering.reverse() might be optimized, so let it do its thing
return ordering.reverse().nullsLast();
}
@SuppressWarnings("unchecked") // still need the right way to explain this
- @Override public <S extends T> Ordering<S> nullsFirst() {
+ @Override
+ public <S extends T> Ordering<S> nullsFirst() {
return (Ordering<S>) this;
}
- @Override public <S extends T> Ordering<S> nullsLast() {
+ @Override
+ public <S extends T> Ordering<S> nullsLast() {
return ordering.nullsLast();
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -69,11 +74,13 @@ final class NullsFirstOrdering<T> extends Ordering<T> implements Serializable {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return ordering.hashCode() ^ 957692532; // meaningless
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return ordering + ".nullsFirst()";
}
diff --git a/guava/src/com/google/common/collect/NullsLastOrdering.java b/guava/src/com/google/common/collect/NullsLastOrdering.java
index 9de17bd..a4b39db 100644
--- a/guava/src/com/google/common/collect/NullsLastOrdering.java
+++ b/guava/src/com/google/common/collect/NullsLastOrdering.java
@@ -31,7 +31,8 @@ final class NullsLastOrdering<T> extends Ordering<T> implements Serializable {
this.ordering = ordering;
}
- @Override public int compare(@Nullable T left, @Nullable T right) {
+ @Override
+ public int compare(@Nullable T left, @Nullable T right) {
if (left == right) {
return 0;
}
@@ -44,21 +45,25 @@ final class NullsLastOrdering<T> extends Ordering<T> implements Serializable {
return ordering.compare(left, right);
}
- @Override public <S extends T> Ordering<S> reverse() {
+ @Override
+ public <S extends T> Ordering<S> reverse() {
// ordering.reverse() might be optimized, so let it do its thing
return ordering.reverse().nullsFirst();
}
- @Override public <S extends T> Ordering<S> nullsFirst() {
+ @Override
+ public <S extends T> Ordering<S> nullsFirst() {
return ordering.nullsFirst();
}
@SuppressWarnings("unchecked") // still need the right way to explain this
- @Override public <S extends T> Ordering<S> nullsLast() {
+ @Override
+ public <S extends T> Ordering<S> nullsLast() {
return (Ordering<S>) this;
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -69,11 +74,13 @@ final class NullsLastOrdering<T> extends Ordering<T> implements Serializable {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return ordering.hashCode() ^ -921210296; // meaningless
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return ordering + ".nullsLast()";
}
diff --git a/guava/src/com/google/common/collect/ObjectArrays.java b/guava/src/com/google/common/collect/ObjectArrays.java
index 16f0e4e..2328002 100644
--- a/guava/src/com/google/common/collect/ObjectArrays.java
+++ b/guava/src/com/google/common/collect/ObjectArrays.java
@@ -30,7 +30,7 @@ import javax.annotation.Nullable;
* Static utility methods pertaining to object arrays.
*
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class ObjectArrays {
@@ -110,8 +110,7 @@ public final class ObjectArrays {
/** GWT safe version of Arrays.copyOf. */
static <T> T[] arraysCopyOf(T[] original, int newLength) {
T[] copy = newArray(original, newLength);
- System.arraycopy(
- original, 0, copy, 0, Math.min(original.length, newLength));
+ System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
@@ -150,7 +149,7 @@ public final class ObjectArrays {
}
return array;
}
-
+
/**
* Implementation of {@link Collection#toArray(Object[])} for collections backed by an object
* array. the runtime type of the returned array is that of the specified array. If the collection
@@ -225,7 +224,7 @@ public final class ObjectArrays {
static Object[] checkElementsNotNull(Object... array) {
return checkElementsNotNull(array, array.length);
}
-
+
static Object[] checkElementsNotNull(Object[] array, int length) {
for (int i = 0; i < length; i++) {
checkElementNotNull(array[i], i);
diff --git a/guava/src/com/google/common/collect/Ordering.java b/guava/src/com/google/common/collect/Ordering.java
index 8b15aef..f31a422 100644
--- a/guava/src/com/google/common/collect/Ordering.java
+++ b/guava/src/com/google/common/collect/Ordering.java
@@ -41,22 +41,30 @@ import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nullable;
/**
- * A comparator, with additional methods to support common operations. This is
- * an "enriched" version of {@code Comparator}, in the same sense that {@link
- * FluentIterable} is an enriched {@link Iterable}.
+ * A comparator, with additional methods to support common operations. This is an "enriched"
+ * version of {@code Comparator}, in the same sense that {@link FluentIterable} is an enriched
+ * {@link Iterable}.
+ *
+ * <h3>Three types of methods</h3>
+ *
+ * Like other fluent types, there are three types of methods present: methods for <i>acquiring</i>,
+ * <i>chaining</i>, and <i>using</i>.
+ *
+ * <h4>Acquiring</h4>
*
* <p>The common ways to get an instance of {@code Ordering} are:
*
* <ul>
- * <li>Subclass it and implement {@link #compare} instead of implementing
- * {@link Comparator} directly
- * <li>Pass a <i>pre-existing</i> {@link Comparator} instance to {@link
- * #from(Comparator)}
+ * <li>Subclass it and implement {@link #compare} instead of implementing {@link Comparator}
+ * directly
+ * <li>Pass a <i>pre-existing</i> {@link Comparator} instance to {@link #from(Comparator)}
* <li>Use the natural ordering, {@link Ordering#natural}
* </ul>
*
- * <p>Then you can use the <i>chaining</i> methods to get an altered version of
- * that {@code Ordering}, including:
+ * <h4>Chaining</h4>
+ *
+ * <p>Then you can use the <i>chaining</i> methods to get an altered version of that {@code
+ * Ordering}, including:
*
* <ul>
* <li>{@link #reverse}
@@ -65,8 +73,10 @@ import javax.annotation.Nullable;
* <li>{@link #nullsFirst} / {@link #nullsLast}
* </ul>
*
- * <p>Finally, use the resulting {@code Ordering} anywhere a {@link Comparator}
- * is required, or use any of its special operations, such as:</p>
+ * <h4>Using</h4>
+ *
+ * <p>Finally, use the resulting {@code Ordering} anywhere a {@link Comparator} is required, or use
+ * any of its special operations, such as:</p>
*
* <ul>
* <li>{@link #immutableSortedCopy}
@@ -74,18 +84,49 @@ import javax.annotation.Nullable;
* <li>{@link #min} / {@link #max}
* </ul>
*
+ * <h3>Understanding complex orderings</h3>
+ *
+ * <p>Complex chained orderings like the following example can be challenging to understand.
+ * <pre> {@code
+ *
+ * Ordering<Foo> ordering =
+ * Ordering.natural()
+ * .nullsFirst()
+ * .onResultOf(getBarFunction)
+ * .nullsLast();}</pre>
+ *
+ * Note that each chaining method returns a new ordering instance which is backed by the previous
+ * instance, but has the chance to act on values <i>before</i> handing off to that backing
+ * instance. As a result, it usually helps to read chained ordering expressions <i>backwards</i>.
+ * For example, when {@code compare} is called on the above ordering:
+ *
+ * <ol>
+ * <li>First, if only one {@code Foo} is null, that null value is treated as <i>greater</i>
+ * <li>Next, non-null {@code Foo} values are passed to {@code getBarFunction} (we will be
+ * comparing {@code Bar} values from now on)
+ * <li>Next, if only one {@code Bar} is null, that null value is treated as <i>lesser</i>
+ * <li>Finally, natural ordering is used (i.e. the result of {@code Bar.compareTo(Bar)} is
+ * returned)
+ * </ol>
+ *
+ * <p>Alas, {@link #reverse} is a little different. As you read backwards through a chain and
+ * encounter a call to {@code reverse}, continue working backwards until a result is determined,
+ * and then reverse that result.
+ *
+ * <h3>Additional notes</h3>
+ *
* <p>Except as noted, the orderings returned by the factory methods of this
* class are serializable if and only if the provided instances that back them
* are. For example, if {@code ordering} and {@code function} can themselves be
* serialized, then {@code ordering.onResultOf(function)} can as well.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/OrderingExplained">
+ * "https://github.com/google/guava/wiki/OrderingExplained">
* {@code Ordering}</a>.
*
* @author Jesse Wilson
* @author Kevin Bourrillion
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public abstract class Ordering<T> implements Comparator<T> {
@@ -132,7 +173,8 @@ public abstract class Ordering<T> implements Comparator<T> {
* @deprecated no need to use this
*/
@GwtCompatible(serializable = true)
- @Deprecated public static <T> Ordering<T> from(Ordering<T> ordering) {
+ @Deprecated
+ public static <T> Ordering<T> from(Ordering<T> ordering) {
return checkNotNull(ordering);
}
@@ -186,8 +228,7 @@ public abstract class Ordering<T> implements Comparator<T> {
* {@link Object#equals(Object)}) are present among the method arguments
*/
@GwtCompatible(serializable = true)
- public static <T> Ordering<T> explicit(
- T leastValue, T... remainingValuesInOrder) {
+ public static <T> Ordering<T> explicit(T leastValue, T... remainingValuesInOrder) {
return explicit(Lists.asList(leastValue, remainingValuesInOrder));
}
@@ -261,19 +302,24 @@ public abstract class Ordering<T> implements Comparator<T> {
static final Ordering<Object> ARBITRARY_ORDERING = new ArbitraryOrdering();
}
- @VisibleForTesting static class ArbitraryOrdering extends Ordering<Object> {
+ @VisibleForTesting
+ static class ArbitraryOrdering extends Ordering<Object> {
+
@SuppressWarnings("deprecation") // TODO(kevinb): ?
private Map<Object, Integer> uids =
- Platform.tryWeakKeys(new MapMaker()).makeComputingMap(
- new Function<Object, Integer>() {
- final AtomicInteger counter = new AtomicInteger(0);
- @Override
- public Integer apply(Object from) {
- return counter.getAndIncrement();
- }
- });
-
- @Override public int compare(Object left, Object right) {
+ Platform.tryWeakKeys(new MapMaker())
+ .makeComputingMap(
+ new Function<Object, Integer>() {
+ final AtomicInteger counter = new AtomicInteger(0);
+
+ @Override
+ public Integer apply(Object from) {
+ return counter.getAndIncrement();
+ }
+ });
+
+ @Override
+ public int compare(Object left, Object right) {
if (left == right) {
return 0;
} else if (left == null) {
@@ -295,7 +341,8 @@ public abstract class Ordering<T> implements Comparator<T> {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Ordering.arbitrary()";
}
@@ -385,8 +432,7 @@ public abstract class Ordering<T> implements Comparator<T> {
* the same component comparators.
*/
@GwtCompatible(serializable = true)
- public <U extends T> Ordering<U> compound(
- Comparator<? super U> secondaryComparator) {
+ public <U extends T> Ordering<U> compound(Comparator<? super U> secondaryComparator) {
return new CompoundOrdering<U>(this, checkNotNull(secondaryComparator));
}
@@ -406,8 +452,7 @@ public abstract class Ordering<T> implements Comparator<T> {
* @param comparators the comparators to try in order
*/
@GwtCompatible(serializable = true)
- public static <T> Ordering<T> compound(
- Iterable<? extends Comparator<? super T>> comparators) {
+ public static <T> Ordering<T> compound(Iterable<? extends Comparator<? super T>> comparators) {
return new CompoundOrdering<T>(comparators);
}
@@ -443,7 +488,8 @@ public abstract class Ordering<T> implements Comparator<T> {
// Regular instance methods
// Override to add @Nullable
- @Override public abstract int compare(@Nullable T left, @Nullable T right);
+ @Override
+ public abstract int compare(@Nullable T left, @Nullable T right);
/**
* Returns the least of the specified values according to this ordering. If
@@ -510,8 +556,7 @@ public abstract class Ordering<T> implements Comparator<T> {
* @throws ClassCastException if the parameters are not <i>mutually
* comparable</i> under this ordering.
*/
- public <E extends T> E min(
- @Nullable E a, @Nullable E b, @Nullable E c, E... rest) {
+ public <E extends T> E min(@Nullable E a, @Nullable E b, @Nullable E c, E... rest) {
E minSoFar = min(min(a, b), c);
for (E r : rest) {
@@ -586,8 +631,7 @@ public abstract class Ordering<T> implements Comparator<T> {
* @throws ClassCastException if the parameters are not <i>mutually
* comparable</i> under this ordering.
*/
- public <E extends T> E max(
- @Nullable E a, @Nullable E b, @Nullable E c, E... rest) {
+ public <E extends T> E max(@Nullable E a, @Nullable E b, @Nullable E c, E... rest) {
E maxSoFar = max(max(a, b), c);
for (E r : rest) {
@@ -737,8 +781,7 @@ public abstract class Ordering<T> implements Comparator<T> {
// We can't use ImmutableList; we have to be null-friendly!
}
- private <E extends T> int partition(
- E[] values, int left, int right, int pivotIndex) {
+ private <E extends T> int partition(E[] values, int left, int right, int pivotIndex) {
E pivotValue = values[pivotIndex];
values[pivotIndex] = values[right];
@@ -836,8 +879,7 @@ public abstract class Ordering<T> implements Comparator<T> {
* elements} itself) is null
* @since 3.0
*/
- public <E extends T> ImmutableList<E> immutableSortedCopy(
- Iterable<E> elements) {
+ public <E extends T> ImmutableList<E> immutableSortedCopy(Iterable<E> elements) {
@SuppressWarnings("unchecked") // we'll only ever have E's in here
E[] array = (E[]) Iterables.toArray(elements);
for (E e : array) {
diff --git a/guava/src/com/google/common/collect/PeekingIterator.java b/guava/src/com/google/common/collect/PeekingIterator.java
index 294b2e6..13442a9 100644
--- a/guava/src/com/google/common/collect/PeekingIterator.java
+++ b/guava/src/com/google/common/collect/PeekingIterator.java
@@ -23,13 +23,13 @@ import java.util.NoSuchElementException;
/**
* An iterator that supports a one-element lookahead while iterating.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionHelpersExplained#PeekingIterator">
+ * "https://github.com/google/guava/wiki/CollectionHelpersExplained#peekingiterator">
* {@code PeekingIterator}</a>.
*
* @author Mick Killianey
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public interface PeekingIterator<E> extends Iterator<E> {
diff --git a/guava/src/com/google/common/collect/Platform.java b/guava/src/com/google/common/collect/Platform.java
index 9fc907b..6e350b8 100644
--- a/guava/src/com/google/common/collect/Platform.java
+++ b/guava/src/com/google/common/collect/Platform.java
@@ -22,10 +22,12 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Maps.EntryTransformer;
import java.lang.reflect.Array;
+import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
+import java.util.Queue;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
@@ -53,7 +55,7 @@ final class Platform {
T[] result = (T[]) Array.newInstance(type, length);
return result;
}
-
+
static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
return Collections.newSetFromMap(map);
}
@@ -69,33 +71,35 @@ final class Platform {
}
static <K, V1, V2> SortedMap<K, V2> mapsTransformEntriesSortedMap(
- SortedMap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
+ SortedMap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) {
return (fromMap instanceof NavigableMap)
? Maps.transformEntries((NavigableMap<K, V1>) fromMap, transformer)
: Maps.transformEntriesIgnoreNavigable(fromMap, transformer);
}
- static <K, V> SortedMap<K, V> mapsAsMapSortedSet(SortedSet<K> set,
- Function<? super K, V> function) {
+ static <K, V> SortedMap<K, V> mapsAsMapSortedSet(
+ SortedSet<K> set, Function<? super K, V> function) {
return (set instanceof NavigableSet)
? Maps.asMap((NavigableSet<K>) set, function)
: Maps.asMapSortedIgnoreNavigable(set, function);
}
- static <E> SortedSet<E> setsFilterSortedSet(SortedSet<E> set,
- Predicate<? super E> predicate) {
+ static <E> SortedSet<E> setsFilterSortedSet(SortedSet<E> set, Predicate<? super E> predicate) {
return (set instanceof NavigableSet)
? Sets.filter((NavigableSet<E>) set, predicate)
: Sets.filterSortedIgnoreNavigable(set, predicate);
}
-
- static <K, V> SortedMap<K, V> mapsFilterSortedMap(SortedMap<K, V> map,
- Predicate<? super Map.Entry<K, V>> predicate) {
+
+ static <K, V> SortedMap<K, V> mapsFilterSortedMap(
+ SortedMap<K, V> map, Predicate<? super Map.Entry<K, V>> predicate) {
return (map instanceof NavigableMap)
? Maps.filterEntries((NavigableMap<K, V>) map, predicate)
: Maps.filterSortedIgnoreNavigable(map, predicate);
}
+ static <E> Queue<E> newFastestQueue(int initialCapacity) {
+ return new ArrayDeque<E>(initialCapacity);
+ }
+
private Platform() {}
}
diff --git a/guava/src/com/google/common/collect/Queues.java b/guava/src/com/google/common/collect/Queues.java
index 1507838..bc8c0de 100644
--- a/guava/src/com/google/common/collect/Queues.java
+++ b/guava/src/com/google/common/collect/Queues.java
@@ -257,8 +257,13 @@ public final class Queues {
* @throws InterruptedException if interrupted while waiting
*/
@Beta
- public static <E> int drain(BlockingQueue<E> q, Collection<? super E> buffer, int numElements,
- long timeout, TimeUnit unit) throws InterruptedException {
+ public static <E> int drain(
+ BlockingQueue<E> q,
+ Collection<? super E> buffer,
+ int numElements,
+ long timeout,
+ TimeUnit unit)
+ throws InterruptedException {
Preconditions.checkNotNull(buffer);
/*
* This code performs one System.nanoTime() more than necessary, and in return, the time to
@@ -282,13 +287,13 @@ public final class Queues {
}
return added;
}
-
+
/**
- * Drains the queue as {@linkplain #drain(BlockingQueue, Collection, int, long, TimeUnit)},
- * but with a different behavior in case it is interrupted while waiting. In that case, the
- * operation will continue as usual, and in the end the thread's interruption status will be set
- * (no {@code InterruptedException} is thrown).
- *
+ * Drains the queue as {@linkplain #drain(BlockingQueue, Collection, int, long, TimeUnit)},
+ * but with a different behavior in case it is interrupted while waiting. In that case, the
+ * operation will continue as usual, and in the end the thread's interruption status will be set
+ * (no {@code InterruptedException} is thrown).
+ *
* @param q the blocking queue to be drained
* @param buffer where to add the transferred elements
* @param numElements the number of elements to be waited for
@@ -297,15 +302,19 @@ public final class Queues {
* @return the number of elements transferred
*/
@Beta
- public static <E> int drainUninterruptibly(BlockingQueue<E> q, Collection<? super E> buffer,
- int numElements, long timeout, TimeUnit unit) {
+ public static <E> int drainUninterruptibly(
+ BlockingQueue<E> q,
+ Collection<? super E> buffer,
+ int numElements,
+ long timeout,
+ TimeUnit unit) {
Preconditions.checkNotNull(buffer);
long deadline = System.nanoTime() + unit.toNanos(timeout);
int added = 0;
boolean interrupted = false;
try {
while (added < numElements) {
- // we could rely solely on #poll, but #drainTo might be more efficient when there are
+ // we could rely solely on #poll, but #drainTo might be more efficient when there are
// multiple elements already available (e.g. LinkedBlockingQueue#drainTo locks only once)
added += q.drainTo(buffer, numElements - added);
if (added < numElements) { // not enough elements immediately available; will have to poll
diff --git a/guava/src/com/google/common/collect/Range.java b/guava/src/com/google/common/collect/Range.java
index bb81d7e..f967633 100644
--- a/guava/src/com/google/common/collect/Range.java
+++ b/guava/src/com/google/common/collect/Range.java
@@ -104,7 +104,7 @@ import javax.annotation.Nullable;
* <h3>Further reading</h3>
*
* <p>See the Guava User Guide article on
- * <a href="http://code.google.com/p/guava-libraries/wiki/RangesExplained">{@code Range}</a>.
+ * <a href="https://github.com/google/guava/wiki/RangesExplained">{@code Range}</a>.
*
* @author Kevin Bourrillion
* @author Gregory Kick
@@ -114,42 +114,35 @@ import javax.annotation.Nullable;
@SuppressWarnings("rawtypes")
public final class Range<C extends Comparable> implements Predicate<C>, Serializable {
- private static final Function<Range, Cut> LOWER_BOUND_FN = new Function<Range, Cut>() {
- @Override
- public Cut apply(Range range) {
- return range.lowerBound;
- }
- };
+ private static final Function<Range, Cut> LOWER_BOUND_FN =
+ new Function<Range, Cut>() {
+ @Override
+ public Cut apply(Range range) {
+ return range.lowerBound;
+ }
+ };
@SuppressWarnings("unchecked")
static <C extends Comparable<?>> Function<Range<C>, Cut<C>> lowerBoundFn() {
return (Function) LOWER_BOUND_FN;
}
- private static final Function<Range, Cut> UPPER_BOUND_FN = new Function<Range, Cut>() {
- @Override
- public Cut apply(Range range) {
- return range.upperBound;
- }
- };
+ private static final Function<Range, Cut> UPPER_BOUND_FN =
+ new Function<Range, Cut>() {
+ @Override
+ public Cut apply(Range range) {
+ return range.upperBound;
+ }
+ };
@SuppressWarnings("unchecked")
static <C extends Comparable<?>> Function<Range<C>, Cut<C>> upperBoundFn() {
return (Function) UPPER_BOUND_FN;
}
- static final Ordering<Range<?>> RANGE_LEX_ORDERING = new Ordering<Range<?>>() {
- @Override
- public int compare(Range<?> left, Range<?> right) {
- return ComparisonChain.start()
- .compare(left.lowerBound, right.lowerBound)
- .compare(left.upperBound, right.upperBound)
- .result();
- }
- };
+ static final Ordering<Range<?>> RANGE_LEX_ORDERING = new RangeLexOrdering();
- static <C extends Comparable<?>> Range<C> create(
- Cut<C> lowerBound, Cut<C> upperBound) {
+ static <C extends Comparable<?>> Range<C> create(Cut<C> lowerBound, Cut<C> upperBound) {
return new Range<C>(lowerBound, upperBound);
}
@@ -185,8 +178,7 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
* upper}
* @since 14.0
*/
- public static <C extends Comparable<?>> Range<C> closedOpen(
- C lower, C upper) {
+ public static <C extends Comparable<?>> Range<C> closedOpen(C lower, C upper) {
return create(Cut.belowValue(lower), Cut.belowValue(upper));
}
@@ -198,8 +190,7 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
* upper}
* @since 14.0
*/
- public static <C extends Comparable<?>> Range<C> openClosed(
- C lower, C upper) {
+ public static <C extends Comparable<?>> Range<C> openClosed(C lower, C upper) {
return create(Cut.aboveValue(lower), Cut.aboveValue(upper));
}
@@ -217,12 +208,10 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
checkNotNull(lowerType);
checkNotNull(upperType);
- Cut<C> lowerBound = (lowerType == BoundType.OPEN)
- ? Cut.aboveValue(lower)
- : Cut.belowValue(lower);
- Cut<C> upperBound = (upperType == BoundType.OPEN)
- ? Cut.belowValue(upper)
- : Cut.aboveValue(upper);
+ Cut<C> lowerBound =
+ (lowerType == BoundType.OPEN) ? Cut.aboveValue(lower) : Cut.belowValue(lower);
+ Cut<C> upperBound =
+ (upperType == BoundType.OPEN) ? Cut.belowValue(upper) : Cut.aboveValue(upper);
return create(lowerBound, upperBound);
}
@@ -252,8 +241,7 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
*
* @since 14.0
*/
- public static <C extends Comparable<?>> Range<C> upTo(
- C endpoint, BoundType boundType) {
+ public static <C extends Comparable<?>> Range<C> upTo(C endpoint, BoundType boundType) {
switch (boundType) {
case OPEN:
return lessThan(endpoint);
@@ -290,8 +278,7 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
*
* @since 14.0
*/
- public static <C extends Comparable<?>> Range<C> downTo(
- C endpoint, BoundType boundType) {
+ public static <C extends Comparable<?>> Range<C> downTo(C endpoint, BoundType boundType) {
switch (boundType) {
case OPEN:
return greaterThan(endpoint);
@@ -326,7 +313,7 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
return closed(value, value);
}
- /**
+ /**
* Returns the minimal range that
* {@linkplain Range#contains(Comparable) contains} all of the given values.
* The returned range is {@linkplain BoundType#CLOSED closed} on both ends.
@@ -337,8 +324,7 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
* @throws NullPointerException if any of {@code values} is null
* @since 14.0
*/
- public static <C extends Comparable<?>> Range<C> encloseAll(
- Iterable<C> values) {
+ public static <C extends Comparable<?>> Range<C> encloseAll(Iterable<C> values) {
checkNotNull(values);
if (values instanceof ContiguousSet) {
return ((ContiguousSet<C>) values).range();
@@ -358,12 +344,13 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
final Cut<C> upperBound;
private Range(Cut<C> lowerBound, Cut<C> upperBound) {
- if (lowerBound.compareTo(upperBound) > 0 || lowerBound == Cut.<C>aboveAll()
+ this.lowerBound = checkNotNull(lowerBound);
+ this.upperBound = checkNotNull(upperBound);
+ if (lowerBound.compareTo(upperBound) > 0
+ || lowerBound == Cut.<C>aboveAll()
|| upperBound == Cut.<C>belowAll()) {
throw new IllegalArgumentException("Invalid range: " + toString(lowerBound, upperBound));
}
- this.lowerBound = checkNotNull(lowerBound);
- this.upperBound = checkNotNull(upperBound);
}
/**
@@ -633,17 +620,18 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
* Similarly, empty ranges are not equal unless they have exactly the same representation, so
* {@code [3..3)}, {@code (3..3]}, {@code (4..4]} are all unequal.
*/
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object instanceof Range) {
Range<?> other = (Range<?>) object;
- return lowerBound.equals(other.lowerBound)
- && upperBound.equals(other.upperBound);
+ return lowerBound.equals(other.lowerBound) && upperBound.equals(other.upperBound);
}
return false;
}
/** Returns a hash code for this range. */
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return lowerBound.hashCode() * 31 + upperBound.hashCode();
}
@@ -651,7 +639,8 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
* Returns a string representation of this range, such as {@code "[3..5)"} (other examples are
* listed in the class documentation).
*/
- @Override public String toString() {
+ @Override
+ public String toString() {
return toString(lowerBound, upperBound);
}
@@ -683,5 +672,21 @@ public final class Range<C extends Comparable> implements Predicate<C>, Serializ
return left.compareTo(right);
}
+ /**
+ * Needed to serialize sorted collections of Ranges.
+ */
+ private static class RangeLexOrdering extends Ordering<Range<?>> implements Serializable {
+
+ @Override
+ public int compare(Range<?> left, Range<?> right) {
+ return ComparisonChain.start()
+ .compare(left.lowerBound, right.lowerBound)
+ .compare(left.upperBound, right.upperBound)
+ .result();
+ }
+
+ private static final long serialVersionUID = 0;
+ }
+
private static final long serialVersionUID = 0;
}
diff --git a/guava/src/com/google/common/collect/RangeMap.java b/guava/src/com/google/common/collect/RangeMap.java
index ba42985..ce41e6d 100644
--- a/guava/src/com/google/common/collect/RangeMap.java
+++ b/guava/src/com/google/common/collect/RangeMap.java
@@ -93,23 +93,39 @@ public interface RangeMap<K extends Comparable, V> {
* Returns a view of this range map as an unmodifiable {@code Map<Range<K>, V>}.
* Modifications to this range map are guaranteed to read through to the returned {@code Map}.
*
+ * <p>The returned {@code Map} iterates over entries in ascending order of the bounds of the
+ * {@code Range} entries.
+ *
* <p>It is guaranteed that no empty ranges will be in the returned {@code Map}.
*/
Map<Range<K>, V> asMapOfRanges();
-
+
+ /**
+ * Returns a view of this range map as an unmodifiable {@code Map<Range<K>, V>}.
+ * Modifications to this range map are guaranteed to read through to the returned {@code Map}.
+ *
+ * <p>The returned {@code Map} iterates over entries in descending order of the bounds of the
+ * {@code Range} entries.
+ *
+ * <p>It is guaranteed that no empty ranges will be in the returned {@code Map}.
+ *
+ * @since 19.0
+ */
+ Map<Range<K>, V> asDescendingMapOfRanges();
+
/**
* Returns a view of the part of this range map that intersects with {@code range}.
- *
- * <p>For example, if {@code rangeMap} had the entries
+ *
+ * <p>For example, if {@code rangeMap} had the entries
* {@code [1, 5] => "foo", (6, 8) => "bar", (10, \u2025) => "baz"}
* then {@code rangeMap.subRangeMap(Range.open(3, 12))} would return a range map
* with the entries {@code (3, 5) => "foo", (6, 8) => "bar", (10, 12) => "baz"}.
- *
+ *
* <p>The returned range map supports all optional operations that this range map supports,
* except for {@code asMapOfRanges().iterator().remove()}.
- *
- * <p>The returned range map will throw an {@link IllegalArgumentException} on an attempt to
- * insert a range not {@linkplain Range#encloses(Range) enclosed} by {@code range}.
+ *
+ * <p>The returned range map will throw an {@link IllegalArgumentException} on an attempt to
+ * insert a range not {@linkplain Range#encloses(Range) enclosed} by {@code range}.
*/
RangeMap<K, V> subRangeMap(Range<K> range);
diff --git a/guava/src/com/google/common/collect/RangeSet.java b/guava/src/com/google/common/collect/RangeSet.java
index 910597f..4d2523e 100644
--- a/guava/src/com/google/common/collect/RangeSet.java
+++ b/guava/src/com/google/common/collect/RangeSet.java
@@ -46,7 +46,7 @@ import javax.annotation.Nullable;
*/
@Beta
public interface RangeSet<C extends Comparable> {
-
+
// Query methods
/**
@@ -91,7 +91,7 @@ public interface RangeSet<C extends Comparable> {
Range<C> span();
// Views
-
+
/**
* Returns a view of the {@linkplain Range#isConnected disconnected} ranges that make up this
* range set. The returned set may be empty. The iterators returned by its
@@ -101,13 +101,23 @@ public interface RangeSet<C extends Comparable> {
Set<Range<C>> asRanges();
/**
+ * Returns a descending view of the {@linkplain Range#isConnected disconnected} ranges that
+ * make up this range set. The returned set may be empty. The iterators returned by its
+ * {@link Iterable#iterator} method return the ranges in decreasing order of lower bound
+ * (equivalently, of upper bound).
+ *
+ * @since 19.0
+ */
+ Set<Range<C>> asDescendingSetOfRanges();
+
+ /**
* Returns a view of the complement of this {@code RangeSet}.
*
* <p>The returned view supports the {@link #add} operation if this {@code RangeSet} supports
* {@link #remove}, and vice versa.
*/
RangeSet<C> complement();
-
+
/**
* Returns a view of the intersection of this {@code RangeSet} with the specified range.
*
@@ -117,7 +127,7 @@ public interface RangeSet<C extends Comparable> {
* {@code view}.
*/
RangeSet<C> subRangeSet(Range<C> view);
-
+
// Modification
/**
@@ -144,13 +154,13 @@ public interface RangeSet<C extends Comparable> {
* operation
*/
void remove(Range<C> range);
-
+
/**
* Removes all ranges from this {@code RangeSet} (optional operation). After this operation,
* {@code this.contains(c)} will return false for all {@code c}.
- *
+ *
* <p>This is equivalent to {@code remove(Range.all())}.
- *
+ *
* @throws UnsupportedOperationException if this range set does not support the {@code clear}
* operation
*/
@@ -180,7 +190,7 @@ public interface RangeSet<C extends Comparable> {
* operation
*/
void removeAll(RangeSet<C> other);
-
+
// Object methods
/**
@@ -189,7 +199,7 @@ public interface RangeSet<C extends Comparable> {
*/
@Override
boolean equals(@Nullable Object obj);
-
+
/**
* Returns {@code asRanges().hashCode()}.
*/
diff --git a/guava/src/com/google/common/collect/RegularContiguousSet.java b/guava/src/com/google/common/collect/RegularContiguousSet.java
index 94b72a0..428377f 100644
--- a/guava/src/com/google/common/collect/RegularContiguousSet.java
+++ b/guava/src/com/google/common/collect/RegularContiguousSet.java
@@ -47,31 +47,37 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
: new EmptyContiguousSet<C>(domain);
}
- @Override ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
+ @Override
+ ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
return intersectionInCurrentDomain(Range.upTo(toElement, BoundType.forBoolean(inclusive)));
}
- @Override ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive, C toElement,
- boolean toInclusive) {
+ @Override
+ ContiguousSet<C> subSetImpl(
+ C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
if (fromElement.compareTo(toElement) == 0 && !fromInclusive && !toInclusive) {
// Range would reject our attempt to create (x, x).
return new EmptyContiguousSet<C>(domain);
}
- return intersectionInCurrentDomain(Range.range(
- fromElement, BoundType.forBoolean(fromInclusive),
- toElement, BoundType.forBoolean(toInclusive)));
+ return intersectionInCurrentDomain(
+ Range.range(
+ fromElement, BoundType.forBoolean(fromInclusive),
+ toElement, BoundType.forBoolean(toInclusive)));
}
- @Override ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive) {
+ @Override
+ ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive) {
return intersectionInCurrentDomain(Range.downTo(fromElement, BoundType.forBoolean(inclusive)));
}
@GwtIncompatible("not used by GWT emulation")
- @Override int indexOf(Object target) {
+ @Override
+ int indexOf(Object target) {
return contains(target) ? (int) domain.distance(first(), (C) target) : -1;
}
- @Override public UnmodifiableIterator<C> iterator() {
+ @Override
+ public UnmodifiableIterator<C> iterator() {
return new AbstractSequentialIterator<C>(first()) {
final C last = last();
@@ -83,7 +89,8 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
}
@GwtIncompatible("NavigableSet")
- @Override public UnmodifiableIterator<C> descendingIterator() {
+ @Override
+ public UnmodifiableIterator<C> descendingIterator() {
return new AbstractSequentialIterator<C>(last()) {
final C first = first();
@@ -98,24 +105,29 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
return right != null && Range.compareOrThrow(left, right) == 0;
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return false;
}
- @Override public C first() {
+ @Override
+ public C first() {
return range.lowerBound.leastValueAbove(domain);
}
- @Override public C last() {
+ @Override
+ public C last() {
return range.upperBound.greatestValueBelow(domain);
}
- @Override public int size() {
+ @Override
+ public int size() {
long distance = domain.distance(first(), last());
return (distance >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) distance + 1;
}
- @Override public boolean contains(@Nullable Object object) {
+ @Override
+ public boolean contains(@Nullable Object object) {
if (object == null) {
return false;
}
@@ -126,15 +138,18 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
}
}
- @Override public boolean containsAll(Collection<?> targets) {
+ @Override
+ public boolean containsAll(Collection<?> targets) {
return Collections2.containsAllImpl(this, targets);
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public ContiguousSet<C> intersection(ContiguousSet<C> other) {
+ @Override
+ public ContiguousSet<C> intersection(ContiguousSet<C> other) {
checkNotNull(other);
checkArgument(this.domain.equals(other.domain));
if (other.isEmpty()) {
@@ -148,30 +163,34 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
}
}
- @Override public Range<C> range() {
+ @Override
+ public Range<C> range() {
return range(CLOSED, CLOSED);
}
- @Override public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
- return Range.create(range.lowerBound.withLowerBoundType(lowerBoundType, domain),
+ @Override
+ public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
+ return Range.create(
+ range.lowerBound.withLowerBoundType(lowerBoundType, domain),
range.upperBound.withUpperBoundType(upperBoundType, domain));
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
} else if (object instanceof RegularContiguousSet) {
RegularContiguousSet<?> that = (RegularContiguousSet<?>) object;
if (this.domain.equals(that.domain)) {
- return this.first().equals(that.first())
- && this.last().equals(that.last());
+ return this.first().equals(that.first()) && this.last().equals(that.last());
}
}
return super.equals(object);
}
// copied to make sure not to use the GWT-emulated version
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Sets.hashCodeImpl(this);
}
@@ -191,7 +210,8 @@ final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C>
}
@GwtIncompatible("serialization")
- @Override Object writeReplace() {
+ @Override
+ Object writeReplace() {
return new SerializedForm<C>(range, domain);
}
diff --git a/guava/src/com/google/common/collect/RegularImmutableAsList.java b/guava/src/com/google/common/collect/RegularImmutableAsList.java
index 041d53d..49c4c4d 100644
--- a/guava/src/com/google/common/collect/RegularImmutableAsList.java
+++ b/guava/src/com/google/common/collect/RegularImmutableAsList.java
@@ -18,6 +18,7 @@ package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.Weak;
/**
* An {@link ImmutableAsList} implementation specialized for when the delegate collection is
@@ -28,7 +29,7 @@ import com.google.common.annotations.GwtIncompatible;
@GwtCompatible(emulated = true)
@SuppressWarnings("serial") // uses writeReplace, not default serialization
class RegularImmutableAsList<E> extends ImmutableAsList<E> {
- private final ImmutableCollection<E> delegate;
+ @Weak private final ImmutableCollection<E> delegate;
private final ImmutableList<? extends E> delegateList;
RegularImmutableAsList(ImmutableCollection<E> delegate, ImmutableList<? extends E> delegateList) {
@@ -49,7 +50,7 @@ class RegularImmutableAsList<E> extends ImmutableAsList<E> {
return delegateList;
}
- @SuppressWarnings("unchecked") // safe covariant cast!
+ @SuppressWarnings("unchecked") // safe covariant cast!
@Override
public UnmodifiableListIterator<E> listIterator(int index) {
return (UnmodifiableListIterator<E>) delegateList.listIterator(index);
diff --git a/guava/src/com/google/common/collect/RegularImmutableBiMap.java b/guava/src/com/google/common/collect/RegularImmutableBiMap.java
index fe8d1d2..b405c91 100644
--- a/guava/src/com/google/common/collect/RegularImmutableBiMap.java
+++ b/guava/src/com/google/common/collect/RegularImmutableBiMap.java
@@ -16,102 +16,60 @@
package com.google.common.collect;
+import static com.google.common.base.Preconditions.checkPositionIndex;
import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
+import static com.google.common.collect.ImmutableMapEntry.createEntryArray;
+import static com.google.common.collect.RegularImmutableMap.checkNoConflictInKeyBucket;
import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.ImmutableMapEntry.TerminalEntry;
+import com.google.common.collect.ImmutableMapEntry.NonTerminalImmutableBiMapEntry;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import javax.annotation.Nullable;
/**
- * Bimap with two or more mappings.
+ * Bimap with zero or more mappings.
*
* @author Louis Wasserman
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // uses writeReplace(), not default serialization
class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
-
+ static final RegularImmutableBiMap<Object, Object> EMPTY =
+ new RegularImmutableBiMap<Object, Object>(
+ null, null, (Entry<Object, Object>[]) ImmutableMap.EMPTY_ENTRY_ARRAY, 0, 0);
+
static final double MAX_LOAD_FACTOR = 1.2;
-
+
private final transient ImmutableMapEntry<K, V>[] keyTable;
private final transient ImmutableMapEntry<K, V>[] valueTable;
- private final transient ImmutableMapEntry<K, V>[] entries;
+ private final transient Entry<K, V>[] entries;
private final transient int mask;
private final transient int hashCode;
-
- RegularImmutableBiMap(TerminalEntry<?, ?>... entriesToAdd) {
- this(entriesToAdd.length, entriesToAdd);
+
+ static <K, V> RegularImmutableBiMap<K, V> fromEntries(Entry<K, V>... entries) {
+ return fromEntryArray(entries.length, entries);
}
-
- /**
- * Constructor for RegularImmutableBiMap that takes as input an array of {@code TerminalEntry}
- * entries. Assumes that these entries have already been checked for null.
- *
- * <p>This allows reuse of the entry objects from the array in the actual implementation.
- */
- RegularImmutableBiMap(int n, TerminalEntry<?, ?>[] entriesToAdd) {
+
+ static <K, V> RegularImmutableBiMap<K, V> fromEntryArray(int n, Entry<K, V>[] entryArray) {
+ checkPositionIndex(n, entryArray.length);
int tableSize = Hashing.closedTableSize(n, MAX_LOAD_FACTOR);
- this.mask = tableSize - 1;
+ int mask = tableSize - 1;
ImmutableMapEntry<K, V>[] keyTable = createEntryArray(tableSize);
ImmutableMapEntry<K, V>[] valueTable = createEntryArray(tableSize);
- ImmutableMapEntry<K, V>[] entries = createEntryArray(n);
- int hashCode = 0;
-
- for (int i = 0; i < n; i++) {
- @SuppressWarnings("unchecked")
- TerminalEntry<K, V> entry = (TerminalEntry<K, V>) entriesToAdd[i];
- K key = entry.getKey();
- V value = entry.getValue();
-
- int keyHash = key.hashCode();
- int valueHash = value.hashCode();
- int keyBucket = Hashing.smear(keyHash) & mask;
- int valueBucket = Hashing.smear(valueHash) & mask;
-
- ImmutableMapEntry<K, V> nextInKeyBucket = keyTable[keyBucket];
- for (ImmutableMapEntry<K, V> keyEntry = nextInKeyBucket; keyEntry != null;
- keyEntry = keyEntry.getNextInKeyBucket()) {
- checkNoConflict(!key.equals(keyEntry.getKey()), "key", entry, keyEntry);
- }
- ImmutableMapEntry<K, V> nextInValueBucket = valueTable[valueBucket];
- for (ImmutableMapEntry<K, V> valueEntry = nextInValueBucket; valueEntry != null;
- valueEntry = valueEntry.getNextInValueBucket()) {
- checkNoConflict(!value.equals(valueEntry.getValue()), "value", entry, valueEntry);
- }
- ImmutableMapEntry<K, V> newEntry =
- (nextInKeyBucket == null && nextInValueBucket == null)
- ? entry
- : new NonTerminalBiMapEntry<K, V>(entry, nextInKeyBucket, nextInValueBucket);
- keyTable[keyBucket] = newEntry;
- valueTable[valueBucket] = newEntry;
- entries[i] = newEntry;
- hashCode += keyHash ^ valueHash;
+ Entry<K, V>[] entries;
+ if (n == entryArray.length) {
+ entries = entryArray;
+ } else {
+ entries = createEntryArray(n);
}
-
- this.keyTable = keyTable;
- this.valueTable = valueTable;
- this.entries = entries;
- this.hashCode = hashCode;
- }
-
- /**
- * Constructor for RegularImmutableBiMap that makes no assumptions about the input entries.
- */
- RegularImmutableBiMap(Entry<?, ?>[] entriesToAdd) {
- int n = entriesToAdd.length;
- int tableSize = Hashing.closedTableSize(n, MAX_LOAD_FACTOR);
- this.mask = tableSize - 1;
- ImmutableMapEntry<K, V>[] keyTable = createEntryArray(tableSize);
- ImmutableMapEntry<K, V>[] valueTable = createEntryArray(tableSize);
- ImmutableMapEntry<K, V>[] entries = createEntryArray(n);
int hashCode = 0;
-
+
for (int i = 0; i < n; i++) {
@SuppressWarnings("unchecked")
- Entry<K, V> entry = (Entry<K, V>) entriesToAdd[i];
+ Entry<K, V> entry = entryArray[i];
K key = entry.getKey();
V value = entry.getValue();
checkEntryNotNull(key, value);
@@ -119,114 +77,79 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
int valueHash = value.hashCode();
int keyBucket = Hashing.smear(keyHash) & mask;
int valueBucket = Hashing.smear(valueHash) & mask;
-
+
ImmutableMapEntry<K, V> nextInKeyBucket = keyTable[keyBucket];
- for (ImmutableMapEntry<K, V> keyEntry = nextInKeyBucket; keyEntry != null;
- keyEntry = keyEntry.getNextInKeyBucket()) {
- checkNoConflict(!key.equals(keyEntry.getKey()), "key", entry, keyEntry);
- }
+ checkNoConflictInKeyBucket(key, entry, nextInKeyBucket);
ImmutableMapEntry<K, V> nextInValueBucket = valueTable[valueBucket];
- for (ImmutableMapEntry<K, V> valueEntry = nextInValueBucket; valueEntry != null;
- valueEntry = valueEntry.getNextInValueBucket()) {
- checkNoConflict(!value.equals(valueEntry.getValue()), "value", entry, valueEntry);
+ checkNoConflictInValueBucket(value, entry, nextInValueBucket);
+ ImmutableMapEntry<K, V> newEntry;
+ if (nextInValueBucket == null && nextInKeyBucket == null) {
+ /*
+ * TODO(lowasser): consider using a NonTerminalImmutableMapEntry when nextInKeyBucket is
+ * nonnull but nextInValueBucket is null. This may save a few bytes on some platforms, but
+ * 2-morphic call sites are often optimized much better than 3-morphic, so it'd require
+ * benchmarking.
+ */
+ boolean reusable =
+ entry instanceof ImmutableMapEntry && ((ImmutableMapEntry<K, V>) entry).isReusable();
+ newEntry = reusable
+ ? (ImmutableMapEntry<K, V>) entry
+ : new ImmutableMapEntry<K, V>(key, value);
+ } else {
+ newEntry = new NonTerminalImmutableBiMapEntry<K, V>(
+ key, value, nextInKeyBucket, nextInValueBucket);
}
- ImmutableMapEntry<K, V> newEntry =
- (nextInKeyBucket == null && nextInValueBucket == null)
- ? new TerminalEntry<K, V>(key, value)
- : new NonTerminalBiMapEntry<K, V>(key, value, nextInKeyBucket, nextInValueBucket);
keyTable[keyBucket] = newEntry;
valueTable[valueBucket] = newEntry;
entries[i] = newEntry;
hashCode += keyHash ^ valueHash;
}
-
+ return new RegularImmutableBiMap<K, V>(keyTable, valueTable, entries, mask, hashCode);
+ }
+
+ private RegularImmutableBiMap(
+ ImmutableMapEntry<K, V>[] keyTable,
+ ImmutableMapEntry<K, V>[] valueTable,
+ Entry<K, V>[] entries,
+ int mask,
+ int hashCode) {
this.keyTable = keyTable;
this.valueTable = valueTable;
this.entries = entries;
+ this.mask = mask;
this.hashCode = hashCode;
}
-
- private static final class NonTerminalBiMapEntry<K, V> extends ImmutableMapEntry<K, V> {
- @Nullable private final ImmutableMapEntry<K, V> nextInKeyBucket;
- @Nullable private final ImmutableMapEntry<K, V> nextInValueBucket;
-
- NonTerminalBiMapEntry(K key, V value, @Nullable ImmutableMapEntry<K, V> nextInKeyBucket,
- @Nullable ImmutableMapEntry<K, V> nextInValueBucket) {
- super(key, value);
- this.nextInKeyBucket = nextInKeyBucket;
- this.nextInValueBucket = nextInValueBucket;
- }
- NonTerminalBiMapEntry(ImmutableMapEntry<K, V> contents,
- @Nullable ImmutableMapEntry<K, V> nextInKeyBucket,
- @Nullable ImmutableMapEntry<K, V> nextInValueBucket) {
- super(contents);
- this.nextInKeyBucket = nextInKeyBucket;
- this.nextInValueBucket = nextInValueBucket;
- }
+ // checkNoConflictInKeyBucket is static imported from RegularImmutableMap
- @Override
- @Nullable
- ImmutableMapEntry<K, V> getNextInKeyBucket() {
- return nextInKeyBucket;
+ private static void checkNoConflictInValueBucket(
+ Object value, Entry<?, ?> entry, @Nullable ImmutableMapEntry<?, ?> valueBucketHead) {
+ for (; valueBucketHead != null; valueBucketHead = valueBucketHead.getNextInValueBucket()) {
+ checkNoConflict(!value.equals(valueBucketHead.getValue()), "value", entry, valueBucketHead);
}
-
- @Override
- @Nullable
- ImmutableMapEntry<K, V> getNextInValueBucket() {
- return nextInValueBucket;
- }
- }
-
- @SuppressWarnings("unchecked")
- private static <K, V> ImmutableMapEntry<K, V>[] createEntryArray(int length) {
- return new ImmutableMapEntry[length];
}
@Override
@Nullable
public V get(@Nullable Object key) {
- if (key == null) {
- return null;
- }
- int bucket = Hashing.smear(key.hashCode()) & mask;
- for (ImmutableMapEntry<K, V> entry = keyTable[bucket]; entry != null;
- entry = entry.getNextInKeyBucket()) {
- if (key.equals(entry.getKey())) {
- return entry.getValue();
- }
- }
- return null;
+ return (keyTable == null) ? null : RegularImmutableMap.get(key, keyTable, mask);
}
@Override
ImmutableSet<Entry<K, V>> createEntrySet() {
- return new ImmutableMapEntrySet<K, V>() {
- @Override
- ImmutableMap<K, V> map() {
- return RegularImmutableBiMap.this;
- }
-
- @Override
- public UnmodifiableIterator<Entry<K, V>> iterator() {
- return asList().iterator();
- }
-
- @Override
- ImmutableList<Entry<K, V>> createAsList() {
- return new RegularImmutableAsList<Entry<K, V>>(this, entries);
- }
+ return isEmpty()
+ ? ImmutableSet.<Entry<K, V>>of()
+ : new ImmutableMapEntrySet.RegularEntrySet<K, V>(this, entries);
+ }
- @Override
- boolean isHashCodeFast() {
- return true;
- }
+ @Override
+ boolean isHashCodeFast() {
+ return true;
+ }
- @Override
- public int hashCode() {
- return hashCode;
- }
- };
+ @Override
+ public int hashCode() {
+ return hashCode;
}
@Override
@@ -238,15 +161,18 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
public int size() {
return entries.length;
}
-
+
private transient ImmutableBiMap<V, K> inverse;
@Override
public ImmutableBiMap<V, K> inverse() {
+ if (isEmpty()) {
+ return ImmutableBiMap.of();
+ }
ImmutableBiMap<V, K> result = inverse;
return (result == null) ? inverse = new Inverse() : result;
}
-
+
private final class Inverse extends ImmutableBiMap<V, K> {
@Override
@@ -261,12 +187,13 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
@Override
public K get(@Nullable Object value) {
- if (value == null) {
+ if (value == null || valueTable == null) {
return null;
}
int bucket = Hashing.smear(value.hashCode()) & mask;
- for (ImmutableMapEntry<K, V> entry = valueTable[bucket]; entry != null;
- entry = entry.getNextInValueBucket()) {
+ for (ImmutableMapEntry<K, V> entry = valueTable[bucket];
+ entry != null;
+ entry = entry.getNextInValueBucket()) {
if (value.equals(entry.getValue())) {
return entry.getKey();
}
@@ -278,7 +205,8 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
ImmutableSet<Entry<V, K>> createEntrySet() {
return new InverseEntrySet();
}
-
+
+ @WeakOuter
final class InverseEntrySet extends ImmutableMapEntrySet<V, K> {
@Override
ImmutableMap<V, K> map() {
@@ -321,24 +249,24 @@ class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
boolean isPartialView() {
return false;
}
-
+
@Override
Object writeReplace() {
return new InverseSerializedForm<K, V>(RegularImmutableBiMap.this);
}
}
-
+
private static class InverseSerializedForm<K, V> implements Serializable {
private final ImmutableBiMap<K, V> forward;
-
+
InverseSerializedForm(ImmutableBiMap<K, V> forward) {
this.forward = forward;
}
-
+
Object readResolve() {
return forward.inverse();
}
-
+
private static final long serialVersionUID = 1;
}
}
diff --git a/guava/src/com/google/common/collect/RegularImmutableList.java b/guava/src/com/google/common/collect/RegularImmutableList.java
index c06d7b7..9436f09 100644
--- a/guava/src/com/google/common/collect/RegularImmutableList.java
+++ b/guava/src/com/google/common/collect/RegularImmutableList.java
@@ -19,16 +19,17 @@ package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Preconditions;
-import javax.annotation.Nullable;
-
/**
- * Implementation of {@link ImmutableList} with one or more elements.
+ * Implementation of {@link ImmutableList} used for 0 or 2+ elements (not 1).
*
* @author Kevin Bourrillion
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // uses writeReplace(), not default serialization
class RegularImmutableList<E> extends ImmutableList<E> {
+ static final ImmutableList<Object> EMPTY =
+ new RegularImmutableList<Object>(ObjectArrays.EMPTY_ARRAY);
+
private final transient int offset;
private final transient int size;
private final transient Object[] array;
@@ -48,7 +49,8 @@ class RegularImmutableList<E> extends ImmutableList<E> {
return size;
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return size != array.length;
}
@@ -67,35 +69,8 @@ class RegularImmutableList<E> extends ImmutableList<E> {
}
@Override
- public int indexOf(@Nullable Object object) {
- if (object == null) {
- return -1;
- }
- for (int i = 0; i < size; i++) {
- if (array[offset + i].equals(object)) {
- return i;
- }
- }
- return -1;
- }
-
- @Override
- public int lastIndexOf(@Nullable Object object) {
- if (object == null) {
- return -1;
- }
- for (int i = size - 1; i >= 0; i--) {
- if (array[offset + i].equals(object)) {
- return i;
- }
- }
- return -1;
- }
-
- @Override
ImmutableList<E> subListUnchecked(int fromIndex, int toIndex) {
- return new RegularImmutableList<E>(
- array, offset + fromIndex, toIndex - fromIndex);
+ return new RegularImmutableList<E>(array, offset + fromIndex, toIndex - fromIndex);
}
@SuppressWarnings("unchecked")
@@ -103,9 +78,8 @@ class RegularImmutableList<E> extends ImmutableList<E> {
public UnmodifiableListIterator<E> listIterator(int index) {
// for performance
// The fake cast to E is safe because the creation methods only allow E's
- return (UnmodifiableListIterator<E>)
- Iterators.forArray(array, offset, size, index);
+ return (UnmodifiableListIterator<E>) Iterators.forArray(array, offset, size, index);
}
- // TODO(user): benchmark optimizations for equals() and see if they're worthwhile
+ // TODO(lowasser): benchmark optimizations for equals() and see if they're worthwhile
}
diff --git a/guava/src/com/google/common/collect/RegularImmutableMap.java b/guava/src/com/google/common/collect/RegularImmutableMap.java
index b594be9..4c2cdfa 100644
--- a/guava/src/com/google/common/collect/RegularImmutableMap.java
+++ b/guava/src/com/google/common/collect/RegularImmutableMap.java
@@ -1,5 +1,5 @@
/*
-* Copyright (C) 2008 The Guava Authors
+ * Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,12 @@
package com.google.common.collect;
+import static com.google.common.base.Preconditions.checkPositionIndex;
import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
+import static com.google.common.collect.ImmutableMapEntry.createEntryArray;
import com.google.common.annotations.GwtCompatible;
-import com.google.common.collect.ImmutableMapEntry.TerminalEntry;
+import com.google.common.collect.ImmutableMapEntry.NonTerminalImmutableMapEntry;
import javax.annotation.Nullable;
@@ -34,101 +36,67 @@ import javax.annotation.Nullable;
final class RegularImmutableMap<K, V> extends ImmutableMap<K, V> {
// entries in insertion order
- private final transient ImmutableMapEntry<K, V>[] entries;
+ private final transient Entry<K, V>[] entries;
// array of linked lists of entries
private final transient ImmutableMapEntry<K, V>[] table;
// 'and' with an int to get a table index
private final transient int mask;
-
- RegularImmutableMap(TerminalEntry<?, ?>... theEntries) {
- this(theEntries.length, theEntries);
+
+ static <K, V> RegularImmutableMap<K, V> fromEntries(Entry<K, V>... entries) {
+ return fromEntryArray(entries.length, entries);
}
-
+
/**
- * Constructor for RegularImmutableMap that takes as input an array of {@code TerminalEntry}
- * entries. Assumes that these entries have already been checked for null.
- *
- * <p>This allows reuse of the entry objects from the array in the actual implementation.
+ * Creates a RegularImmutableMap from the first n entries in entryArray. This implementation
+ * may replace the entries in entryArray with its own entry objects (though they will have the
+ * same key/value contents), and may take ownership of entryArray.
*/
- RegularImmutableMap(int size, TerminalEntry<?, ?>[] theEntries) {
- entries = createEntryArray(size);
- int tableSize = Hashing.closedTableSize(size, MAX_LOAD_FACTOR);
- table = createEntryArray(tableSize);
- mask = tableSize - 1;
- for (int entryIndex = 0; entryIndex < size; entryIndex++) {
- @SuppressWarnings("unchecked")
- TerminalEntry<K, V> entry = (TerminalEntry<K, V>) theEntries[entryIndex];
- K key = entry.getKey();
- int tableIndex = Hashing.smear(key.hashCode()) & mask;
- @Nullable ImmutableMapEntry<K, V> existing = table[tableIndex];
- // prepend, not append, so the entries can be immutable
- ImmutableMapEntry<K, V> newEntry = (existing == null)
- ? entry
- : new NonTerminalMapEntry<K, V>(entry, existing);
- table[tableIndex] = newEntry;
- entries[entryIndex] = newEntry;
- checkNoConflictInBucket(key, newEntry, existing);
+ static <K, V> RegularImmutableMap<K, V> fromEntryArray(int n, Entry<K, V>[] entryArray) {
+ checkPositionIndex(n, entryArray.length);
+ Entry<K, V>[] entries;
+ if (n == entryArray.length) {
+ entries = entryArray;
+ } else {
+ entries = createEntryArray(n);
}
- }
-
- /**
- * Constructor for RegularImmutableMap that makes no assumptions about the input entries.
- */
- RegularImmutableMap(Entry<?, ?>[] theEntries) {
- int size = theEntries.length;
- entries = createEntryArray(size);
- int tableSize = Hashing.closedTableSize(size, MAX_LOAD_FACTOR);
- table = createEntryArray(tableSize);
- mask = tableSize - 1;
- for (int entryIndex = 0; entryIndex < size; entryIndex++) {
- @SuppressWarnings("unchecked") // all our callers carefully put in only Entry<K, V>s
- Entry<K, V> entry = (Entry<K, V>) theEntries[entryIndex];
+ int tableSize = Hashing.closedTableSize(n, MAX_LOAD_FACTOR);
+ ImmutableMapEntry<K, V>[] table = createEntryArray(tableSize);
+ int mask = tableSize - 1;
+ for (int entryIndex = 0; entryIndex < n; entryIndex++) {
+ Entry<K, V> entry = entryArray[entryIndex];
K key = entry.getKey();
V value = entry.getValue();
checkEntryNotNull(key, value);
int tableIndex = Hashing.smear(key.hashCode()) & mask;
@Nullable ImmutableMapEntry<K, V> existing = table[tableIndex];
// prepend, not append, so the entries can be immutable
- ImmutableMapEntry<K, V> newEntry = (existing == null)
- ? new TerminalEntry<K, V>(key, value)
- : new NonTerminalMapEntry<K, V>(key, value, existing);
+ ImmutableMapEntry<K, V> newEntry;
+ if (existing == null) {
+ boolean reusable =
+ entry instanceof ImmutableMapEntry && ((ImmutableMapEntry<K, V>) entry).isReusable();
+ newEntry =
+ reusable ? (ImmutableMapEntry<K, V>) entry : new ImmutableMapEntry<K, V>(key, value);
+ } else {
+ newEntry = new NonTerminalImmutableMapEntry<K, V>(key, value, existing);
+ }
table[tableIndex] = newEntry;
entries[entryIndex] = newEntry;
- checkNoConflictInBucket(key, newEntry, existing);
+ checkNoConflictInKeyBucket(key, newEntry, existing);
}
+ return new RegularImmutableMap<K, V>(entries, table, mask);
}
- private void checkNoConflictInBucket(
- K key, ImmutableMapEntry<K, V> entry, ImmutableMapEntry<K, V> bucketHead) {
- for (; bucketHead != null; bucketHead = bucketHead.getNextInKeyBucket()) {
- checkNoConflict(!key.equals(bucketHead.getKey()), "key", entry, bucketHead);
- }
+ private RegularImmutableMap(Entry<K, V>[] entries, ImmutableMapEntry<K, V>[] table, int mask) {
+ this.entries = entries;
+ this.table = table;
+ this.mask = mask;
}
-
- private static final class NonTerminalMapEntry<K, V> extends ImmutableMapEntry<K, V> {
- private final ImmutableMapEntry<K, V> nextInKeyBucket;
-
- NonTerminalMapEntry(K key, V value, ImmutableMapEntry<K, V> nextInKeyBucket) {
- super(key, value);
- this.nextInKeyBucket = nextInKeyBucket;
- }
-
- NonTerminalMapEntry(ImmutableMapEntry<K, V> contents, ImmutableMapEntry<K, V> nextInKeyBucket) {
- super(contents);
- this.nextInKeyBucket = nextInKeyBucket;
- }
-
- @Override
- ImmutableMapEntry<K, V> getNextInKeyBucket() {
- return nextInKeyBucket;
- }
- @Override
- @Nullable
- ImmutableMapEntry<K, V> getNextInValueBucket() {
- return null;
+ static void checkNoConflictInKeyBucket(
+ Object key, Entry<?, ?> entry, @Nullable ImmutableMapEntry<?, ?> keyBucketHead) {
+ for (; keyBucketHead != null; keyBucketHead = keyBucketHead.getNextInKeyBucket()) {
+ checkNoConflict(!key.equals(keyBucketHead.getKey()), "key", entry, keyBucketHead);
}
-
}
/**
@@ -138,25 +106,21 @@ final class RegularImmutableMap<K, V> extends ImmutableMap<K, V> {
*/
private static final double MAX_LOAD_FACTOR = 1.2;
- /**
- * Creates an {@code ImmutableMapEntry} array to hold parameterized entries. The
- * result must never be upcast back to ImmutableMapEntry[] (or Object[], etc.), or
- * allowed to escape the class.
- */
- @SuppressWarnings("unchecked") // Safe as long as the javadocs are followed
- private ImmutableMapEntry<K, V>[] createEntryArray(int size) {
- return new ImmutableMapEntry[size];
+ @Override
+ public V get(@Nullable Object key) {
+ return get(key, table, mask);
}
- @Override public V get(@Nullable Object key) {
+ @Nullable
+ static <V> V get(@Nullable Object key, ImmutableMapEntry<?, V>[] keyTable, int mask) {
if (key == null) {
return null;
}
int index = Hashing.smear(key.hashCode()) & mask;
- for (ImmutableMapEntry<K, V> entry = table[index];
+ for (ImmutableMapEntry<?, V> entry = keyTable[index];
entry != null;
entry = entry.getNextInKeyBucket()) {
- K candidateKey = entry.getKey();
+ Object candidateKey = entry.getKey();
/*
* Assume that equals uses the == optimization when appropriate, and that
@@ -175,31 +139,15 @@ final class RegularImmutableMap<K, V> extends ImmutableMap<K, V> {
public int size() {
return entries.length;
}
-
- @Override boolean isPartialView() {
+
+ @Override
+ boolean isPartialView() {
return false;
}
@Override
ImmutableSet<Entry<K, V>> createEntrySet() {
- return new EntrySet();
- }
-
- @SuppressWarnings("serial") // uses writeReplace(), not default serialization
- private class EntrySet extends ImmutableMapEntrySet<K, V> {
- @Override ImmutableMap<K, V> map() {
- return RegularImmutableMap.this;
- }
-
- @Override
- public UnmodifiableIterator<Entry<K, V>> iterator() {
- return asList().iterator();
- }
-
- @Override
- ImmutableList<Entry<K, V>> createAsList() {
- return new RegularImmutableAsList<Entry<K, V>>(this, entries);
- }
+ return new ImmutableMapEntrySet.RegularEntrySet<K, V>(this, entries);
}
// This class is never actually serialized directly, but we have to make the
diff --git a/guava/src/com/google/common/collect/RegularImmutableMultiset.java b/guava/src/com/google/common/collect/RegularImmutableMultiset.java
index 552c774..5181f57 100644
--- a/guava/src/com/google/common/collect/RegularImmutableMultiset.java
+++ b/guava/src/com/google/common/collect/RegularImmutableMultiset.java
@@ -1,24 +1,28 @@
/*
* Copyright (C) 2011 The Guava Authors
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
*/
package com.google.common.collect;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Objects;
+import com.google.common.collect.Multisets.ImmutableEntry;
+import com.google.common.primitives.Ints;
+import com.google.j2objc.annotations.WeakOuter;
-import java.util.Map;
+import java.util.Collection;
import javax.annotation.Nullable;
@@ -29,26 +33,101 @@ import javax.annotation.Nullable;
* @author Louis Wasserman
*/
@GwtCompatible(serializable = true)
- at SuppressWarnings("serial")
-// uses writeReplace(), not default serialization
+ at SuppressWarnings("serial") // uses writeReplace(), not default serialization
class RegularImmutableMultiset<E> extends ImmutableMultiset<E> {
- private final transient ImmutableMap<E, Integer> map;
+ static final RegularImmutableMultiset<Object> EMPTY =
+ new RegularImmutableMultiset<Object>(ImmutableList.<Entry<Object>>of());
+
+ private final transient Multisets.ImmutableEntry<E>[] entries;
+ private final transient Multisets.ImmutableEntry<E>[] hashTable;
private final transient int size;
+ private final transient int hashCode;
+
+ private transient ImmutableSet<E> elementSet;
+
+ RegularImmutableMultiset(Collection<? extends Entry<? extends E>> entries) {
+ int distinct = entries.size();
+ @SuppressWarnings("unchecked")
+ Multisets.ImmutableEntry<E>[] entryArray = new Multisets.ImmutableEntry[distinct];
+ if (distinct == 0) {
+ this.entries = entryArray;
+ this.hashTable = null;
+ this.size = 0;
+ this.hashCode = 0;
+ this.elementSet = ImmutableSet.of();
+ } else {
+ int tableSize = Hashing.closedTableSize(distinct, 1.0);
+ int mask = tableSize - 1;
+ @SuppressWarnings("unchecked")
+ Multisets.ImmutableEntry<E>[] hashTable = new Multisets.ImmutableEntry[tableSize];
+
+ int index = 0;
+ int hashCode = 0;
+ long size = 0;
+ for (Entry<? extends E> entry : entries) {
+ E element = checkNotNull(entry.getElement());
+ int count = entry.getCount();
+ int hash = element.hashCode();
+ int bucket = Hashing.smear(hash) & mask;
+ Multisets.ImmutableEntry<E> bucketHead = hashTable[bucket];
+ Multisets.ImmutableEntry<E> newEntry;
+ if (bucketHead == null) {
+ boolean canReuseEntry =
+ entry instanceof Multisets.ImmutableEntry && !(entry instanceof NonTerminalEntry);
+ newEntry =
+ canReuseEntry
+ ? (Multisets.ImmutableEntry<E>) entry
+ : new Multisets.ImmutableEntry<E>(element, count);
+ } else {
+ newEntry = new NonTerminalEntry<E>(element, count, bucketHead);
+ }
+ hashCode += hash ^ count;
+ entryArray[index++] = newEntry;
+ hashTable[bucket] = newEntry;
+ size += count;
+ }
+ this.entries = entryArray;
+ this.hashTable = hashTable;
+ this.size = Ints.saturatedCast(size);
+ this.hashCode = hashCode;
+ }
+ }
+
+ private static final class NonTerminalEntry<E> extends Multisets.ImmutableEntry<E> {
+ private final Multisets.ImmutableEntry<E> nextInBucket;
+
+ NonTerminalEntry(E element, int count, ImmutableEntry<E> nextInBucket) {
+ super(element, count);
+ this.nextInBucket = nextInBucket;
+ }
- RegularImmutableMultiset(ImmutableMap<E, Integer> map, int size) {
- this.map = map;
- this.size = size;
+ @Override
+ public ImmutableEntry<E> nextInBucket() {
+ return nextInBucket;
+ }
}
@Override
boolean isPartialView() {
- return map.isPartialView();
+ return false;
}
@Override
public int count(@Nullable Object element) {
- Integer value = map.get(element);
- return (value == null) ? 0 : value;
+ Multisets.ImmutableEntry<E>[] hashTable = this.hashTable;
+ if (element == null || hashTable == null) {
+ return 0;
+ }
+ int hash = Hashing.smearedHash(element);
+ int mask = hashTable.length - 1;
+ for (Multisets.ImmutableEntry<E> entry = hashTable[hash & mask];
+ entry != null;
+ entry = entry.nextInBucket()) {
+ if (Objects.equal(element, entry.getElement())) {
+ return entry.getCount();
+ }
+ }
+ return 0;
}
@Override
@@ -57,23 +136,42 @@ class RegularImmutableMultiset<E> extends ImmutableMultiset<E> {
}
@Override
- public boolean contains(@Nullable Object element) {
- return map.containsKey(element);
+ public ImmutableSet<E> elementSet() {
+ ImmutableSet<E> result = elementSet;
+ return (result == null) ? elementSet = new ElementSet() : result;
}
- @Override
- public ImmutableSet<E> elementSet() {
- return map.keySet();
+ @WeakOuter
+ private final class ElementSet extends ImmutableSet.Indexed<E> {
+
+ @Override
+ E get(int index) {
+ return entries[index].getElement();
+ }
+
+ @Override
+ public boolean contains(@Nullable Object object) {
+ return RegularImmutableMultiset.this.contains(object);
+ }
+
+ @Override
+ boolean isPartialView() {
+ return true;
+ }
+
+ @Override
+ public int size() {
+ return entries.length;
+ }
}
@Override
Entry<E> getEntry(int index) {
- Map.Entry<E, Integer> mapEntry = map.entrySet().asList().get(index);
- return Multisets.immutableEntry(mapEntry.getKey(), mapEntry.getValue());
+ return entries[index];
}
@Override
public int hashCode() {
- return map.hashCode();
+ return hashCode;
}
}
diff --git a/guava/src/com/google/common/collect/RegularImmutableSet.java b/guava/src/com/google/common/collect/RegularImmutableSet.java
index f3cbb55..9bf70d7 100644
--- a/guava/src/com/google/common/collect/RegularImmutableSet.java
+++ b/guava/src/com/google/common/collect/RegularImmutableSet.java
@@ -19,6 +19,8 @@ package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.VisibleForTesting;
+import javax.annotation.Nullable;
+
/**
* Implementation of {@link ImmutableSet} with two or more elements.
*
@@ -27,31 +29,35 @@ import com.google.common.annotations.VisibleForTesting;
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // uses writeReplace(), not default serialization
final class RegularImmutableSet<E> extends ImmutableSet<E> {
- private final Object[] elements;
+ static final RegularImmutableSet<Object> EMPTY =
+ new RegularImmutableSet<Object>(ObjectArrays.EMPTY_ARRAY, 0, null, 0);
+
+ private final transient Object[] elements;
// the same elements in hashed positions (plus nulls)
@VisibleForTesting final transient Object[] table;
// 'and' with an int to get a valid table index.
private final transient int mask;
private final transient int hashCode;
- RegularImmutableSet(
- Object[] elements, int hashCode, Object[] table, int mask) {
+ RegularImmutableSet(Object[] elements, int hashCode, Object[] table, int mask) {
this.elements = elements;
this.table = table;
this.mask = mask;
this.hashCode = hashCode;
}
- @Override public boolean contains(Object target) {
- if (target == null) {
+ @Override
+ public boolean contains(@Nullable Object target) {
+ Object[] table = this.table;
+ if (target == null || table == null) {
return false;
}
- for (int i = Hashing.smear(target.hashCode()); true; i++) {
- Object candidate = table[i & mask];
+ for (int i = Hashing.smearedHash(target); ; i++) {
+ i &= mask;
+ Object candidate = table[i];
if (candidate == null) {
return false;
- }
- if (candidate.equals(target)) {
+ } else if (candidate.equals(target)) {
return true;
}
}
@@ -76,7 +82,7 @@ final class RegularImmutableSet<E> extends ImmutableSet<E> {
@Override
ImmutableList<E> createAsList() {
- return new RegularImmutableAsList<E>(this, elements);
+ return (table == null) ? ImmutableList.<E>of() : new RegularImmutableAsList<E>(this, elements);
}
@Override
@@ -84,11 +90,13 @@ final class RegularImmutableSet<E> extends ImmutableSet<E> {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return hashCode;
}
- @Override boolean isHashCodeFast() {
+ @Override
+ boolean isHashCodeFast() {
return true;
}
}
diff --git a/guava/src/com/google/common/collect/RegularImmutableSortedMap.java b/guava/src/com/google/common/collect/RegularImmutableSortedMap.java
deleted file mode 100644
index dd93b7f..0000000
--- a/guava/src/com/google/common/collect/RegularImmutableSortedMap.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2012 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.google.common.collect;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.common.annotations.GwtCompatible;
-
-import javax.annotation.Nullable;
-
-/**
- * An implementation of an immutable sorted map with one or more entries.
- *
- * @author Louis Wasserman
- */
- at GwtCompatible(emulated = true)
- at SuppressWarnings("serial") // uses writeReplace, not default serialization
-final class RegularImmutableSortedMap<K, V> extends ImmutableSortedMap<K, V> {
- private final transient RegularImmutableSortedSet<K> keySet;
- private final transient ImmutableList<V> valueList;
-
- RegularImmutableSortedMap(RegularImmutableSortedSet<K> keySet, ImmutableList<V> valueList) {
- this.keySet = keySet;
- this.valueList = valueList;
- }
-
- RegularImmutableSortedMap(
- RegularImmutableSortedSet<K> keySet,
- ImmutableList<V> valueList,
- ImmutableSortedMap<K, V> descendingMap) {
- super(descendingMap);
- this.keySet = keySet;
- this.valueList = valueList;
- }
-
- @Override
- ImmutableSet<Entry<K, V>> createEntrySet() {
- return new EntrySet();
- }
-
- private class EntrySet extends ImmutableMapEntrySet<K, V> {
- @Override
- public UnmodifiableIterator<Entry<K, V>> iterator() {
- return asList().iterator();
- }
-
- @Override
- ImmutableList<Entry<K, V>> createAsList() {
- return new ImmutableAsList<Entry<K, V>>() {
- // avoid additional indirection
- private final ImmutableList<K> keyList = keySet().asList();
-
- @Override
- public Entry<K, V> get(int index) {
- return Maps.immutableEntry(keyList.get(index), valueList.get(index));
- }
-
- @Override
- ImmutableCollection<Entry<K, V>> delegateCollection() {
- return EntrySet.this;
- }
- };
- }
-
- @Override
- ImmutableMap<K, V> map() {
- return RegularImmutableSortedMap.this;
- }
- }
-
- @Override
- public ImmutableSortedSet<K> keySet() {
- return keySet;
- }
-
- @Override
- public ImmutableCollection<V> values() {
- return valueList;
- }
-
- @Override
- public V get(@Nullable Object key) {
- int index = keySet.indexOf(key);
- return (index == -1) ? null : valueList.get(index);
- }
-
- private ImmutableSortedMap<K, V> getSubMap(int fromIndex, int toIndex) {
- if (fromIndex == 0 && toIndex == size()) {
- return this;
- } else if (fromIndex == toIndex) {
- return emptyMap(comparator());
- } else {
- return from(
- keySet.getSubSet(fromIndex, toIndex),
- valueList.subList(fromIndex, toIndex));
- }
- }
-
- @Override
- public ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive) {
- return getSubMap(0, keySet.headIndex(checkNotNull(toKey), inclusive));
- }
-
- @Override
- public ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive) {
- return getSubMap(keySet.tailIndex(checkNotNull(fromKey), inclusive), size());
- }
-
- @Override
- ImmutableSortedMap<K, V> createDescendingMap() {
- return new RegularImmutableSortedMap<K, V>(
- (RegularImmutableSortedSet<K>) keySet.descendingSet(),
- valueList.reverse(),
- this);
- }
-
-}
diff --git a/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java b/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java
index 5ef3e0d..bf39c07 100644
--- a/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java
+++ b/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java
@@ -20,6 +20,8 @@ import static com.google.common.collect.BoundType.CLOSED;
import com.google.common.primitives.Ints;
+import java.util.Comparator;
+
import javax.annotation.Nullable;
/**
@@ -29,46 +31,51 @@ import javax.annotation.Nullable;
*/
@SuppressWarnings("serial") // uses writeReplace, not default serialization
final class RegularImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E> {
+ private static final long[] ZERO_CUMULATIVE_COUNTS = {0};
+
private final transient RegularImmutableSortedSet<E> elementSet;
- private final transient int[] counts;
private final transient long[] cumulativeCounts;
private final transient int offset;
private final transient int length;
+ RegularImmutableSortedMultiset(Comparator<? super E> comparator) {
+ this.elementSet = ImmutableSortedSet.emptySet(comparator);
+ this.cumulativeCounts = ZERO_CUMULATIVE_COUNTS;
+ this.offset = 0;
+ this.length = 0;
+ }
+
RegularImmutableSortedMultiset(
- RegularImmutableSortedSet<E> elementSet,
- int[] counts,
- long[] cumulativeCounts,
- int offset,
- int length) {
+ RegularImmutableSortedSet<E> elementSet, long[] cumulativeCounts, int offset, int length) {
this.elementSet = elementSet;
- this.counts = counts;
this.cumulativeCounts = cumulativeCounts;
this.offset = offset;
this.length = length;
}
+ private int getCount(int index) {
+ return (int) (cumulativeCounts[offset + index + 1] - cumulativeCounts[offset + index]);
+ }
+
@Override
Entry<E> getEntry(int index) {
- return Multisets.immutableEntry(
- elementSet.asList().get(index),
- counts[offset + index]);
+ return Multisets.immutableEntry(elementSet.asList().get(index), getCount(index));
}
@Override
public Entry<E> firstEntry() {
- return getEntry(0);
+ return isEmpty() ? null : getEntry(0);
}
@Override
public Entry<E> lastEntry() {
- return getEntry(length - 1);
+ return isEmpty() ? null : getEntry(length - 1);
}
@Override
public int count(@Nullable Object element) {
int index = elementSet.indexOf(element);
- return (index == -1) ? 0 : counts[index + offset];
+ return (index >= 0) ? getCount(index) : 0;
}
@Override
@@ -89,8 +96,8 @@ final class RegularImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E>
@Override
public ImmutableSortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
- return getSubMultiset(elementSet.tailIndex(lowerBound, checkNotNull(boundType) == CLOSED),
- length);
+ return getSubMultiset(
+ elementSet.tailIndex(lowerBound, checkNotNull(boundType) == CLOSED), length);
}
ImmutableSortedMultiset<E> getSubMultiset(int from, int to) {
@@ -103,12 +110,12 @@ final class RegularImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E>
RegularImmutableSortedSet<E> subElementSet =
(RegularImmutableSortedSet<E>) elementSet.getSubSet(from, to);
return new RegularImmutableSortedMultiset<E>(
- subElementSet, counts, cumulativeCounts, offset + from, to - from);
+ subElementSet, cumulativeCounts, offset + from, to - from);
}
}
@Override
boolean isPartialView() {
- return offset > 0 || length < counts.length;
+ return offset > 0 || length < cumulativeCounts.length - 1;
}
}
diff --git a/guava/src/com/google/common/collect/RegularImmutableSortedSet.java b/guava/src/com/google/common/collect/RegularImmutableSortedSet.java
index 382e338..32883b0 100644
--- a/guava/src/com/google/common/collect/RegularImmutableSortedSet.java
+++ b/guava/src/com/google/common/collect/RegularImmutableSortedSet.java
@@ -16,7 +16,6 @@
package com.google.common.collect;
-import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.SortedLists.KeyAbsentBehavior.INVERTED_INSERTION_INDEX;
import static com.google.common.collect.SortedLists.KeyAbsentBehavior.NEXT_HIGHER;
@@ -49,32 +48,29 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
private transient final ImmutableList<E> elements;
- RegularImmutableSortedSet(
- ImmutableList<E> elements, Comparator<? super E> comparator) {
+ RegularImmutableSortedSet(ImmutableList<E> elements, Comparator<? super E> comparator) {
super(comparator);
this.elements = elements;
- checkArgument(!elements.isEmpty());
}
- @Override public UnmodifiableIterator<E> iterator() {
+ @Override
+ public UnmodifiableIterator<E> iterator() {
return elements.iterator();
}
@GwtIncompatible("NavigableSet")
- @Override public UnmodifiableIterator<E> descendingIterator() {
+ @Override
+ public UnmodifiableIterator<E> descendingIterator() {
return elements.reverse().iterator();
}
- @Override public boolean isEmpty() {
- return false;
- }
-
@Override
public int size() {
return elements.size();
}
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(@Nullable Object o) {
try {
return o != null && unsafeBinarySearch(o) >= 0;
} catch (ClassCastException e) {
@@ -82,7 +78,8 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
}
}
- @Override public boolean containsAll(Collection<?> targets) {
+ @Override
+ public boolean containsAll(Collection<?> targets) {
// TODO(jlevy): For optimal performance, use a binary search when
// targets.size() < size() / log(size())
// TODO(kevinb): see if we can share code with OrderedIterator after it
@@ -90,8 +87,7 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
if (targets instanceof Multiset) {
targets = ((Multiset<?>) targets).elementSet();
}
- if (!SortedIterables.hasSameComparator(comparator(), targets)
- || (targets.size() <= 1)) {
+ if (!SortedIterables.hasSameComparator(comparator(), targets) || (targets.size() <= 1)) {
return super.containsAll(targets);
}
@@ -137,7 +133,8 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
return Collections.binarySearch(elements, key, unsafeComparator());
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return elements.isPartialView();
}
@@ -146,7 +143,8 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
return elements.copyIntoArray(dst, offset);
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -157,6 +155,8 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
Set<?> that = (Set<?>) object;
if (size() != that.size()) {
return false;
+ } else if (isEmpty()) {
+ return true;
}
if (SortedIterables.hasSameComparator(comparator, that)) {
@@ -166,8 +166,7 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
while (iterator.hasNext()) {
Object element = iterator.next();
Object otherElement = otherIterator.next();
- if (otherElement == null
- || unsafeCompare(element, otherElement) != 0) {
+ if (otherElement == null || unsafeCompare(element, otherElement) != 0) {
return false;
}
}
@@ -183,11 +182,17 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
@Override
public E first() {
+ if (isEmpty()) {
+ throw new NoSuchElementException();
+ }
return elements.get(0);
}
@Override
public E last() {
+ if (isEmpty()) {
+ throw new NoSuchElementException();
+ }
return elements.get(size() - 1);
}
@@ -222,15 +227,17 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
int headIndex(E toElement, boolean inclusive) {
return SortedLists.binarySearch(
- elements, checkNotNull(toElement), comparator(),
- inclusive ? FIRST_AFTER : FIRST_PRESENT, NEXT_HIGHER);
+ elements,
+ checkNotNull(toElement),
+ comparator(),
+ inclusive ? FIRST_AFTER : FIRST_PRESENT,
+ NEXT_HIGHER);
}
@Override
ImmutableSortedSet<E> subSetImpl(
E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
- return tailSetImpl(fromElement, fromInclusive)
- .headSetImpl(toElement, toInclusive);
+ return tailSetImpl(fromElement, fromInclusive).headSetImpl(toElement, toInclusive);
}
@Override
@@ -243,7 +250,8 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
elements,
checkNotNull(fromElement),
comparator(),
- inclusive ? FIRST_PRESENT : FIRST_AFTER, NEXT_HIGHER);
+ inclusive ? FIRST_PRESENT : FIRST_AFTER,
+ NEXT_HIGHER);
}
// Pretend the comparator can compare anything. If it turns out it can't
@@ -254,7 +262,7 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
return (Comparator<Object>) comparator;
}
- ImmutableSortedSet<E> getSubSet(int newFromIndex, int newToIndex) {
+ RegularImmutableSortedSet<E> getSubSet(int newFromIndex, int newToIndex) {
if (newFromIndex == 0 && newToIndex == size()) {
return this;
} else if (newFromIndex < newToIndex) {
@@ -265,27 +273,31 @@ final class RegularImmutableSortedSet<E> extends ImmutableSortedSet<E> {
}
}
- @Override int indexOf(@Nullable Object target) {
+ @Override
+ int indexOf(@Nullable Object target) {
if (target == null) {
return -1;
}
int position;
try {
- position = SortedLists.binarySearch(elements, target, unsafeComparator(),
- ANY_PRESENT, INVERTED_INSERTION_INDEX);
+ position = SortedLists.binarySearch(
+ elements, target, unsafeComparator(), ANY_PRESENT, INVERTED_INSERTION_INDEX);
} catch (ClassCastException e) {
return -1;
}
return (position >= 0) ? position : -1;
}
- @Override ImmutableList<E> createAsList() {
- return new ImmutableSortedAsList<E>(this, elements);
+ @Override
+ ImmutableList<E> createAsList() {
+ return (size() <= 1) ? elements : new ImmutableSortedAsList<E>(this, elements);
}
@Override
ImmutableSortedSet<E> createDescendingSet() {
- return new RegularImmutableSortedSet<E>(elements.reverse(),
- Ordering.from(comparator).reverse());
+ Ordering<E> reversedOrder = Ordering.from(comparator).reverse();
+ return isEmpty()
+ ? emptySet(reversedOrder)
+ : new RegularImmutableSortedSet<E>(elements.reverse(), reversedOrder);
}
}
diff --git a/guava/src/com/google/common/collect/RegularImmutableTable.java b/guava/src/com/google/common/collect/RegularImmutableTable.java
index 6bbec91..0bbbe39 100644
--- a/guava/src/com/google/common/collect/RegularImmutableTable.java
+++ b/guava/src/com/google/common/collect/RegularImmutableTable.java
@@ -17,10 +17,14 @@ package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.Table.Cell;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.Collections;
import java.util.Comparator;
+import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Set;
import javax.annotation.Nullable;
@@ -33,45 +37,31 @@ import javax.annotation.Nullable;
@GwtCompatible
abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
RegularImmutableTable() {}
-
+
abstract Cell<R, C, V> getCell(int iterationIndex);
-
+
@Override
final ImmutableSet<Cell<R, C, V>> createCellSet() {
return isEmpty() ? ImmutableSet.<Cell<R, C, V>>of() : new CellSet();
}
- private final class CellSet extends ImmutableSet<Cell<R, C, V>> {
+ @WeakOuter
+ private final class CellSet extends ImmutableSet.Indexed<Cell<R, C, V>> {
@Override
public int size() {
return RegularImmutableTable.this.size();
}
@Override
- public UnmodifiableIterator<Cell<R, C, V>> iterator() {
- return asList().iterator();
- }
-
- @Override
- ImmutableList<Cell<R, C, V>> createAsList() {
- return new ImmutableAsList<Cell<R, C, V>>() {
- @Override
- public Cell<R, C, V> get(int index) {
- return getCell(index);
- }
-
- @Override
- ImmutableCollection<Cell<R, C, V>> delegateCollection() {
- return CellSet.this;
- }
- };
+ Cell<R, C, V> get(int index) {
+ return getCell(index);
}
@Override
public boolean contains(@Nullable Object object) {
if (object instanceof Cell) {
Cell<?, ?, ?> cell = (Cell<?, ?, ?>) object;
- Object value = get(cell.getRowKey(), cell.getColumnKey());
+ Object value = RegularImmutableTable.this.get(cell.getRowKey(), cell.getColumnKey());
return value != null && value.equals(cell.getValue());
}
return false;
@@ -82,14 +72,15 @@ abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
return false;
}
}
-
+
abstract V getValue(int iterationIndex);
@Override
final ImmutableCollection<V> createValues() {
return isEmpty() ? ImmutableList.<V>of() : new Values();
}
-
+
+ @WeakOuter
private final class Values extends ImmutableList<V> {
@Override
public int size() {
@@ -120,24 +111,28 @@ abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
* provided but a row Comparator isn't, cellSet() iterates across the rows in the first
* column, the rows in the second column, etc.
*/
- Comparator<Cell<R, C, V>> comparator = new Comparator<Cell<R, C, V>>() {
- @Override public int compare(Cell<R, C, V> cell1, Cell<R, C, V> cell2) {
- int rowCompare = (rowComparator == null) ? 0
- : rowComparator.compare(cell1.getRowKey(), cell2.getRowKey());
- if (rowCompare != 0) {
- return rowCompare;
- }
- return (columnComparator == null) ? 0
- : columnComparator.compare(cell1.getColumnKey(), cell2.getColumnKey());
- }
- };
+ Comparator<Cell<R, C, V>> comparator =
+ new Comparator<Cell<R, C, V>>() {
+ @Override
+ public int compare(Cell<R, C, V> cell1, Cell<R, C, V> cell2) {
+ int rowCompare =
+ (rowComparator == null)
+ ? 0
+ : rowComparator.compare(cell1.getRowKey(), cell2.getRowKey());
+ if (rowCompare != 0) {
+ return rowCompare;
+ }
+ return (columnComparator == null)
+ ? 0
+ : columnComparator.compare(cell1.getColumnKey(), cell2.getColumnKey());
+ }
+ };
Collections.sort(cells, comparator);
}
return forCellsInternal(cells, rowComparator, columnComparator);
}
- static <R, C, V> RegularImmutableTable<R, C, V> forCells(
- Iterable<Cell<R, C, V>> cells) {
+ static <R, C, V> RegularImmutableTable<R, C, V> forCells(Iterable<Cell<R, C, V>> cells) {
return forCellsInternal(cells, null, null);
}
@@ -145,35 +140,33 @@ abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
* A factory that chooses the most space-efficient representation of the
* table.
*/
- private static final <R, C, V> RegularImmutableTable<R, C, V>
- forCellsInternal(Iterable<Cell<R, C, V>> cells,
- @Nullable Comparator<? super R> rowComparator,
- @Nullable Comparator<? super C> columnComparator) {
- ImmutableSet.Builder<R> rowSpaceBuilder = ImmutableSet.builder();
- ImmutableSet.Builder<C> columnSpaceBuilder = ImmutableSet.builder();
+ private static final <R, C, V> RegularImmutableTable<R, C, V> forCellsInternal(
+ Iterable<Cell<R, C, V>> cells,
+ @Nullable Comparator<? super R> rowComparator,
+ @Nullable Comparator<? super C> columnComparator) {
+ Set<R> rowSpaceBuilder = new LinkedHashSet<R>();
+ Set<C> columnSpaceBuilder = new LinkedHashSet<C>();
ImmutableList<Cell<R, C, V>> cellList = ImmutableList.copyOf(cells);
- for (Cell<R, C, V> cell : cellList) {
+ for (Cell<R, C, V> cell : cells) {
rowSpaceBuilder.add(cell.getRowKey());
columnSpaceBuilder.add(cell.getColumnKey());
}
- ImmutableSet<R> rowSpace = rowSpaceBuilder.build();
- if (rowComparator != null) {
- List<R> rowList = Lists.newArrayList(rowSpace);
- Collections.sort(rowList, rowComparator);
- rowSpace = ImmutableSet.copyOf(rowList);
- }
- ImmutableSet<C> columnSpace = columnSpaceBuilder.build();
- if (columnComparator != null) {
- List<C> columnList = Lists.newArrayList(columnSpace);
- Collections.sort(columnList, columnComparator);
- columnSpace = ImmutableSet.copyOf(columnList);
- }
+ ImmutableSet<R> rowSpace =
+ (rowComparator == null)
+ ? ImmutableSet.copyOf(rowSpaceBuilder)
+ : ImmutableSet.copyOf(
+ Ordering.from(rowComparator).immutableSortedCopy(rowSpaceBuilder));
+ ImmutableSet<C> columnSpace =
+ (columnComparator == null)
+ ? ImmutableSet.copyOf(columnSpaceBuilder)
+ : ImmutableSet.copyOf(
+ Ordering.from(columnComparator).immutableSortedCopy(columnSpaceBuilder));
// use a dense table if more than half of the cells have values
// TODO(gak): tune this condition based on empirical evidence
- return (cellList.size() > (((long) rowSpace.size() * columnSpace.size()) / 2)) ?
- new DenseImmutableTable<R, C, V>(cellList, rowSpace, columnSpace) :
- new SparseImmutableTable<R, C, V>(cellList, rowSpace, columnSpace);
+ return (cellList.size() > (((long) rowSpace.size() * columnSpace.size()) / 2))
+ ? new DenseImmutableTable<R, C, V>(cellList, rowSpace, columnSpace)
+ : new SparseImmutableTable<R, C, V>(cellList, rowSpace, columnSpace);
}
}
diff --git a/guava/src/com/google/common/collect/ReverseNaturalOrdering.java b/guava/src/com/google/common/collect/ReverseNaturalOrdering.java
index 9a73613..d94fc0c 100644
--- a/guava/src/com/google/common/collect/ReverseNaturalOrdering.java
+++ b/guava/src/com/google/common/collect/ReverseNaturalOrdering.java
@@ -26,11 +26,11 @@ import java.util.Iterator;
/** An ordering that uses the reverse of the natural order of the values. */
@GwtCompatible(serializable = true)
@SuppressWarnings("unchecked") // TODO(kevinb): the right way to explain this??
-final class ReverseNaturalOrdering
- extends Ordering<Comparable> implements Serializable {
+final class ReverseNaturalOrdering extends Ordering<Comparable> implements Serializable {
static final ReverseNaturalOrdering INSTANCE = new ReverseNaturalOrdering();
- @Override public int compare(Comparable left, Comparable right) {
+ @Override
+ public int compare(Comparable left, Comparable right) {
checkNotNull(left); // right null is caught later
if (left == right) {
return 0;
@@ -39,41 +39,50 @@ final class ReverseNaturalOrdering
return right.compareTo(left);
}
- @Override public <S extends Comparable> Ordering<S> reverse() {
+ @Override
+ public <S extends Comparable> Ordering<S> reverse() {
return Ordering.natural();
}
// Override the min/max methods to "hoist" delegation outside loops
- @Override public <E extends Comparable> E min(E a, E b) {
+ @Override
+ public <E extends Comparable> E min(E a, E b) {
return NaturalOrdering.INSTANCE.max(a, b);
}
- @Override public <E extends Comparable> E min(E a, E b, E c, E... rest) {
+ @Override
+ public <E extends Comparable> E min(E a, E b, E c, E... rest) {
return NaturalOrdering.INSTANCE.max(a, b, c, rest);
}
- @Override public <E extends Comparable> E min(Iterator<E> iterator) {
+ @Override
+ public <E extends Comparable> E min(Iterator<E> iterator) {
return NaturalOrdering.INSTANCE.max(iterator);
}
- @Override public <E extends Comparable> E min(Iterable<E> iterable) {
+ @Override
+ public <E extends Comparable> E min(Iterable<E> iterable) {
return NaturalOrdering.INSTANCE.max(iterable);
}
- @Override public <E extends Comparable> E max(E a, E b) {
+ @Override
+ public <E extends Comparable> E max(E a, E b) {
return NaturalOrdering.INSTANCE.min(a, b);
}
- @Override public <E extends Comparable> E max(E a, E b, E c, E... rest) {
+ @Override
+ public <E extends Comparable> E max(E a, E b, E c, E... rest) {
return NaturalOrdering.INSTANCE.min(a, b, c, rest);
}
- @Override public <E extends Comparable> E max(Iterator<E> iterator) {
+ @Override
+ public <E extends Comparable> E max(Iterator<E> iterator) {
return NaturalOrdering.INSTANCE.min(iterator);
}
- @Override public <E extends Comparable> E max(Iterable<E> iterable) {
+ @Override
+ public <E extends Comparable> E max(Iterable<E> iterable) {
return NaturalOrdering.INSTANCE.min(iterable);
}
@@ -82,7 +91,8 @@ final class ReverseNaturalOrdering
return INSTANCE;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Ordering.natural().reverse()";
}
diff --git a/guava/src/com/google/common/collect/ReverseOrdering.java b/guava/src/com/google/common/collect/ReverseOrdering.java
index 36ae02c..30ffbf8 100644
--- a/guava/src/com/google/common/collect/ReverseOrdering.java
+++ b/guava/src/com/google/common/collect/ReverseOrdering.java
@@ -34,54 +34,66 @@ final class ReverseOrdering<T> extends Ordering<T> implements Serializable {
this.forwardOrder = checkNotNull(forwardOrder);
}
- @Override public int compare(T a, T b) {
+ @Override
+ public int compare(T a, T b) {
return forwardOrder.compare(b, a);
}
@SuppressWarnings("unchecked") // how to explain?
- @Override public <S extends T> Ordering<S> reverse() {
+ @Override
+ public <S extends T> Ordering<S> reverse() {
return (Ordering<S>) forwardOrder;
}
// Override the min/max methods to "hoist" delegation outside loops
- @Override public <E extends T> E min(E a, E b) {
+ @Override
+ public <E extends T> E min(E a, E b) {
return forwardOrder.max(a, b);
}
- @Override public <E extends T> E min(E a, E b, E c, E... rest) {
+ @Override
+ public <E extends T> E min(E a, E b, E c, E... rest) {
return forwardOrder.max(a, b, c, rest);
}
- @Override public <E extends T> E min(Iterator<E> iterator) {
+ @Override
+ public <E extends T> E min(Iterator<E> iterator) {
return forwardOrder.max(iterator);
}
- @Override public <E extends T> E min(Iterable<E> iterable) {
+ @Override
+ public <E extends T> E min(Iterable<E> iterable) {
return forwardOrder.max(iterable);
}
- @Override public <E extends T> E max(E a, E b) {
+ @Override
+ public <E extends T> E max(E a, E b) {
return forwardOrder.min(a, b);
}
- @Override public <E extends T> E max(E a, E b, E c, E... rest) {
+ @Override
+ public <E extends T> E max(E a, E b, E c, E... rest) {
return forwardOrder.min(a, b, c, rest);
}
- @Override public <E extends T> E max(Iterator<E> iterator) {
+ @Override
+ public <E extends T> E max(Iterator<E> iterator) {
return forwardOrder.min(iterator);
}
- @Override public <E extends T> E max(Iterable<E> iterable) {
+ @Override
+ public <E extends T> E max(Iterable<E> iterable) {
return forwardOrder.min(iterable);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return -forwardOrder.hashCode();
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -92,7 +104,8 @@ final class ReverseOrdering<T> extends Ordering<T> implements Serializable {
return false;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return forwardOrder + ".reverse()";
}
diff --git a/guava/src/com/google/common/collect/RowSortedTable.java b/guava/src/com/google/common/collect/RowSortedTable.java
index 4b597b7..76d8ad6 100644
--- a/guava/src/com/google/common/collect/RowSortedTable.java
+++ b/guava/src/com/google/common/collect/RowSortedTable.java
@@ -43,7 +43,8 @@ public interface RowSortedTable<R, C, V> extends Table<R, C, V> {
* <p>This method returns a {@link SortedSet}, instead of the {@code Set}
* specified in the {@link Table} interface.
*/
- @Override SortedSet<R> rowKeySet();
+ @Override
+ SortedSet<R> rowKeySet();
/**
* {@inheritDoc}
@@ -51,5 +52,6 @@ public interface RowSortedTable<R, C, V> extends Table<R, C, V> {
* <p>This method returns a {@link SortedMap}, instead of the {@code Map}
* specified in the {@link Table} interface.
*/
- @Override SortedMap<R, Map<C, V>> rowMap();
+ @Override
+ SortedMap<R, Map<C, V>> rowMap();
}
diff --git a/guava/src/com/google/common/collect/Serialization.java b/guava/src/com/google/common/collect/Serialization.java
index 2541548..6f57fdc 100644
--- a/guava/src/com/google/common/collect/Serialization.java
+++ b/guava/src/com/google/common/collect/Serialization.java
@@ -42,9 +42,6 @@ final class Serialization {
* #writeMultiset(Multiset, ObjectOutputStream)}, or the number of distinct
* keys in a multimap serialized by {@link
* #writeMultimap(Multimap, ObjectOutputStream)}.
- *
- * <p>The returned count may be used to construct an empty collection of the
- * appropriate capacity before calling any of the {@code populate} methods.
*/
static int readCount(ObjectInputStream stream) throws IOException {
return stream.readInt();
@@ -58,8 +55,7 @@ final class Serialization {
* <p>The serialized output consists of the number of entries, first key,
* first value, second key, second value, and so on.
*/
- static <K, V> void writeMap(Map<K, V> map, ObjectOutputStream stream)
- throws IOException {
+ static <K, V> void writeMap(Map<K, V> map, ObjectOutputStream stream) throws IOException {
stream.writeInt(map.size());
for (Map.Entry<K, V> entry : map.entrySet()) {
stream.writeObject(entry.getKey());
@@ -82,8 +78,8 @@ final class Serialization {
* See {@link #writeMap} for the data format. The size is determined by a
* prior call to {@link #readCount}.
*/
- static <K, V> void populateMap(Map<K, V> map, ObjectInputStream stream,
- int size) throws IOException, ClassNotFoundException {
+ static <K, V> void populateMap(Map<K, V> map, ObjectInputStream stream, int size)
+ throws IOException, ClassNotFoundException {
for (int i = 0; i < size; i++) {
@SuppressWarnings("unchecked") // reading data stored by writeMap
K key = (K) stream.readObject();
@@ -101,8 +97,8 @@ final class Serialization {
* <p>The serialized output consists of the number of distinct elements, the
* first element, its count, the second element, its count, and so on.
*/
- static <E> void writeMultiset(
- Multiset<E> multiset, ObjectOutputStream stream) throws IOException {
+ static <E> void writeMultiset(Multiset<E> multiset, ObjectOutputStream stream)
+ throws IOException {
int entryCount = multiset.entrySet().size();
stream.writeInt(entryCount);
for (Multiset.Entry<E> entry : multiset.entrySet()) {
@@ -115,8 +111,7 @@ final class Serialization {
* Populates a multiset by reading an input stream, as part of
* deserialization. See {@link #writeMultiset} for the data format.
*/
- static <E> void populateMultiset(
- Multiset<E> multiset, ObjectInputStream stream)
+ static <E> void populateMultiset(Multiset<E> multiset, ObjectInputStream stream)
throws IOException, ClassNotFoundException {
int distinctElements = stream.readInt();
populateMultiset(multiset, stream, distinctElements);
@@ -148,8 +143,8 @@ final class Serialization {
* for each distinct key: the key, the number of values for that key, and the
* key's values.
*/
- static <K, V> void writeMultimap(
- Multimap<K, V> multimap, ObjectOutputStream stream) throws IOException {
+ static <K, V> void writeMultimap(Multimap<K, V> multimap, ObjectOutputStream stream)
+ throws IOException {
stream.writeInt(multimap.asMap().size());
for (Map.Entry<K, Collection<V>> entry : multimap.asMap().entrySet()) {
stream.writeObject(entry.getKey());
@@ -164,8 +159,7 @@ final class Serialization {
* Populates a multimap by reading an input stream, as part of
* deserialization. See {@link #writeMultimap} for the data format.
*/
- static <K, V> void populateMultimap(
- Multimap<K, V> multimap, ObjectInputStream stream)
+ static <K, V> void populateMultimap(Multimap<K, V> multimap, ObjectInputStream stream)
throws IOException, ClassNotFoundException {
int distinctKeys = stream.readInt();
populateMultimap(multimap, stream, distinctKeys);
@@ -193,8 +187,7 @@ final class Serialization {
}
// Secret sauce for setting final fields; don't make it public.
- static <T> FieldSetter<T> getFieldSetter(
- final Class<T> clazz, String fieldName) {
+ static <T> FieldSetter<T> getFieldSetter(final Class<T> clazz, String fieldName) {
try {
Field field = clazz.getDeclaredField(fieldName);
return new FieldSetter<T>(field);
diff --git a/guava/src/com/google/common/collect/SetMultimap.java b/guava/src/com/google/common/collect/SetMultimap.java
index 8c28d6b..46ae17a 100644
--- a/guava/src/com/google/common/collect/SetMultimap.java
+++ b/guava/src/com/google/common/collect/SetMultimap.java
@@ -37,19 +37,19 @@ import javax.annotation.Nullable;
* <p>If the values corresponding to a single key should be ordered according to
* a {@link java.util.Comparator} (or the natural order), see the
* {@link SortedSetMultimap} subinterface.
- *
+ *
* <p>Since the value collections are sets, the behavior of a {@code SetMultimap}
- * is not specified if key <em>or value</em> objects already present in the
- * multimap change in a manner that affects {@code equals} comparisons.
- * Use caution if mutable objects are used as keys or values in a
+ * is not specified if key <em>or value</em> objects already present in the
+ * multimap change in a manner that affects {@code equals} comparisons.
+ * Use caution if mutable objects are used as keys or values in a
* {@code SetMultimap}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
* {@code Multimap}</a>.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public interface SetMultimap<K, V> extends Multimap<K, V> {
diff --git a/guava/src/com/google/common/collect/Sets.java b/guava/src/com/google/common/collect/Sets.java
index 4218725..5d0142c 100644
--- a/guava/src/com/google/common/collect/Sets.java
+++ b/guava/src/com/google/common/collect/Sets.java
@@ -45,6 +45,7 @@ import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -52,13 +53,13 @@ import javax.annotation.Nullable;
* class's counterparts {@link Lists}, {@link Maps} and {@link Queues}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Sets">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#sets">
* {@code Sets}</a>.
*
* @author Kevin Bourrillion
* @author Jared Levy
* @author Chris Povirk
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Sets {
@@ -111,8 +112,7 @@ public final class Sets {
*/
// http://code.google.com/p/google-web-toolkit/issues/detail?id=3028
@GwtCompatible(serializable = true)
- public static <E extends Enum<E>> ImmutableSet<E> immutableEnumSet(
- Iterable<E> elements) {
+ public static <E extends Enum<E>> ImmutableSet<E> immutableEnumSet(Iterable<E> elements) {
if (elements instanceof ImmutableEnumSet) {
return (ImmutableEnumSet<E>) elements;
} else if (elements instanceof Collection) {
@@ -135,13 +135,12 @@ public final class Sets {
}
/**
- * Returns a new {@code EnumSet} instance containing the given elements.
- * Unlike {@link EnumSet#copyOf(Collection)}, this method does not produce an
- * exception on an empty collection, and it may be called on any iterable, not
- * just a {@code Collection}.
+ * Returns a new, <i>mutable</i> {@code EnumSet} instance containing the given elements in their
+ * natural order. This method behaves identically to {@link EnumSet#copyOf(Collection)}, but also
+ * accepts non-{@code Collection} iterables and empty iterables.
*/
- public static <E extends Enum<E>> EnumSet<E> newEnumSet(Iterable<E> iterable,
- Class<E> elementType) {
+ public static <E extends Enum<E>> EnumSet<E> newEnumSet(
+ Iterable<E> iterable, Class<E> elementType) {
EnumSet<E> set = EnumSet.noneOf(elementType);
Iterables.addAll(set, iterable);
return set;
@@ -150,33 +149,33 @@ public final class Sets {
// HashSet
/**
- * Creates a <i>mutable</i>, empty {@code HashSet} instance.
+ * Creates a <i>mutable</i>, initially empty {@code HashSet} instance.
*
- * <p><b>Note:</b> if mutability is not required, use {@link
- * ImmutableSet#of()} instead.
+ * <p><b>Note:</b> if mutability is not required, use {@link ImmutableSet#of()} instead. If
+ * {@code E} is an {@link Enum} type, use {@link EnumSet#noneOf} instead. Otherwise, strongly
+ * consider using a {@code LinkedHashSet} instead, at the cost of increased memory footprint, to
+ * get deterministic iteration behavior.
*
- * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link
- * EnumSet#noneOf} instead.
- *
- * @return a new, empty {@code HashSet}
+ * <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as
+ * deprecated. Instead, use the {@code HashSet} constructor directly, taking advantage of the new
+ * <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
*/
public static <E> HashSet<E> newHashSet() {
return new HashSet<E>();
}
/**
- * Creates a <i>mutable</i> {@code HashSet} instance containing the given
- * elements in unspecified order.
- *
- * <p><b>Note:</b> if mutability is not required and the elements are
- * non-null, use an overload of {@link ImmutableSet#of()} (for varargs) or
- * {@link ImmutableSet#copyOf(Object[])} (for an array) instead.
+ * Creates a <i>mutable</i> {@code HashSet} instance initially containing the given elements.
*
- * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link
- * EnumSet#of(Enum, Enum[])} instead.
+ * <p><b>Note:</b> if elements are non-null and won't be added or removed after this point, use
+ * {@link ImmutableSet#of()} or {@link ImmutableSet#copyOf(Object[])} instead. If {@code E} is an
+ * {@link Enum} type, use {@link EnumSet#of(Enum, Enum[])} instead. Otherwise, strongly consider
+ * using a {@code LinkedHashSet} instead, at the cost of increased memory footprint, to get
+ * deterministic iteration behavior.
*
- * @param elements the elements that the set should contain
- * @return a new {@code HashSet} containing those elements (minus duplicates)
+ * <p>This method is just a small convenience, either for {@code newHashSet(}{@link Arrays#asList
+ * asList}{@code (...))}, or for creating an empty set then calling {@link Collections#addAll}.
+ * This method is not actually very useful and will likely be deprecated in the future.
*/
public static <E> HashSet<E> newHashSet(E... elements) {
HashSet<E> set = newHashSetWithExpectedSize(elements.length);
@@ -185,11 +184,10 @@ public final class Sets {
}
/**
- * Creates a {@code HashSet} instance, with a high enough "initial capacity"
- * that it <i>should</i> hold {@code expectedSize} elements without growth.
- * This behavior cannot be broadly guaranteed, but it is observed to be true
- * for OpenJDK 1.6. It also can't be guaranteed that the method isn't
- * inadvertently <i>oversizing</i> the returned set.
+ * Creates a {@code HashSet} instance, with a high enough initial table size that it <i>should</i>
+ * hold {@code expectedSize} elements without resizing. This behavior cannot be broadly
+ * guaranteed, but it is observed to be true for OpenJDK 1.7. It also can't be guaranteed that the
+ * method isn't inadvertently <i>oversizing</i> the returned set.
*
* @param expectedSize the number of elements you expect to add to the
* returned set
@@ -202,17 +200,22 @@ public final class Sets {
}
/**
- * Creates a <i>mutable</i> {@code HashSet} instance containing the given
- * elements in unspecified order.
+ * Creates a <i>mutable</i> {@code HashSet} instance containing the given elements. A very thin
+ * convenience for creating an empty set then calling {@link Collection#addAll} or {@link
+ * Iterables#addAll}.
*
- * <p><b>Note:</b> if mutability is not required and the elements are
- * non-null, use {@link ImmutableSet#copyOf(Iterable)} instead.
+ * <p><b>Note:</b> if mutability is not required and the elements are non-null, use {@link
+ * ImmutableSet#copyOf(Iterable)} instead. (Or, change {@code elements} to be a {@link
+ * FluentIterable} and call {@code elements.toSet()}.)
*
- * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use
- * {@link #newEnumSet(Iterable, Class)} instead.
+ * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link #newEnumSet(Iterable, Class)}
+ * instead.
*
- * @param elements the elements that the set should contain
- * @return a new {@code HashSet} containing those elements (minus duplicates)
+ * <p><b>Note for Java 7 and later:</b> if {@code elements} is a {@link Collection}, you don't
+ * need this method. Instead, use the {@code HashSet} constructor directly, taking advantage of
+ * the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
+ *
+ * <p>Overall, this method is not very useful and will likely be deprecated in the future.
*/
public static <E> HashSet<E> newHashSet(Iterable<? extends E> elements) {
return (elements instanceof Collection)
@@ -221,17 +224,16 @@ public final class Sets {
}
/**
- * Creates a <i>mutable</i> {@code HashSet} instance containing the given
- * elements in unspecified order.
+ * Creates a <i>mutable</i> {@code HashSet} instance containing the given elements. A very thin
+ * convenience for creating an empty set and then calling {@link Iterators#addAll}.
*
- * <p><b>Note:</b> if mutability is not required and the elements are
- * non-null, use {@link ImmutableSet#copyOf(Iterable)} instead.
+ * <p><b>Note:</b> if mutability is not required and the elements are non-null, use {@link
+ * ImmutableSet#copyOf(Iterator)} instead.
*
- * <p><b>Note:</b> if {@code E} is an {@link Enum} type, you should create an
- * {@link EnumSet} instead.
+ * <p><b>Note:</b> if {@code E} is an {@link Enum} type, you should create an {@link EnumSet}
+ * instead.
*
- * @param elements the elements that the set should contain
- * @return a new {@code HashSet} containing those elements (minus duplicates)
+ * <p>Overall, this method is not very useful and will likely be deprecated in the future.
*/
public static <E> HashSet<E> newHashSet(Iterator<? extends E> elements) {
HashSet<E> set = newHashSet();
@@ -268,8 +270,7 @@ public final class Sets {
* null
* @since 15.0
*/
- public static <E> Set<E> newConcurrentHashSet(
- Iterable<? extends E> elements) {
+ public static <E> Set<E> newConcurrentHashSet(Iterable<? extends E> elements) {
Set<E> set = newConcurrentHashSet();
Iterables.addAll(set, elements);
return set;
@@ -303,8 +304,7 @@ public final class Sets {
* @throws IllegalArgumentException if {@code expectedSize} is negative
* @since 11.0
*/
- public static <E> LinkedHashSet<E> newLinkedHashSetWithExpectedSize(
- int expectedSize) {
+ public static <E> LinkedHashSet<E> newLinkedHashSetWithExpectedSize(int expectedSize) {
return new LinkedHashSet<E>(Maps.capacity(expectedSize));
}
@@ -319,8 +319,7 @@ public final class Sets {
* @return a new {@code LinkedHashSet} containing those elements (minus
* duplicates)
*/
- public static <E> LinkedHashSet<E> newLinkedHashSet(
- Iterable<? extends E> elements) {
+ public static <E> LinkedHashSet<E> newLinkedHashSet(Iterable<? extends E> elements) {
if (elements instanceof Collection) {
return new LinkedHashSet<E>(Collections2.cast(elements));
}
@@ -359,8 +358,7 @@ public final class Sets {
* @param elements the elements that the set should contain
* @return a new {@code TreeSet} containing those elements (minus duplicates)
*/
- public static <E extends Comparable> TreeSet<E> newTreeSet(
- Iterable<? extends E> elements) {
+ public static <E extends Comparable> TreeSet<E> newTreeSet(Iterable<? extends E> elements) {
TreeSet<E> set = newTreeSet();
Iterables.addAll(set, elements);
return set;
@@ -417,13 +415,13 @@ public final class Sets {
* @since 12.0
*/
@GwtIncompatible("CopyOnWriteArraySet")
- public static <E> CopyOnWriteArraySet<E> newCopyOnWriteArraySet(
- Iterable<? extends E> elements) {
+ public static <E> CopyOnWriteArraySet<E> newCopyOnWriteArraySet(Iterable<? extends E> elements) {
// We copy elements to an ArrayList first, rather than incurring the
// quadratic cost of adding them to the COWAS directly.
- Collection<? extends E> elementsCollection = (elements instanceof Collection)
- ? Collections2.cast(elements)
- : Lists.newArrayList(elements);
+ Collection<? extends E> elementsCollection =
+ (elements instanceof Collection)
+ ? Collections2.cast(elements)
+ : Lists.newArrayList(elements);
return new CopyOnWriteArraySet<E>(elementsCollection);
}
@@ -442,13 +440,12 @@ public final class Sets {
* @throws IllegalArgumentException if {@code collection} is not an
* {@code EnumSet} instance and contains no elements
*/
- public static <E extends Enum<E>> EnumSet<E> complementOf(
- Collection<E> collection) {
+ public static <E extends Enum<E>> EnumSet<E> complementOf(Collection<E> collection) {
if (collection instanceof EnumSet) {
return EnumSet.complementOf((EnumSet<E>) collection);
}
- checkArgument(!collection.isEmpty(),
- "collection is empty; use the other version of this method");
+ checkArgument(
+ !collection.isEmpty(), "collection is empty; use the other version of this method");
Class<E> type = collection.iterator().next().getDeclaringClass();
return makeComplementByHand(collection, type);
}
@@ -503,14 +500,15 @@ public final class Sets {
* Set<Object> identityHashSet = Sets.newSetFromMap(
* new IdentityHashMap<Object, Boolean>());}</pre>
*
- * <p>This method has the same behavior as the JDK 6 method
- * {@code Collections.newSetFromMap()}. The returned set is serializable if
- * the backing map is.
+ * <p>The returned set is serializable if the backing map is.
*
* @param map the backing map
* @return the set backed by the map
* @throws IllegalArgumentException if {@code map} is not empty
+ * @deprecated Use {@link Collections#newSetFromMap} instead. This method
+ * will be removed in August 2017.
*/
+ @Deprecated
public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
return Platform.newSetFromMap(map);
}
@@ -523,7 +521,7 @@ public final class Sets {
* as a plain {@link Set}, or immediately invoke {@link #immutableCopy} or
* {@link #copyInto} and forget the {@code SetView} itself.
*
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
public abstract static class SetView<E> extends AbstractSet<E> {
private SetView() {} // no subclasses but our own
@@ -576,35 +574,44 @@ public final class Sets {
* {@code union = Sets.union(union, anotherSet);}, since iterating over the resulting
* set has a cubic complexity to the depth of the nesting.
*/
- public static <E> SetView<E> union(
- final Set<? extends E> set1, final Set<? extends E> set2) {
+ public static <E> SetView<E> union(final Set<? extends E> set1, final Set<? extends E> set2) {
checkNotNull(set1, "set1");
checkNotNull(set2, "set2");
final Set<? extends E> set2minus1 = difference(set2, set1);
return new SetView<E>() {
- @Override public int size() {
+ @Override
+ public int size() {
return set1.size() + set2minus1.size();
}
- @Override public boolean isEmpty() {
+
+ @Override
+ public boolean isEmpty() {
return set1.isEmpty() && set2.isEmpty();
}
- @Override public Iterator<E> iterator() {
+
+ @Override
+ public Iterator<E> iterator() {
return Iterators.unmodifiableIterator(
Iterators.concat(set1.iterator(), set2minus1.iterator()));
}
- @Override public boolean contains(Object object) {
+
+ @Override
+ public boolean contains(Object object) {
return set1.contains(object) || set2.contains(object);
}
- @Override public <S extends Set<E>> S copyInto(S set) {
+
+ @Override
+ public <S extends Set<E>> S copyInto(S set) {
set.addAll(set1);
set.addAll(set2);
return set;
}
- @Override public ImmutableSet<E> immutableCopy() {
- return new ImmutableSet.Builder<E>()
- .addAll(set1).addAll(set2).build();
+
+ @Override
+ public ImmutableSet<E> immutableCopy() {
+ return new ImmutableSet.Builder<E>().addAll(set1).addAll(set2).build();
}
};
}
@@ -635,28 +642,35 @@ public final class Sets {
*
* <p>This is unfortunate, but should come up only very rarely.
*/
- public static <E> SetView<E> intersection(
- final Set<E> set1, final Set<?> set2) {
+ public static <E> SetView<E> intersection(final Set<E> set1, final Set<?> set2) {
checkNotNull(set1, "set1");
checkNotNull(set2, "set2");
final Predicate<Object> inSet2 = Predicates.in(set2);
return new SetView<E>() {
- @Override public Iterator<E> iterator() {
+ @Override
+ public Iterator<E> iterator() {
return Iterators.filter(set1.iterator(), inSet2);
}
- @Override public int size() {
+
+ @Override
+ public int size() {
return Iterators.size(iterator());
}
- @Override public boolean isEmpty() {
+
+ @Override
+ public boolean isEmpty() {
return !iterator().hasNext();
}
- @Override public boolean contains(Object object) {
+
+ @Override
+ public boolean contains(Object object) {
return set1.contains(object) && set2.contains(object);
}
- @Override public boolean containsAll(Collection<?> collection) {
- return set1.containsAll(collection)
- && set2.containsAll(collection);
+
+ @Override
+ public boolean containsAll(Collection<?> collection) {
+ return set1.containsAll(collection) && set2.containsAll(collection);
}
};
}
@@ -672,23 +686,29 @@ public final class Sets {
* on different equivalence relations (as {@code HashSet}, {@code TreeSet},
* and the keySet of an {@code IdentityHashMap} all are).
*/
- public static <E> SetView<E> difference(
- final Set<E> set1, final Set<?> set2) {
+ public static <E> SetView<E> difference(final Set<E> set1, final Set<?> set2) {
checkNotNull(set1, "set1");
checkNotNull(set2, "set2");
final Predicate<Object> notInSet2 = Predicates.not(Predicates.in(set2));
return new SetView<E>() {
- @Override public Iterator<E> iterator() {
+ @Override
+ public Iterator<E> iterator() {
return Iterators.filter(set1.iterator(), notInSet2);
}
- @Override public int size() {
+
+ @Override
+ public int size() {
return Iterators.size(iterator());
}
- @Override public boolean isEmpty() {
+
+ @Override
+ public boolean isEmpty() {
return set2.containsAll(set1);
}
- @Override public boolean contains(Object element) {
+
+ @Override
+ public boolean contains(Object element) {
return set1.contains(element) && !set2.contains(element);
}
};
@@ -707,12 +727,50 @@ public final class Sets {
* @since 3.0
*/
public static <E> SetView<E> symmetricDifference(
- Set<? extends E> set1, Set<? extends E> set2) {
+ final Set<? extends E> set1, final Set<? extends E> set2) {
checkNotNull(set1, "set1");
checkNotNull(set2, "set2");
- // TODO(kevinb): Replace this with a more efficient implementation
- return difference(union(set1, set2), intersection(set1, set2));
+ return new SetView<E>() {
+ @Override
+ public Iterator<E> iterator() {
+ final Iterator<? extends E> itr1 = set1.iterator();
+ final Iterator<? extends E> itr2 = set2.iterator();
+ return new AbstractIterator<E>() {
+ @Override
+ public E computeNext() {
+ while (itr1.hasNext()) {
+ E elem1 = itr1.next();
+ if (!set2.contains(elem1)) {
+ return elem1;
+ }
+ }
+ while (itr2.hasNext()) {
+ E elem2 = itr2.next();
+ if (!set1.contains(elem2)) {
+ return elem2;
+ }
+ }
+ return endOfData();
+ }
+ };
+ }
+
+ @Override
+ public int size() {
+ return Iterators.size(iterator());
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return set1.equals(set2);
+ }
+
+ @Override
+ public boolean contains(Object element) {
+ return set1.contains(element) ^ set2.contains(element);
+ }
+ };
}
/**
@@ -742,8 +800,8 @@ public final class Sets {
* functionality.)
*/
// TODO(kevinb): how to omit that last sentence when building GWT javadoc?
- public static <E> Set<E> filter(
- Set<E> unfiltered, Predicate<? super E> predicate) {
+ @CheckReturnValue
+ public static <E> Set<E> filter(Set<E> unfiltered, Predicate<? super E> predicate) {
if (unfiltered instanceof SortedSet) {
return filter((SortedSet<E>) unfiltered, predicate);
}
@@ -751,27 +809,25 @@ public final class Sets {
// Support clear(), removeAll(), and retainAll() when filtering a filtered
// collection.
FilteredSet<E> filtered = (FilteredSet<E>) unfiltered;
- Predicate<E> combinedPredicate
- = Predicates.<E>and(filtered.predicate, predicate);
- return new FilteredSet<E>(
- (Set<E>) filtered.unfiltered, combinedPredicate);
+ Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
+ return new FilteredSet<E>((Set<E>) filtered.unfiltered, combinedPredicate);
}
- return new FilteredSet<E>(
- checkNotNull(unfiltered), checkNotNull(predicate));
+ return new FilteredSet<E>(checkNotNull(unfiltered), checkNotNull(predicate));
}
- private static class FilteredSet<E> extends FilteredCollection<E>
- implements Set<E> {
+ private static class FilteredSet<E> extends FilteredCollection<E> implements Set<E> {
FilteredSet(Set<E> unfiltered, Predicate<? super E> predicate) {
super(unfiltered, predicate);
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
return equalsImpl(this, object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return hashCodeImpl(this);
}
}
@@ -805,8 +861,8 @@ public final class Sets {
*
* @since 11.0
*/
- public static <E> SortedSet<E> filter(
- SortedSet<E> unfiltered, Predicate<? super E> predicate) {
+ @CheckReturnValue
+ public static <E> SortedSet<E> filter(SortedSet<E> unfiltered, Predicate<? super E> predicate) {
return Platform.setsFilterSortedSet(unfiltered, predicate);
}
@@ -816,18 +872,14 @@ public final class Sets {
// Support clear(), removeAll(), and retainAll() when filtering a filtered
// collection.
FilteredSet<E> filtered = (FilteredSet<E>) unfiltered;
- Predicate<E> combinedPredicate
- = Predicates.<E>and(filtered.predicate, predicate);
- return new FilteredSortedSet<E>(
- (SortedSet<E>) filtered.unfiltered, combinedPredicate);
+ Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
+ return new FilteredSortedSet<E>((SortedSet<E>) filtered.unfiltered, combinedPredicate);
}
- return new FilteredSortedSet<E>(
- checkNotNull(unfiltered), checkNotNull(predicate));
+ return new FilteredSortedSet<E>(checkNotNull(unfiltered), checkNotNull(predicate));
}
- private static class FilteredSortedSet<E> extends FilteredSet<E>
- implements SortedSet<E> {
+ private static class FilteredSortedSet<E> extends FilteredSet<E> implements SortedSet<E> {
FilteredSortedSet(SortedSet<E> unfiltered, Predicate<? super E> predicate) {
super(unfiltered, predicate);
@@ -840,8 +892,8 @@ public final class Sets {
@Override
public SortedSet<E> subSet(E fromElement, E toElement) {
- return new FilteredSortedSet<E>(((SortedSet<E>) unfiltered).subSet(fromElement, toElement),
- predicate);
+ return new FilteredSortedSet<E>(
+ ((SortedSet<E>) unfiltered).subSet(fromElement, toElement), predicate);
}
@Override
@@ -903,20 +955,18 @@ public final class Sets {
*/
@GwtIncompatible("NavigableSet")
@SuppressWarnings("unchecked")
+ @CheckReturnValue
public static <E> NavigableSet<E> filter(
NavigableSet<E> unfiltered, Predicate<? super E> predicate) {
if (unfiltered instanceof FilteredSet) {
// Support clear(), removeAll(), and retainAll() when filtering a filtered
// collection.
FilteredSet<E> filtered = (FilteredSet<E>) unfiltered;
- Predicate<E> combinedPredicate
- = Predicates.<E>and(filtered.predicate, predicate);
- return new FilteredNavigableSet<E>(
- (NavigableSet<E>) filtered.unfiltered, combinedPredicate);
+ Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
+ return new FilteredNavigableSet<E>((NavigableSet<E>) filtered.unfiltered, combinedPredicate);
}
- return new FilteredNavigableSet<E>(
- checkNotNull(unfiltered), checkNotNull(predicate));
+ return new FilteredNavigableSet<E>(checkNotNull(unfiltered), checkNotNull(predicate));
}
@GwtIncompatible("NavigableSet")
@@ -1050,8 +1100,7 @@ public final class Sets {
* or any element of a provided set is null
* @since 2.0
*/
- public static <B> Set<List<B>> cartesianProduct(
- List<? extends Set<? extends B>> sets) {
+ public static <B> Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets) {
return CartesianSet.create(sets);
}
@@ -1110,13 +1159,12 @@ public final class Sets {
* or any element of a provided set is null
* @since 2.0
*/
- public static <B> Set<List<B>> cartesianProduct(
- Set<? extends B>... sets) {
+ public static <B> Set<List<B>> cartesianProduct(Set<? extends B>... sets) {
return cartesianProduct(Arrays.asList(sets));
}
- private static final class CartesianSet<E>
- extends ForwardingCollection<List<E>> implements Set<List<E>> {
+ private static final class CartesianSet<E> extends ForwardingCollection<List<E>>
+ implements Set<List<E>> {
private transient final ImmutableList<ImmutableSet<E>> axes;
private transient final CartesianList<E> delegate;
@@ -1131,28 +1179,27 @@ public final class Sets {
axesBuilder.add(copy);
}
final ImmutableList<ImmutableSet<E>> axes = axesBuilder.build();
- ImmutableList<List<E>> listAxes = new ImmutableList<List<E>>() {
-
- @Override
- public int size() {
- return axes.size();
- }
-
- @Override
- public List<E> get(int index) {
- return axes.get(index).asList();
- }
-
- @Override
- boolean isPartialView() {
- return true;
- }
- };
+ ImmutableList<List<E>> listAxes =
+ new ImmutableList<List<E>>() {
+ @Override
+ public int size() {
+ return axes.size();
+ }
+
+ @Override
+ public List<E> get(int index) {
+ return axes.get(index).asList();
+ }
+
+ @Override
+ boolean isPartialView() {
+ return true;
+ }
+ };
return new CartesianSet<E>(axes, new CartesianList<E>(listAxes));
}
- private CartesianSet(
- ImmutableList<ImmutableSet<E>> axes, CartesianList<E> delegate) {
+ private CartesianSet(ImmutableList<ImmutableSet<E>> axes, CartesianList<E> delegate) {
this.axes = axes;
this.delegate = delegate;
}
@@ -1162,7 +1209,8 @@ public final class Sets {
return delegate;
}
- @Override public boolean equals(@Nullable Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
// Warning: this is broken if size() == 0, so it is critical that we
// substitute an empty ImmutableSet to the user in place of this
if (object instanceof CartesianSet) {
@@ -1277,33 +1325,33 @@ public final class Sets {
final ImmutableMap<E, Integer> inputSet;
PowerSet(Set<E> input) {
- ImmutableMap.Builder<E, Integer> builder = ImmutableMap.builder();
- int i = 0;
- for (E e : checkNotNull(input)) {
- builder.put(e, i++);
- }
- this.inputSet = builder.build();
- checkArgument(inputSet.size() <= 30,
- "Too many elements to create power set: %s > 30", inputSet.size());
+ this.inputSet = Maps.indexMap(input);
+ checkArgument(
+ inputSet.size() <= 30, "Too many elements to create power set: %s > 30", inputSet.size());
}
- @Override public int size() {
+ @Override
+ public int size() {
return 1 << inputSet.size();
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Iterator<Set<E>> iterator() {
+ @Override
+ public Iterator<Set<E>> iterator() {
return new AbstractIndexedListIterator<Set<E>>(size()) {
- @Override protected Set<E> get(final int setBits) {
+ @Override
+ protected Set<E> get(final int setBits) {
return new SubSet<E>(inputSet, setBits);
}
};
}
- @Override public boolean contains(@Nullable Object obj) {
+ @Override
+ public boolean contains(@Nullable Object obj) {
if (obj instanceof Set) {
Set<?> set = (Set<?>) obj;
return inputSet.keySet().containsAll(set);
@@ -1311,7 +1359,8 @@ public final class Sets {
return false;
}
- @Override public boolean equals(@Nullable Object obj) {
+ @Override
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof PowerSet) {
PowerSet<?> that = (PowerSet<?>) obj;
return inputSet.equals(that.inputSet);
@@ -1319,7 +1368,8 @@ public final class Sets {
return super.equals(obj);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
/*
* The sum of the sums of the hash codes in each subset is just the sum of
* each input element's hash code times the number of sets that element
@@ -1328,7 +1378,8 @@ public final class Sets {
return inputSet.keySet().hashCode() << (inputSet.size() - 1);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "powerSet(" + inputSet + ")";
}
}
@@ -1385,18 +1436,16 @@ public final class Sets {
* @since 12.0
*/
@GwtIncompatible("NavigableSet")
- public static <E> NavigableSet<E> unmodifiableNavigableSet(
- NavigableSet<E> set) {
- if (set instanceof ImmutableSortedSet
- || set instanceof UnmodifiableNavigableSet) {
+ public static <E> NavigableSet<E> unmodifiableNavigableSet(NavigableSet<E> set) {
+ if (set instanceof ImmutableSortedSet || set instanceof UnmodifiableNavigableSet) {
return set;
}
return new UnmodifiableNavigableSet<E>(set);
}
@GwtIncompatible("NavigableSet")
- static final class UnmodifiableNavigableSet<E>
- extends ForwardingSortedSet<E> implements NavigableSet<E>, Serializable {
+ static final class UnmodifiableNavigableSet<E> extends ForwardingSortedSet<E>
+ implements NavigableSet<E>, Serializable {
private final NavigableSet<E> delegate;
UnmodifiableNavigableSet(NavigableSet<E> delegate) {
@@ -1444,8 +1493,7 @@ public final class Sets {
public NavigableSet<E> descendingSet() {
UnmodifiableNavigableSet<E> result = descendingSet;
if (result == null) {
- result = descendingSet = new UnmodifiableNavigableSet<E>(
- delegate.descendingSet());
+ result = descendingSet = new UnmodifiableNavigableSet<E>(delegate.descendingSet());
result.descendingSet = this;
}
return result;
@@ -1458,15 +1506,9 @@ public final class Sets {
@Override
public NavigableSet<E> subSet(
- E fromElement,
- boolean fromInclusive,
- E toElement,
- boolean toInclusive) {
- return unmodifiableNavigableSet(delegate.subSet(
- fromElement,
- fromInclusive,
- toElement,
- toInclusive));
+ E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+ return unmodifiableNavigableSet(
+ delegate.subSet(fromElement, fromInclusive, toElement, toInclusive));
}
@Override
@@ -1476,8 +1518,7 @@ public final class Sets {
@Override
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
- return unmodifiableNavigableSet(
- delegate.tailSet(fromElement, inclusive));
+ return unmodifiableNavigableSet(delegate.tailSet(fromElement, inclusive));
}
private static final long serialVersionUID = 0;
@@ -1527,8 +1568,7 @@ public final class Sets {
* @since 13.0
*/
@GwtIncompatible("NavigableSet")
- public static <E> NavigableSet<E> synchronizedNavigableSet(
- NavigableSet<E> navigableSet) {
+ public static <E> NavigableSet<E> synchronizedNavigableSet(NavigableSet<E> navigableSet) {
return Synchronized.navigableSet(navigableSet);
}
@@ -1617,10 +1657,7 @@ public final class Sets {
@Override
public NavigableSet<E> subSet(
- E fromElement,
- boolean fromInclusive,
- E toElement,
- boolean toInclusive) {
+ E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
return forward.subSet(toElement, toInclusive, fromElement, fromInclusive).descendingSet();
}
diff --git a/guava/src/com/google/common/collect/SingletonImmutableBiMap.java b/guava/src/com/google/common/collect/SingletonImmutableBiMap.java
index ffc93e9..d330190 100644
--- a/guava/src/com/google/common/collect/SingletonImmutableBiMap.java
+++ b/guava/src/com/google/common/collect/SingletonImmutableBiMap.java
@@ -41,18 +41,14 @@ final class SingletonImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
this.singleValue = singleValue;
}
- private SingletonImmutableBiMap(K singleKey, V singleValue,
- ImmutableBiMap<V, K> inverse) {
+ private SingletonImmutableBiMap(K singleKey, V singleValue, ImmutableBiMap<V, K> inverse) {
this.singleKey = singleKey;
this.singleValue = singleValue;
this.inverse = inverse;
}
- SingletonImmutableBiMap(Entry<? extends K, ? extends V> entry) {
- this(entry.getKey(), entry.getValue());
- }
-
- @Override public V get(@Nullable Object key) {
+ @Override
+ public V get(@Nullable Object key) {
return singleKey.equals(key) ? singleValue : null;
}
@@ -61,15 +57,18 @@ final class SingletonImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
return 1;
}
- @Override public boolean containsKey(@Nullable Object key) {
+ @Override
+ public boolean containsKey(@Nullable Object key) {
return singleKey.equals(key);
}
- @Override public boolean containsValue(@Nullable Object value) {
+ @Override
+ public boolean containsValue(@Nullable Object value) {
return singleValue.equals(value);
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return false;
}
@@ -90,8 +89,7 @@ final class SingletonImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
// racy single-check idiom
ImmutableBiMap<V, K> result = inverse;
if (result == null) {
- return inverse = new SingletonImmutableBiMap<V, K>(
- singleValue, singleKey, this);
+ return inverse = new SingletonImmutableBiMap<V, K>(singleValue, singleKey, this);
} else {
return result;
}
diff --git a/guava/src/com/google/common/collect/SingletonImmutableList.java b/guava/src/com/google/common/collect/SingletonImmutableList.java
index 18d8290..267d946 100644
--- a/guava/src/com/google/common/collect/SingletonImmutableList.java
+++ b/guava/src/com/google/common/collect/SingletonImmutableList.java
@@ -21,10 +21,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Preconditions;
-import java.util.List;
-
-import javax.annotation.Nullable;
-
/**
* Implementation of {@link ImmutableList} with exactly one element.
*
@@ -46,54 +42,24 @@ final class SingletonImmutableList<E> extends ImmutableList<E> {
return element;
}
- @Override public int indexOf(@Nullable Object object) {
- return element.equals(object) ? 0 : -1;
- }
-
- @Override public UnmodifiableIterator<E> iterator() {
+ @Override
+ public UnmodifiableIterator<E> iterator() {
return Iterators.singletonIterator(element);
}
- @Override public int lastIndexOf(@Nullable Object object) {
- return indexOf(object);
- }
-
@Override
public int size() {
return 1;
}
- @Override public ImmutableList<E> subList(int fromIndex, int toIndex) {
+ @Override
+ public ImmutableList<E> subList(int fromIndex, int toIndex) {
Preconditions.checkPositionIndexes(fromIndex, toIndex, 1);
return (fromIndex == toIndex) ? ImmutableList.<E>of() : this;
}
- @Override public ImmutableList<E> reverse() {
- return this;
- }
-
- @Override public boolean contains(@Nullable Object object) {
- return element.equals(object);
- }
-
- @Override public boolean equals(@Nullable Object object) {
- if (object == this) {
- return true;
- }
- if (object instanceof List) {
- List<?> that = (List<?>) object;
- return that.size() == 1 && element.equals(that.get(0));
- }
- return false;
- }
-
- @Override public int hashCode() {
- // not caching hash code since it could change if the element is mutable
- // in a way that modifies its hash code.
- return 31 + element.hashCode();
- }
-
- @Override public String toString() {
+ @Override
+ public String toString() {
String elementToString = element.toString();
return new StringBuilder(elementToString.length() + 2)
.append('[')
@@ -102,17 +68,8 @@ final class SingletonImmutableList<E> extends ImmutableList<E> {
.toString();
}
- @Override public boolean isEmpty() {
- return false;
- }
-
- @Override boolean isPartialView() {
- return false;
- }
-
@Override
- int copyIntoArray(Object[] dst, int offset) {
- dst[offset] = element;
- return offset + 1;
+ boolean isPartialView() {
+ return false;
}
}
diff --git a/guava/src/com/google/common/collect/SingletonImmutableSet.java b/guava/src/com/google/common/collect/SingletonImmutableSet.java
index 50c932c..9067e60 100644
--- a/guava/src/com/google/common/collect/SingletonImmutableSet.java
+++ b/guava/src/com/google/common/collect/SingletonImmutableSet.java
@@ -19,10 +19,6 @@ package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Preconditions;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
/**
* Implementation of {@link ImmutableSet} with exactly one element.
*
@@ -58,19 +54,18 @@ final class SingletonImmutableSet<E> extends ImmutableSet<E> {
return 1;
}
- @Override public boolean isEmpty() {
- return false;
- }
-
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
return element.equals(target);
}
- @Override public UnmodifiableIterator<E> iterator() {
+ @Override
+ public UnmodifiableIterator<E> iterator() {
return Iterators.singletonIterator(element);
}
- @Override boolean isPartialView() {
+ @Override
+ boolean isPartialView() {
return false;
}
@@ -80,18 +75,8 @@ final class SingletonImmutableSet<E> extends ImmutableSet<E> {
return offset + 1;
}
- @Override public boolean equals(@Nullable Object object) {
- if (object == this) {
- return true;
- }
- if (object instanceof Set) {
- Set<?> that = (Set<?>) object;
- return that.size() == 1 && element.equals(that.iterator().next());
- }
- return false;
- }
-
- @Override public final int hashCode() {
+ @Override
+ public final int hashCode() {
// Racy single-check.
int code = cachedHashCode;
if (code == 0) {
@@ -100,11 +85,13 @@ final class SingletonImmutableSet<E> extends ImmutableSet<E> {
return code;
}
- @Override boolean isHashCodeFast() {
+ @Override
+ boolean isHashCodeFast() {
return cachedHashCode != 0;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
String elementToString = element.toString();
return new StringBuilder(elementToString.length() + 2)
.append('[')
diff --git a/guava/src/com/google/common/collect/SingletonImmutableTable.java b/guava/src/com/google/common/collect/SingletonImmutableTable.java
index 490ece7..33e89cd 100644
--- a/guava/src/com/google/common/collect/SingletonImmutableTable.java
+++ b/guava/src/com/google/common/collect/SingletonImmutableTable.java
@@ -43,34 +43,36 @@ class SingletonImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
this(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
}
- @Override public ImmutableMap<R, V> column(C columnKey) {
+ @Override
+ public ImmutableMap<R, V> column(C columnKey) {
checkNotNull(columnKey);
return containsColumn(columnKey)
? ImmutableMap.of(singleRowKey, singleValue)
: ImmutableMap.<R, V>of();
}
- @Override public ImmutableMap<C, Map<R, V>> columnMap() {
- return ImmutableMap.of(singleColumnKey,
- (Map<R, V>) ImmutableMap.of(singleRowKey, singleValue));
+ @Override
+ public ImmutableMap<C, Map<R, V>> columnMap() {
+ return ImmutableMap.of(singleColumnKey, (Map<R, V>) ImmutableMap.of(singleRowKey, singleValue));
}
- @Override public ImmutableMap<R, Map<C, V>> rowMap() {
- return ImmutableMap.of(singleRowKey,
- (Map<C, V>) ImmutableMap.of(singleColumnKey, singleValue));
+ @Override
+ public ImmutableMap<R, Map<C, V>> rowMap() {
+ return ImmutableMap.of(singleRowKey, (Map<C, V>) ImmutableMap.of(singleColumnKey, singleValue));
}
- @Override public int size() {
+ @Override
+ public int size() {
return 1;
}
@Override
ImmutableSet<Cell<R, C, V>> createCellSet() {
- return ImmutableSet.of(
- cellOf(singleRowKey, singleColumnKey, singleValue));
+ return ImmutableSet.of(cellOf(singleRowKey, singleColumnKey, singleValue));
}
- @Override ImmutableCollection<V> createValues() {
+ @Override
+ ImmutableCollection<V> createValues() {
return ImmutableSet.of(singleValue);
}
}
diff --git a/guava/src/com/google/common/collect/SortedLists.java b/guava/src/com/google/common/collect/SortedLists.java
index 6fc0d71..bc7cad7 100644
--- a/guava/src/com/google/common/collect/SortedLists.java
+++ b/guava/src/com/google/common/collect/SortedLists.java
@@ -128,6 +128,7 @@ import javax.annotation.Nullable;
return FIRST_PRESENT.resultIndex(comparator, key, list, foundIndex) - 1;
}
};
+
abstract <E> int resultIndex(
Comparator<? super E> comparator, E key, List<? extends E> list, int foundIndex);
}
@@ -186,11 +187,13 @@ import javax.annotation.Nullable;
* <p>Equivalent to {@link #binarySearch(List, Function, Object, Comparator, KeyPresentBehavior,
* KeyAbsentBehavior)} using {@link Ordering#natural}.
*/
- public static <E extends Comparable> int binarySearch(List<? extends E> list, E e,
- KeyPresentBehavior presentBehavior, KeyAbsentBehavior absentBehavior) {
+ public static <E extends Comparable> int binarySearch(
+ List<? extends E> list,
+ E e,
+ KeyPresentBehavior presentBehavior,
+ KeyAbsentBehavior absentBehavior) {
checkNotNull(e);
- return binarySearch(
- list, checkNotNull(e), Ordering.natural(), presentBehavior, absentBehavior);
+ return binarySearch(list, e, Ordering.natural(), presentBehavior, absentBehavior);
}
/**
@@ -199,16 +202,14 @@ import javax.annotation.Nullable;
* <p>Equivalent to {@link #binarySearch(List, Function, Object, Comparator, KeyPresentBehavior,
* KeyAbsentBehavior)} using {@link Ordering#natural}.
*/
- public static <E, K extends Comparable> int binarySearch(List<E> list,
- Function<? super E, K> keyFunction, @Nullable K key, KeyPresentBehavior presentBehavior,
+ public static <E, K extends Comparable> int binarySearch(
+ List<E> list,
+ Function<? super E, K> keyFunction,
+ @Nullable K key,
+ KeyPresentBehavior presentBehavior,
KeyAbsentBehavior absentBehavior) {
return binarySearch(
- list,
- keyFunction,
- key,
- Ordering.natural(),
- presentBehavior,
- absentBehavior);
+ list, keyFunction, key, Ordering.natural(), presentBehavior, absentBehavior);
}
/**
@@ -252,8 +253,11 @@ import javax.annotation.Nullable;
* @return the index determined by the {@code KeyPresentBehavior}, if the key is in the list;
* otherwise the index determined by the {@code KeyAbsentBehavior}.
*/
- public static <E> int binarySearch(List<? extends E> list, @Nullable E key,
- Comparator<? super E> comparator, KeyPresentBehavior presentBehavior,
+ public static <E> int binarySearch(
+ List<? extends E> list,
+ @Nullable E key,
+ Comparator<? super E> comparator,
+ KeyPresentBehavior presentBehavior,
KeyAbsentBehavior absentBehavior) {
checkNotNull(comparator);
checkNotNull(list);
@@ -262,7 +266,7 @@ import javax.annotation.Nullable;
if (!(list instanceof RandomAccess)) {
list = Lists.newArrayList(list);
}
- // TODO(user): benchmark when it's best to do a linear search
+ // TODO(lowasser): benchmark when it's best to do a linear search
int lower = 0;
int upper = list.size() - 1;
diff --git a/guava/src/com/google/common/collect/SortedMultiset.java b/guava/src/com/google/common/collect/SortedMultiset.java
index de1f3e0..8c92212 100644
--- a/guava/src/com/google/common/collect/SortedMultiset.java
+++ b/guava/src/com/google/common/collect/SortedMultiset.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2011 The Guava Authors
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -33,16 +33,16 @@ import java.util.Set;
* this implementation uses {@link Comparable#compareTo} or
* {@link Comparator#compare} instead of {@link Object#equals} to determine
* equivalence of instances.
- *
+ *
* <p><b>Warning:</b> The comparison must be <i>consistent with equals</i> as
* explained by the {@link Comparable} class specification. Otherwise, the
* resulting multiset will violate the {@link Collection} contract, which it is
* specified in terms of {@link Object#equals}.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
* {@code Multiset}</a>.
- *
+ *
* @author Louis Wasserman
* @since 11.0
*/
@@ -81,18 +81,20 @@ public interface SortedMultiset<E> extends SortedMultisetBridge<E>, SortedIterab
/**
* Returns a {@link NavigableSet} view of the distinct elements in this multiset.
- *
+ *
* @since 14.0 (present with return type {@code SortedSet} since 11.0)
*/
- @Override NavigableSet<E> elementSet();
-
+ @Override
+ NavigableSet<E> elementSet();
+
/**
* {@inheritDoc}
*
* <p>The {@code entrySet}'s iterator returns entries in ascending element
* order according to the this multiset's comparator.
*/
- @Override Set<Entry<E>> entrySet();
+ @Override
+ Set<Entry<E>> entrySet();
/**
* {@inheritDoc}
@@ -100,7 +102,8 @@ public interface SortedMultiset<E> extends SortedMultisetBridge<E>, SortedIterab
* <p>The iterator returns the elements in ascending order according to this
* multiset's comparator.
*/
- @Override Iterator<E> iterator();
+ @Override
+ Iterator<E> iterator();
/**
* Returns a descending view of this multiset. Modifications made to either
@@ -114,7 +117,7 @@ public interface SortedMultiset<E> extends SortedMultisetBridge<E>, SortedIterab
* returned multiset is a view of this multiset, so changes to one will be
* reflected in the other. The returned multiset supports all operations that
* this multiset supports.
- *
+ *
* <p>The returned multiset will throw an {@link IllegalArgumentException} on
* attempts to add elements outside its range.
*/
@@ -125,16 +128,16 @@ public interface SortedMultiset<E> extends SortedMultisetBridge<E>, SortedIterab
* {@code lowerBound} and {@code upperBound}. The returned multiset is a view
* of this multiset, so changes to one will be reflected in the other. The
* returned multiset supports all operations that this multiset supports.
- *
+ *
* <p>The returned multiset will throw an {@link IllegalArgumentException} on
* attempts to add elements outside its range.
- *
+ *
* <p>This method is equivalent to
* {@code tailMultiset(lowerBound, lowerBoundType).headMultiset(upperBound,
* upperBoundType)}.
*/
- SortedMultiset<E> subMultiset(E lowerBound, BoundType lowerBoundType,
- E upperBound, BoundType upperBoundType);
+ SortedMultiset<E> subMultiset(
+ E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType);
/**
* Returns a view of this multiset restricted to the elements greater than
@@ -142,7 +145,7 @@ public interface SortedMultiset<E> extends SortedMultisetBridge<E>, SortedIterab
* returned multiset is a view of this multiset, so changes to one will be
* reflected in the other. The returned multiset supports all operations that
* this multiset supports.
- *
+ *
* <p>The returned multiset will throw an {@link IllegalArgumentException} on
* attempts to add elements outside its range.
*/
diff --git a/guava/src/com/google/common/collect/SortedMultisetBridge.java b/guava/src/com/google/common/collect/SortedMultisetBridge.java
index 669b54d..a2d04ed 100644
--- a/guava/src/com/google/common/collect/SortedMultisetBridge.java
+++ b/guava/src/com/google/common/collect/SortedMultisetBridge.java
@@ -22,7 +22,7 @@ import java.util.SortedSet;
* Superinterface of {@link SortedMultiset} to introduce a bridge method for
* {@code elementSet()}, to ensure binary compatibility with older Guava versions
* that specified {@code elementSet()} to return {@code SortedSet}.
- *
+ *
* @author Louis Wasserman
*/
interface SortedMultisetBridge<E> extends Multiset<E> {
diff --git a/guava/src/com/google/common/collect/SortedMultisets.java b/guava/src/com/google/common/collect/SortedMultisets.java
index 1055664..b0695a2 100644
--- a/guava/src/com/google/common/collect/SortedMultisets.java
+++ b/guava/src/com/google/common/collect/SortedMultisets.java
@@ -22,6 +22,7 @@ import static com.google.common.collect.BoundType.OPEN;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.Multiset.Entry;
+import com.google.j2objc.annotations.Weak;
import java.util.Comparator;
import java.util.Iterator;
@@ -39,45 +40,50 @@ import javax.annotation.Nullable;
*/
@GwtCompatible(emulated = true)
final class SortedMultisets {
- private SortedMultisets() {
- }
+ private SortedMultisets() {}
/**
* A skeleton implementation for {@link SortedMultiset#elementSet}.
*/
- static class ElementSet<E> extends Multisets.ElementSet<E> implements
- SortedSet<E> {
- private final SortedMultiset<E> multiset;
+ static class ElementSet<E> extends Multisets.ElementSet<E> implements SortedSet<E> {
+ @Weak private final SortedMultiset<E> multiset;
ElementSet(SortedMultiset<E> multiset) {
this.multiset = multiset;
}
- @Override final SortedMultiset<E> multiset() {
+ @Override
+ final SortedMultiset<E> multiset() {
return multiset;
}
- @Override public Comparator<? super E> comparator() {
+ @Override
+ public Comparator<? super E> comparator() {
return multiset().comparator();
}
- @Override public SortedSet<E> subSet(E fromElement, E toElement) {
+ @Override
+ public SortedSet<E> subSet(E fromElement, E toElement) {
return multiset().subMultiset(fromElement, CLOSED, toElement, OPEN).elementSet();
}
- @Override public SortedSet<E> headSet(E toElement) {
+ @Override
+ public SortedSet<E> headSet(E toElement) {
return multiset().headMultiset(toElement, OPEN).elementSet();
}
- @Override public SortedSet<E> tailSet(E fromElement) {
+ @Override
+ public SortedSet<E> tailSet(E fromElement) {
return multiset().tailMultiset(fromElement, CLOSED).elementSet();
}
- @Override public E first() {
+ @Override
+ public E first() {
return getElementOrThrow(multiset().firstEntry());
}
- @Override public E last() {
+ @Override
+ public E last() {
return getElementOrThrow(multiset().lastEntry());
}
}
@@ -134,9 +140,10 @@ final class SortedMultisets {
@Override
public NavigableSet<E> subSet(
E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
- return new NavigableElementSet<E>(multiset().subMultiset(
- fromElement, BoundType.forBoolean(fromInclusive),
- toElement, BoundType.forBoolean(toInclusive)));
+ return new NavigableElementSet<E>(
+ multiset().subMultiset(
+ fromElement, BoundType.forBoolean(fromInclusive),
+ toElement, BoundType.forBoolean(toInclusive)));
}
@Override
diff --git a/guava/src/com/google/common/collect/SortedSetMultimap.java b/guava/src/com/google/common/collect/SortedSetMultimap.java
index 8077618..436ca5d 100644
--- a/guava/src/com/google/common/collect/SortedSetMultimap.java
+++ b/guava/src/com/google/common/collect/SortedSetMultimap.java
@@ -39,13 +39,13 @@ import javax.annotation.Nullable;
* returns a {@link Set} of map entries. Though the method signature doesn't say
* so explicitly, the map returned by {@link #asMap} has {@code SortedSet}
* values.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
* {@code Multimap}</a>.
*
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public interface SortedSetMultimap<K, V> extends SetMultimap<K, V> {
@@ -105,7 +105,8 @@ public interface SortedSetMultimap<K, V> extends SetMultimap<K, V> {
* {@code Map<K, SortedSet<V>>}, call
* {@link Multimaps#asMap(SortedSetMultimap)} instead.
*/
- @Override Map<K, Collection<V>> asMap();
+ @Override
+ Map<K, Collection<V>> asMap();
/**
* Returns the comparator that orders the multimap values, with {@code null}
diff --git a/guava/src/com/google/common/collect/SparseImmutableTable.java b/guava/src/com/google/common/collect/SparseImmutableTable.java
index 7be096b..deebd11 100644
--- a/guava/src/com/google/common/collect/SparseImmutableTable.java
+++ b/guava/src/com/google/common/collect/SparseImmutableTable.java
@@ -26,20 +26,20 @@ import javax.annotation.concurrent.Immutable;
*/
@GwtCompatible
@Immutable
-final class SparseImmutableTable<R, C, V>
- extends RegularImmutableTable<R, C, V> {
+final class SparseImmutableTable<R, C, V> extends RegularImmutableTable<R, C, V> {
private final ImmutableMap<R, Map<C, V>> rowMap;
private final ImmutableMap<C, Map<R, V>> columnMap;
private final int[] iterationOrderRow;
private final int[] iterationOrderColumn;
- SparseImmutableTable(ImmutableList<Cell<R, C, V>> cellList,
- ImmutableSet<R> rowSpace, ImmutableSet<C> columnSpace) {
- Map<R, Integer> rowIndex = Maps.newHashMap();
+ SparseImmutableTable(
+ ImmutableList<Cell<R, C, V>> cellList,
+ ImmutableSet<R> rowSpace,
+ ImmutableSet<C> columnSpace) {
+ Map<R, Integer> rowIndex = Maps.indexMap(rowSpace);
Map<R, Map<C, V>> rows = Maps.newLinkedHashMap();
for (R row : rowSpace) {
- rowIndex.put(row, rows.size());
rows.put(row, new LinkedHashMap<C, V>());
}
Map<C, Map<R, V>> columns = Maps.newLinkedHashMap();
@@ -53,37 +53,42 @@ final class SparseImmutableTable<R, C, V>
R rowKey = cell.getRowKey();
C columnKey = cell.getColumnKey();
V value = cell.getValue();
-
+
iterationOrderRow[i] = rowIndex.get(rowKey);
Map<C, V> thisRow = rows.get(rowKey);
iterationOrderColumn[i] = thisRow.size();
V oldValue = thisRow.put(columnKey, value);
if (oldValue != null) {
- throw new IllegalArgumentException("Duplicate value for row=" + rowKey + ", column="
- + columnKey + ": " + value + ", " + oldValue);
+ throw new IllegalArgumentException(
+ "Duplicate value for row=" + rowKey + ", column=" + columnKey + ": "
+ + value + ", " + oldValue);
}
columns.get(columnKey).put(rowKey, value);
}
this.iterationOrderRow = iterationOrderRow;
this.iterationOrderColumn = iterationOrderColumn;
- ImmutableMap.Builder<R, Map<C, V>> rowBuilder = ImmutableMap.builder();
+ ImmutableMap.Builder<R, Map<C, V>> rowBuilder =
+ new ImmutableMap.Builder<R, Map<C, V>>(rows.size());
for (Map.Entry<R, Map<C, V>> row : rows.entrySet()) {
rowBuilder.put(row.getKey(), ImmutableMap.copyOf(row.getValue()));
}
this.rowMap = rowBuilder.build();
-
- ImmutableMap.Builder<C, Map<R, V>> columnBuilder = ImmutableMap.builder();
+
+ ImmutableMap.Builder<C, Map<R, V>> columnBuilder =
+ new ImmutableMap.Builder<C, Map<R, V>>(columns.size());
for (Map.Entry<C, Map<R, V>> col : columns.entrySet()) {
columnBuilder.put(col.getKey(), ImmutableMap.copyOf(col.getValue()));
}
this.columnMap = columnBuilder.build();
}
- @Override public ImmutableMap<C, Map<R, V>> columnMap() {
+ @Override
+ public ImmutableMap<C, Map<R, V>> columnMap() {
return columnMap;
}
- @Override public ImmutableMap<R, Map<C, V>> rowMap() {
+ @Override
+ public ImmutableMap<R, Map<C, V>> rowMap() {
return rowMap;
}
@@ -91,7 +96,7 @@ final class SparseImmutableTable<R, C, V>
public int size() {
return iterationOrderRow.length;
}
-
+
@Override
Cell<R, C, V> getCell(int index) {
int rowIndex = iterationOrderRow[index];
diff --git a/guava/src/com/google/common/collect/StandardRowSortedTable.java b/guava/src/com/google/common/collect/StandardRowSortedTable.java
index eaaf002..54bd03c 100644
--- a/guava/src/com/google/common/collect/StandardRowSortedTable.java
+++ b/guava/src/com/google/common/collect/StandardRowSortedTable.java
@@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Supplier;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.Comparator;
import java.util.Map;
@@ -54,8 +55,8 @@ class StandardRowSortedTable<R, C, V> extends StandardTable<R, C, V>
* RowSortedTable subinterface with the revised methods?
*/
- StandardRowSortedTable(SortedMap<R, Map<C, V>> backingMap,
- Supplier<? extends Map<C, V>> factory) {
+ StandardRowSortedTable(
+ SortedMap<R, Map<C, V>> backingMap, Supplier<? extends Map<C, V>> factory) {
super(backingMap, factory);
}
@@ -69,7 +70,8 @@ class StandardRowSortedTable<R, C, V> extends StandardTable<R, C, V>
* <p>This method returns a {@link SortedSet}, instead of the {@code Set}
* specified in the {@link Table} interface.
*/
- @Override public SortedSet<R> rowKeySet() {
+ @Override
+ public SortedSet<R> rowKeySet() {
return (SortedSet<R>) rowMap().keySet();
}
@@ -79,7 +81,8 @@ class StandardRowSortedTable<R, C, V> extends StandardTable<R, C, V>
* <p>This method returns a {@link SortedMap}, instead of the {@code Map}
* specified in the {@link Table} interface.
*/
- @Override public SortedMap<R, Map<C, V>> rowMap() {
+ @Override
+ public SortedMap<R, Map<C, V>> rowMap() {
return (SortedMap<R, Map<C, V>>) super.rowMap();
}
@@ -88,6 +91,7 @@ class StandardRowSortedTable<R, C, V> extends StandardTable<R, C, V>
return new RowSortedMap();
}
+ @WeakOuter
private class RowSortedMap extends RowMap implements SortedMap<R, Map<C, V>> {
@Override
public SortedSet<R> keySet() {
@@ -117,23 +121,23 @@ class StandardRowSortedTable<R, C, V> extends StandardTable<R, C, V>
@Override
public SortedMap<R, Map<C, V>> headMap(R toKey) {
checkNotNull(toKey);
- return new StandardRowSortedTable<R, C, V>(
- sortedBackingMap().headMap(toKey), factory).rowMap();
+ return new StandardRowSortedTable<R, C, V>(sortedBackingMap().headMap(toKey), factory)
+ .rowMap();
}
@Override
public SortedMap<R, Map<C, V>> subMap(R fromKey, R toKey) {
checkNotNull(fromKey);
checkNotNull(toKey);
- return new StandardRowSortedTable<R, C, V>(
- sortedBackingMap().subMap(fromKey, toKey), factory).rowMap();
+ return new StandardRowSortedTable<R, C, V>(sortedBackingMap().subMap(fromKey, toKey), factory)
+ .rowMap();
}
@Override
public SortedMap<R, Map<C, V>> tailMap(R fromKey) {
checkNotNull(fromKey);
- return new StandardRowSortedTable<R, C, V>(
- sortedBackingMap().tailMap(fromKey), factory).rowMap();
+ return new StandardRowSortedTable<R, C, V>(sortedBackingMap().tailMap(fromKey), factory)
+ .rowMap();
}
}
diff --git a/guava/src/com/google/common/collect/StandardTable.java b/guava/src/com/google/common/collect/StandardTable.java
index 06aa37d..6d7d751 100644
--- a/guava/src/com/google/common/collect/StandardTable.java
+++ b/guava/src/com/google/common/collect/StandardTable.java
@@ -28,8 +28,10 @@ import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
-import com.google.common.collect.Maps.ImprovedAbstractMap;
+import com.google.common.collect.Maps.IteratorBasedAbstractMap;
+import com.google.common.collect.Maps.ViewCachingAbstractMap;
import com.google.common.collect.Sets.ImprovedAbstractSet;
+import com.google.j2objc.annotations.WeakOuter;
import java.io.Serializable;
import java.util.Collection;
@@ -68,20 +70,20 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
@GwtTransient final Map<R, Map<C, V>> backingMap;
@GwtTransient final Supplier<? extends Map<C, V>> factory;
- StandardTable(Map<R, Map<C, V>> backingMap,
- Supplier<? extends Map<C, V>> factory) {
+ StandardTable(Map<R, Map<C, V>> backingMap, Supplier<? extends Map<C, V>> factory) {
this.backingMap = backingMap;
this.factory = factory;
}
// Accessors
- @Override public boolean contains(
- @Nullable Object rowKey, @Nullable Object columnKey) {
+ @Override
+ public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
return rowKey != null && columnKey != null && super.contains(rowKey, columnKey);
}
- @Override public boolean containsColumn(@Nullable Object columnKey) {
+ @Override
+ public boolean containsColumn(@Nullable Object columnKey) {
if (columnKey == null) {
return false;
}
@@ -93,25 +95,28 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return false;
}
- @Override public boolean containsRow(@Nullable Object rowKey) {
+ @Override
+ public boolean containsRow(@Nullable Object rowKey) {
return rowKey != null && safeContainsKey(backingMap, rowKey);
}
- @Override public boolean containsValue(@Nullable Object value) {
+ @Override
+ public boolean containsValue(@Nullable Object value) {
return value != null && super.containsValue(value);
}
- @Override public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
- return (rowKey == null || columnKey == null)
- ? null
- : super.get(rowKey, columnKey);
+ @Override
+ public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
+ return (rowKey == null || columnKey == null) ? null : super.get(rowKey, columnKey);
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return backingMap.isEmpty();
}
- @Override public int size() {
+ @Override
+ public int size() {
int size = 0;
for (Map<C, V> map : backingMap.values()) {
size += map.size();
@@ -121,7 +126,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
// Mutators
- @Override public void clear() {
+ @Override
+ public void clear() {
backingMap.clear();
}
@@ -134,15 +140,16 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return map;
}
- @Override public V put(R rowKey, C columnKey, V value) {
+ @Override
+ public V put(R rowKey, C columnKey, V value) {
checkNotNull(rowKey);
checkNotNull(columnKey);
checkNotNull(value);
return getOrCreate(rowKey).put(columnKey, value);
}
- @Override public V remove(
- @Nullable Object rowKey, @Nullable Object columnKey) {
+ @Override
+ public V remove(@Nullable Object rowKey, @Nullable Object columnKey) {
if ((rowKey == null) || (columnKey == null)) {
return null;
}
@@ -159,8 +166,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
private Map<R, V> removeColumn(Object column) {
Map<R, V> output = new LinkedHashMap<R, V>();
- Iterator<Entry<R, Map<C, V>>> iterator
- = backingMap.entrySet().iterator();
+ Iterator<Entry<R, Map<C, V>>> iterator = backingMap.entrySet().iterator();
while (iterator.hasNext()) {
Entry<R, Map<C, V>> entry = iterator.next();
V value = entry.getValue().remove(column);
@@ -174,8 +180,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return output;
}
- private boolean containsMapping(
- Object rowKey, Object columnKey, Object value) {
+ private boolean containsMapping(Object rowKey, Object columnKey, Object value) {
return value != null && value.equals(get(rowKey, columnKey));
}
@@ -194,12 +199,15 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
* Abstract set whose {@code isEmpty()} returns whether the table is empty and
* whose {@code clear()} clears all table mappings.
*/
+ @WeakOuter
private abstract class TableSet<T> extends ImprovedAbstractSet<T> {
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return backingMap.isEmpty();
}
- @Override public void clear() {
+ @Override
+ public void clear() {
backingMap.clear();
}
}
@@ -214,36 +222,38 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
* mapping, taken at the time the cell is returned by a method call to the
* set or its iterator.
*/
- @Override public Set<Cell<R, C, V>> cellSet() {
+ @Override
+ public Set<Cell<R, C, V>> cellSet() {
return super.cellSet();
}
- @Override Iterator<Cell<R, C, V>> cellIterator() {
+ @Override
+ Iterator<Cell<R, C, V>> cellIterator() {
return new CellIterator();
}
private class CellIterator implements Iterator<Cell<R, C, V>> {
- final Iterator<Entry<R, Map<C, V>>> rowIterator
- = backingMap.entrySet().iterator();
+ final Iterator<Entry<R, Map<C, V>>> rowIterator = backingMap.entrySet().iterator();
Entry<R, Map<C, V>> rowEntry;
- Iterator<Entry<C, V>> columnIterator
- = Iterators.emptyModifiableIterator();
+ Iterator<Entry<C, V>> columnIterator = Iterators.emptyModifiableIterator();
- @Override public boolean hasNext() {
+ @Override
+ public boolean hasNext() {
return rowIterator.hasNext() || columnIterator.hasNext();
}
- @Override public Cell<R, C, V> next() {
+ @Override
+ public Cell<R, C, V> next() {
if (!columnIterator.hasNext()) {
rowEntry = rowIterator.next();
columnIterator = rowEntry.getValue().entrySet().iterator();
}
Entry<C, V> columnEntry = columnIterator.next();
- return Tables.immutableCell(
- rowEntry.getKey(), columnEntry.getKey(), columnEntry.getValue());
+ return Tables.immutableCell(rowEntry.getKey(), columnEntry.getKey(), columnEntry.getValue());
}
- @Override public void remove() {
+ @Override
+ public void remove() {
columnIterator.remove();
if (rowEntry.getValue().isEmpty()) {
rowIterator.remove();
@@ -251,11 +261,12 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
}
}
- @Override public Map<C, V> row(R rowKey) {
+ @Override
+ public Map<C, V> row(R rowKey) {
return new Row(rowKey);
}
- class Row extends ImprovedAbstractMap<C, V> {
+ class Row extends IteratorBasedAbstractMap<C, V> {
final R rowKey;
Row(R rowKey) {
@@ -265,8 +276,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
Map<C, V> backingRowMap;
Map<C, V> backingRowMap() {
- return (backingRowMap == null
- || (backingRowMap.isEmpty() && backingMap.containsKey(rowKey)))
+ return (backingRowMap == null || (backingRowMap.isEmpty() && backingMap.containsKey(rowKey)))
? backingRowMap = computeBackingRowMap()
: backingRowMap;
}
@@ -286,16 +296,13 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
@Override
public boolean containsKey(Object key) {
Map<C, V> backingRowMap = backingRowMap();
- return (key != null && backingRowMap != null)
- && Maps.safeContainsKey(backingRowMap, key);
+ return (key != null && backingRowMap != null) && Maps.safeContainsKey(backingRowMap, key);
}
@Override
public V get(Object key) {
Map<C, V> backingRowMap = backingRowMap();
- return (key != null && backingRowMap != null)
- ? Maps.safeGet(backingRowMap, key)
- : null;
+ return (key != null && backingRowMap != null) ? Maps.safeGet(backingRowMap, key) : null;
}
@Override
@@ -329,57 +336,52 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
}
@Override
- protected Set<Entry<C, V>> createEntrySet() {
- return new RowEntrySet();
+ public int size() {
+ Map<C, V> map = backingRowMap();
+ return (map == null) ? 0 : map.size();
}
- private final class RowEntrySet extends Maps.EntrySet<C, V> {
- @Override
- Map<C, V> map() {
- return Row.this;
- }
-
- @Override
- public int size() {
- Map<C, V> map = backingRowMap();
- return (map == null) ? 0 : map.size();
- }
+ @Override
+ Iterator<Entry<C, V>> entryIterator() {
+ final Map<C, V> map = backingRowMap();
+ if (map == null) {
+ return Iterators.emptyModifiableIterator();
+ }
+ final Iterator<Entry<C, V>> iterator = map.entrySet().iterator();
+ return new Iterator<Entry<C, V>>() {
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
- @Override
- public Iterator<Entry<C, V>> iterator() {
- final Map<C, V> map = backingRowMap();
- if (map == null) {
- return Iterators.emptyModifiableIterator();
+ @Override
+ public Entry<C, V> next() {
+ final Entry<C, V> entry = iterator.next();
+ return new ForwardingMapEntry<C, V>() {
+ @Override
+ protected Entry<C, V> delegate() {
+ return entry;
+ }
+
+ @Override
+ public V setValue(V value) {
+ return super.setValue(checkNotNull(value));
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ // TODO(lowasser): identify why this affects GWT tests
+ return standardEquals(object);
+ }
+ };
}
- final Iterator<Entry<C, V>> iterator = map.entrySet().iterator();
- return new Iterator<Entry<C, V>>() {
- @Override public boolean hasNext() {
- return iterator.hasNext();
- }
- @Override public Entry<C, V> next() {
- final Entry<C, V> entry = iterator.next();
- return new ForwardingMapEntry<C, V>() {
- @Override protected Entry<C, V> delegate() {
- return entry;
- }
- @Override public V setValue(V value) {
- return super.setValue(checkNotNull(value));
- }
- @Override
- public boolean equals(Object object) {
- // TODO(user): identify why this affects GWT tests
- return standardEquals(object);
- }
- };
- }
- @Override
- public void remove() {
- iterator.remove();
- maintainEmptyInvariant();
- }
- };
- }
+ @Override
+ public void remove() {
+ iterator.remove();
+ maintainEmptyInvariant();
+ }
+ };
}
}
@@ -389,30 +391,35 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
* <p>The returned map's views have iterators that don't support
* {@code remove()}.
*/
- @Override public Map<R, V> column(C columnKey) {
+ @Override
+ public Map<R, V> column(C columnKey) {
return new Column(columnKey);
}
- private class Column extends ImprovedAbstractMap<R, V> {
+ private class Column extends ViewCachingAbstractMap<R, V> {
final C columnKey;
Column(C columnKey) {
this.columnKey = checkNotNull(columnKey);
}
- @Override public V put(R key, V value) {
+ @Override
+ public V put(R key, V value) {
return StandardTable.this.put(key, columnKey, value);
}
- @Override public V get(Object key) {
+ @Override
+ public V get(Object key) {
return StandardTable.this.get(key, columnKey);
}
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return StandardTable.this.contains(key, columnKey);
}
- @Override public V remove(Object key) {
+ @Override
+ public V remove(Object key) {
return StandardTable.this.remove(key, columnKey);
}
@@ -422,14 +429,12 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
*/
boolean removeFromColumnIf(Predicate<? super Entry<R, V>> predicate) {
boolean changed = false;
- Iterator<Entry<R, Map<C, V>>> iterator
- = backingMap.entrySet().iterator();
+ Iterator<Entry<R, Map<C, V>>> iterator = backingMap.entrySet().iterator();
while (iterator.hasNext()) {
Entry<R, Map<C, V>> entry = iterator.next();
Map<C, V> map = entry.getValue();
V value = map.get(columnKey);
- if (value != null
- && predicate.apply(Maps.immutableEntry(entry.getKey(), value))) {
+ if (value != null && predicate.apply(Maps.immutableEntry(entry.getKey(), value))) {
map.remove(columnKey);
changed = true;
if (map.isEmpty()) {
@@ -440,16 +445,20 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return changed;
}
- @Override Set<Entry<R, V>> createEntrySet() {
+ @Override
+ Set<Entry<R, V>> createEntrySet() {
return new EntrySet();
}
+ @WeakOuter
private class EntrySet extends ImprovedAbstractSet<Entry<R, V>> {
- @Override public Iterator<Entry<R, V>> iterator() {
+ @Override
+ public Iterator<Entry<R, V>> iterator() {
return new EntrySetIterator();
}
- @Override public int size() {
+ @Override
+ public int size() {
int size = 0;
for (Map<C, V> map : backingMap.values()) {
if (map.containsKey(columnKey)) {
@@ -459,15 +468,18 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return size;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return !containsColumn(columnKey);
}
- @Override public void clear() {
+ @Override
+ public void clear() {
removeFromColumnIf(alwaysTrue());
}
- @Override public boolean contains(Object o) {
+ @Override
+ public boolean contains(Object o) {
if (o instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) o;
return containsMapping(entry.getKey(), columnKey, entry.getValue());
@@ -475,7 +487,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return false;
}
- @Override public boolean remove(Object obj) {
+ @Override
+ public boolean remove(Object obj) {
if (obj instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) obj;
return removeMapping(entry.getKey(), columnKey, entry.getValue());
@@ -483,53 +496,67 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return false;
}
- @Override public boolean retainAll(Collection<?> c) {
+ @Override
+ public boolean retainAll(Collection<?> c) {
return removeFromColumnIf(not(in(c)));
}
}
private class EntrySetIterator extends AbstractIterator<Entry<R, V>> {
- final Iterator<Entry<R, Map<C, V>>> iterator
- = backingMap.entrySet().iterator();
- @Override protected Entry<R, V> computeNext() {
+ final Iterator<Entry<R, Map<C, V>>> iterator = backingMap.entrySet().iterator();
+
+ @Override
+ protected Entry<R, V> computeNext() {
while (iterator.hasNext()) {
final Entry<R, Map<C, V>> entry = iterator.next();
if (entry.getValue().containsKey(columnKey)) {
- return new AbstractMapEntry<R, V>() {
- @Override public R getKey() {
+ @WeakOuter
+ class EntryImpl extends AbstractMapEntry<R, V> {
+ @Override
+ public R getKey() {
return entry.getKey();
}
- @Override public V getValue() {
+
+ @Override
+ public V getValue() {
return entry.getValue().get(columnKey);
}
- @Override public V setValue(V value) {
+
+ @Override
+ public V setValue(V value) {
return entry.getValue().put(columnKey, checkNotNull(value));
}
- };
+ }
+ return new EntryImpl();
}
}
return endOfData();
}
}
- @Override Set<R> createKeySet() {
+ @Override
+ Set<R> createKeySet() {
return new KeySet();
}
+ @WeakOuter
private class KeySet extends Maps.KeySet<R, V> {
KeySet() {
super(Column.this);
}
- @Override public boolean contains(Object obj) {
+ @Override
+ public boolean contains(Object obj) {
return StandardTable.this.contains(obj, columnKey);
}
- @Override public boolean remove(Object obj) {
+ @Override
+ public boolean remove(Object obj) {
return StandardTable.this.remove(obj, columnKey) != null;
}
- @Override public boolean retainAll(final Collection<?> c) {
+ @Override
+ public boolean retainAll(final Collection<?> c) {
return removeFromColumnIf(Maps.<R>keyPredicateOnEntries(not(in(c))));
}
}
@@ -539,26 +566,31 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return new Values();
}
+ @WeakOuter
private class Values extends Maps.Values<R, V> {
Values() {
super(Column.this);
}
- @Override public boolean remove(Object obj) {
+ @Override
+ public boolean remove(Object obj) {
return obj != null && removeFromColumnIf(Maps.<V>valuePredicateOnEntries(equalTo(obj)));
}
- @Override public boolean removeAll(final Collection<?> c) {
+ @Override
+ public boolean removeAll(final Collection<?> c) {
return removeFromColumnIf(Maps.<V>valuePredicateOnEntries(in(c)));
}
- @Override public boolean retainAll(final Collection<?> c) {
+ @Override
+ public boolean retainAll(final Collection<?> c) {
return removeFromColumnIf(Maps.<V>valuePredicateOnEntries(not(in(c))));
}
}
}
- @Override public Set<R> rowKeySet() {
+ @Override
+ public Set<R> rowKeySet() {
return rowMap().keySet();
}
@@ -579,16 +611,20 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return (result == null) ? columnKeySet = new ColumnKeySet() : result;
}
+ @WeakOuter
private class ColumnKeySet extends TableSet<C> {
- @Override public Iterator<C> iterator() {
+ @Override
+ public Iterator<C> iterator() {
return createColumnKeyIterator();
}
- @Override public int size() {
+ @Override
+ public int size() {
return Iterators.size(iterator());
}
- @Override public boolean remove(Object obj) {
+ @Override
+ public boolean remove(Object obj) {
if (obj == null) {
return false;
}
@@ -606,7 +642,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return changed;
}
- @Override public boolean removeAll(Collection<?> c) {
+ @Override
+ public boolean removeAll(Collection<?> c) {
checkNotNull(c);
boolean changed = false;
Iterator<Map<C, V>> iterator = backingMap.values().iterator();
@@ -624,7 +661,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return changed;
}
- @Override public boolean retainAll(Collection<?> c) {
+ @Override
+ public boolean retainAll(Collection<?> c) {
checkNotNull(c);
boolean changed = false;
Iterator<Map<C, V>> iterator = backingMap.values().iterator();
@@ -640,7 +678,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return changed;
}
- @Override public boolean contains(Object obj) {
+ @Override
+ public boolean contains(Object obj) {
return containsColumn(obj);
}
}
@@ -660,7 +699,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
final Iterator<Map<C, V>> mapIterator = backingMap.values().iterator();
Iterator<Entry<C, V>> entryIterator = Iterators.emptyIterator();
- @Override protected C computeNext() {
+ @Override
+ protected C computeNext() {
while (true) {
if (entryIterator.hasNext()) {
Entry<C, V> entry = entryIterator.next();
@@ -683,13 +723,15 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
* <p>The collection's iterator traverses the values for the first row,
* the values for the second row, and so on.
*/
- @Override public Collection<V> values() {
+ @Override
+ public Collection<V> values() {
return super.values();
}
private transient Map<R, Map<C, V>> rowMap;
- @Override public Map<R, Map<C, V>> rowMap() {
+ @Override
+ public Map<R, Map<C, V>> rowMap() {
Map<R, Map<C, V>> result = rowMap;
return (result == null) ? rowMap = createRowMap() : result;
}
@@ -698,40 +740,51 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return new RowMap();
}
- class RowMap extends ImprovedAbstractMap<R, Map<C, V>> {
- @Override public boolean containsKey(Object key) {
+ @WeakOuter
+ class RowMap extends ViewCachingAbstractMap<R, Map<C, V>> {
+ @Override
+ public boolean containsKey(Object key) {
return containsRow(key);
}
// performing cast only when key is in backing map and has the correct type
@SuppressWarnings("unchecked")
- @Override public Map<C, V> get(Object key) {
+ @Override
+ public Map<C, V> get(Object key) {
return containsRow(key) ? row((R) key) : null;
}
- @Override public Map<C, V> remove(Object key) {
+ @Override
+ public Map<C, V> remove(Object key) {
return (key == null) ? null : backingMap.remove(key);
}
- @Override protected Set<Entry<R, Map<C, V>>> createEntrySet() {
+ @Override
+ protected Set<Entry<R, Map<C, V>>> createEntrySet() {
return new EntrySet();
}
+ @WeakOuter
class EntrySet extends TableSet<Entry<R, Map<C, V>>> {
- @Override public Iterator<Entry<R, Map<C, V>>> iterator() {
- return Maps.asMapEntryIterator(backingMap.keySet(), new Function<R, Map<C, V>>() {
- @Override
- public Map<C, V> apply(R rowKey) {
- return row(rowKey);
- }
- });
+ @Override
+ public Iterator<Entry<R, Map<C, V>>> iterator() {
+ return Maps.asMapEntryIterator(
+ backingMap.keySet(),
+ new Function<R, Map<C, V>>() {
+ @Override
+ public Map<C, V> apply(R rowKey) {
+ return row(rowKey);
+ }
+ });
}
- @Override public int size() {
+ @Override
+ public int size() {
return backingMap.size();
}
- @Override public boolean contains(Object obj) {
+ @Override
+ public boolean contains(Object obj) {
if (obj instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) obj;
return entry.getKey() != null
@@ -741,7 +794,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return false;
}
- @Override public boolean remove(Object obj) {
+ @Override
+ public boolean remove(Object obj) {
if (obj instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) obj;
return entry.getKey() != null
@@ -755,54 +809,68 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
private transient ColumnMap columnMap;
- @Override public Map<C, Map<R, V>> columnMap() {
+ @Override
+ public Map<C, Map<R, V>> columnMap() {
ColumnMap result = columnMap;
return (result == null) ? columnMap = new ColumnMap() : result;
}
- private class ColumnMap extends ImprovedAbstractMap<C, Map<R, V>> {
+ @WeakOuter
+ private class ColumnMap extends ViewCachingAbstractMap<C, Map<R, V>> {
// The cast to C occurs only when the key is in the map, implying that it
// has the correct type.
@SuppressWarnings("unchecked")
- @Override public Map<R, V> get(Object key) {
+ @Override
+ public Map<R, V> get(Object key) {
return containsColumn(key) ? column((C) key) : null;
}
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return containsColumn(key);
}
- @Override public Map<R, V> remove(Object key) {
+ @Override
+ public Map<R, V> remove(Object key) {
return containsColumn(key) ? removeColumn(key) : null;
}
- @Override public Set<Entry<C, Map<R, V>>> createEntrySet() {
+ @Override
+ public Set<Entry<C, Map<R, V>>> createEntrySet() {
return new ColumnMapEntrySet();
}
- @Override public Set<C> keySet() {
+ @Override
+ public Set<C> keySet() {
return columnKeySet();
}
- @Override Collection<Map<R, V>> createValues() {
+ @Override
+ Collection<Map<R, V>> createValues() {
return new ColumnMapValues();
}
+ @WeakOuter
class ColumnMapEntrySet extends TableSet<Entry<C, Map<R, V>>> {
- @Override public Iterator<Entry<C, Map<R, V>>> iterator() {
- return Maps.asMapEntryIterator(columnKeySet(), new Function<C, Map<R, V>>() {
- @Override
- public Map<R, V> apply(C columnKey) {
- return column(columnKey);
- }
- });
+ @Override
+ public Iterator<Entry<C, Map<R, V>>> iterator() {
+ return Maps.asMapEntryIterator(
+ columnKeySet(),
+ new Function<C, Map<R, V>>() {
+ @Override
+ public Map<R, V> apply(C columnKey) {
+ return column(columnKey);
+ }
+ });
}
- @Override public int size() {
+ @Override
+ public int size() {
return columnKeySet().size();
}
- @Override public boolean contains(Object obj) {
+ @Override
+ public boolean contains(Object obj) {
if (obj instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) obj;
if (containsColumn(entry.getKey())) {
@@ -816,7 +884,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return false;
}
- @Override public boolean remove(Object obj) {
+ @Override
+ public boolean remove(Object obj) {
if (contains(obj)) {
Entry<?, ?> entry = (Entry<?, ?>) obj;
removeColumn(entry.getKey());
@@ -825,7 +894,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return false;
}
- @Override public boolean removeAll(Collection<?> c) {
+ @Override
+ public boolean removeAll(Collection<?> c) {
/*
* We can't inherit the normal implementation (which calls
* Sets.removeAllImpl(Set, *Collection*) because, under some
@@ -836,7 +906,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return Sets.removeAllImpl(this, c.iterator());
}
- @Override public boolean retainAll(Collection<?> c) {
+ @Override
+ public boolean retainAll(Collection<?> c) {
checkNotNull(c);
boolean changed = false;
for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
@@ -849,12 +920,14 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
}
}
+ @WeakOuter
private class ColumnMapValues extends Maps.Values<C, Map<R, V>> {
ColumnMapValues() {
super(ColumnMap.this);
}
- @Override public boolean remove(Object obj) {
+ @Override
+ public boolean remove(Object obj) {
for (Entry<C, Map<R, V>> entry : ColumnMap.this.entrySet()) {
if (entry.getValue().equals(obj)) {
removeColumn(entry.getKey());
@@ -864,7 +937,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return false;
}
- @Override public boolean removeAll(Collection<?> c) {
+ @Override
+ public boolean removeAll(Collection<?> c) {
checkNotNull(c);
boolean changed = false;
for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
@@ -876,7 +950,8 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa
return changed;
}
- @Override public boolean retainAll(Collection<?> c) {
+ @Override
+ public boolean retainAll(Collection<?> c) {
checkNotNull(c);
boolean changed = false;
for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
diff --git a/guava/src/com/google/common/collect/Synchronized.java b/guava/src/com/google/common/collect/Synchronized.java
index f8633bd..29c43ef 100644
--- a/guava/src/com/google/common/collect/Synchronized.java
+++ b/guava/src/com/google/common/collect/Synchronized.java
@@ -75,7 +75,8 @@ final class Synchronized {
// No equals and hashCode; see ForwardingObject for details.
- @Override public String toString() {
+ @Override
+ public String toString() {
synchronized (mutex) {
return delegate.toString();
}
@@ -97,20 +98,19 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- private static <E> Collection<E> collection(
- Collection<E> collection, @Nullable Object mutex) {
+ private static <E> Collection<E> collection(Collection<E> collection, @Nullable Object mutex) {
return new SynchronizedCollection<E>(collection, mutex);
}
- @VisibleForTesting static class SynchronizedCollection<E>
- extends SynchronizedObject implements Collection<E> {
- private SynchronizedCollection(
- Collection<E> delegate, @Nullable Object mutex) {
+ @VisibleForTesting
+ static class SynchronizedCollection<E> extends SynchronizedObject implements Collection<E> {
+ private SynchronizedCollection(Collection<E> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
@SuppressWarnings("unchecked")
- @Override Collection<E> delegate() {
+ @Override
+ Collection<E> delegate() {
return (Collection<E>) super.delegate();
}
@@ -206,22 +206,24 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- @VisibleForTesting static <E> Set<E> set(Set<E> set, @Nullable Object mutex) {
+ @VisibleForTesting
+ static <E> Set<E> set(Set<E> set, @Nullable Object mutex) {
return new SynchronizedSet<E>(set, mutex);
}
- static class SynchronizedSet<E>
- extends SynchronizedCollection<E> implements Set<E> {
+ static class SynchronizedSet<E> extends SynchronizedCollection<E> implements Set<E> {
SynchronizedSet(Set<E> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override Set<E> delegate() {
+ @Override
+ Set<E> delegate() {
return (Set<E>) super.delegate();
}
- @Override public boolean equals(Object o) {
+ @Override
+ public boolean equals(Object o) {
if (o == this) {
return true;
}
@@ -230,7 +232,8 @@ final class Synchronized {
}
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
synchronized (mutex) {
return delegate().hashCode();
}
@@ -239,18 +242,17 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- private static <E> SortedSet<E> sortedSet(
- SortedSet<E> set, @Nullable Object mutex) {
+ private static <E> SortedSet<E> sortedSet(SortedSet<E> set, @Nullable Object mutex) {
return new SynchronizedSortedSet<E>(set, mutex);
}
- static class SynchronizedSortedSet<E> extends SynchronizedSet<E>
- implements SortedSet<E> {
+ static class SynchronizedSortedSet<E> extends SynchronizedSet<E> implements SortedSet<E> {
SynchronizedSortedSet(SortedSet<E> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override SortedSet<E> delegate() {
+ @Override
+ SortedSet<E> delegate() {
return (SortedSet<E>) super.delegate();
}
@@ -305,13 +307,13 @@ final class Synchronized {
: new SynchronizedList<E>(list, mutex);
}
- private static class SynchronizedList<E> extends SynchronizedCollection<E>
- implements List<E> {
+ private static class SynchronizedList<E> extends SynchronizedCollection<E> implements List<E> {
SynchronizedList(List<E> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override List<E> delegate() {
+ @Override
+ List<E> delegate() {
return (List<E>) super.delegate();
}
@@ -381,7 +383,8 @@ final class Synchronized {
}
}
- @Override public boolean equals(Object o) {
+ @Override
+ public boolean equals(Object o) {
if (o == this) {
return true;
}
@@ -390,7 +393,8 @@ final class Synchronized {
}
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
synchronized (mutex) {
return delegate().hashCode();
}
@@ -399,18 +403,17 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- private static class SynchronizedRandomAccessList<E>
- extends SynchronizedList<E> implements RandomAccess {
+ private static class SynchronizedRandomAccessList<E> extends SynchronizedList<E>
+ implements RandomAccess {
SynchronizedRandomAccessList(List<E> list, @Nullable Object mutex) {
super(list, mutex);
}
+
private static final long serialVersionUID = 0;
}
- static <E> Multiset<E> multiset(
- Multiset<E> multiset, @Nullable Object mutex) {
- if (multiset instanceof SynchronizedMultiset ||
- multiset instanceof ImmutableMultiset) {
+ static <E> Multiset<E> multiset(Multiset<E> multiset, @Nullable Object mutex) {
+ if (multiset instanceof SynchronizedMultiset || multiset instanceof ImmutableMultiset) {
return multiset;
}
return new SynchronizedMultiset<E>(multiset, mutex);
@@ -425,7 +428,8 @@ final class Synchronized {
super(delegate, mutex);
}
- @Override Multiset<E> delegate() {
+ @Override
+ Multiset<E> delegate() {
return (Multiset<E>) super.delegate();
}
@@ -484,7 +488,8 @@ final class Synchronized {
}
}
- @Override public boolean equals(Object o) {
+ @Override
+ public boolean equals(Object o) {
if (o == this) {
return true;
}
@@ -493,7 +498,8 @@ final class Synchronized {
}
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
synchronized (mutex) {
return delegate().hashCode();
}
@@ -502,10 +508,8 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- static <K, V> Multimap<K, V> multimap(
- Multimap<K, V> multimap, @Nullable Object mutex) {
- if (multimap instanceof SynchronizedMultimap ||
- multimap instanceof ImmutableMultimap) {
+ static <K, V> Multimap<K, V> multimap(Multimap<K, V> multimap, @Nullable Object mutex) {
+ if (multimap instanceof SynchronizedMultimap || multimap instanceof ImmutableMultimap) {
return multimap;
}
return new SynchronizedMultimap<K, V>(multimap, mutex);
@@ -520,7 +524,8 @@ final class Synchronized {
transient Multiset<K> keys;
@SuppressWarnings("unchecked")
- @Override Multimap<K, V> delegate() {
+ @Override
+ Multimap<K, V> delegate() {
return (Multimap<K, V>) super.delegate();
}
@@ -669,7 +674,8 @@ final class Synchronized {
}
}
- @Override public boolean equals(Object o) {
+ @Override
+ public boolean equals(Object o) {
if (o == this) {
return true;
}
@@ -678,7 +684,8 @@ final class Synchronized {
}
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
synchronized (mutex) {
return delegate().hashCode();
}
@@ -689,78 +696,90 @@ final class Synchronized {
static <K, V> ListMultimap<K, V> listMultimap(
ListMultimap<K, V> multimap, @Nullable Object mutex) {
- if (multimap instanceof SynchronizedListMultimap ||
- multimap instanceof ImmutableListMultimap) {
+ if (multimap instanceof SynchronizedListMultimap || multimap instanceof ImmutableListMultimap) {
return multimap;
}
return new SynchronizedListMultimap<K, V>(multimap, mutex);
}
- private static class SynchronizedListMultimap<K, V>
- extends SynchronizedMultimap<K, V> implements ListMultimap<K, V> {
- SynchronizedListMultimap(
- ListMultimap<K, V> delegate, @Nullable Object mutex) {
+ private static class SynchronizedListMultimap<K, V> extends SynchronizedMultimap<K, V>
+ implements ListMultimap<K, V> {
+ SynchronizedListMultimap(ListMultimap<K, V> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override ListMultimap<K, V> delegate() {
+
+ @Override
+ ListMultimap<K, V> delegate() {
return (ListMultimap<K, V>) super.delegate();
}
- @Override public List<V> get(K key) {
+
+ @Override
+ public List<V> get(K key) {
synchronized (mutex) {
return list(delegate().get(key), mutex);
}
}
- @Override public List<V> removeAll(Object key) {
+
+ @Override
+ public List<V> removeAll(Object key) {
synchronized (mutex) {
return delegate().removeAll(key); // copy not synchronized
}
}
- @Override public List<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public List<V> replaceValues(K key, Iterable<? extends V> values) {
synchronized (mutex) {
return delegate().replaceValues(key, values); // copy not synchronized
}
}
+
private static final long serialVersionUID = 0;
}
- static <K, V> SetMultimap<K, V> setMultimap(
- SetMultimap<K, V> multimap, @Nullable Object mutex) {
- if (multimap instanceof SynchronizedSetMultimap ||
- multimap instanceof ImmutableSetMultimap) {
+ static <K, V> SetMultimap<K, V> setMultimap(SetMultimap<K, V> multimap, @Nullable Object mutex) {
+ if (multimap instanceof SynchronizedSetMultimap || multimap instanceof ImmutableSetMultimap) {
return multimap;
}
return new SynchronizedSetMultimap<K, V>(multimap, mutex);
}
- private static class SynchronizedSetMultimap<K, V>
- extends SynchronizedMultimap<K, V> implements SetMultimap<K, V> {
+ private static class SynchronizedSetMultimap<K, V> extends SynchronizedMultimap<K, V>
+ implements SetMultimap<K, V> {
transient Set<Map.Entry<K, V>> entrySet;
- SynchronizedSetMultimap(
- SetMultimap<K, V> delegate, @Nullable Object mutex) {
+ SynchronizedSetMultimap(SetMultimap<K, V> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override SetMultimap<K, V> delegate() {
+
+ @Override
+ SetMultimap<K, V> delegate() {
return (SetMultimap<K, V>) super.delegate();
}
- @Override public Set<V> get(K key) {
+
+ @Override
+ public Set<V> get(K key) {
synchronized (mutex) {
return set(delegate().get(key), mutex);
}
}
- @Override public Set<V> removeAll(Object key) {
+
+ @Override
+ public Set<V> removeAll(Object key) {
synchronized (mutex) {
return delegate().removeAll(key); // copy not synchronized
}
}
- @Override public Set<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public Set<V> replaceValues(K key, Iterable<? extends V> values) {
synchronized (mutex) {
return delegate().replaceValues(key, values); // copy not synchronized
}
}
- @Override public Set<Map.Entry<K, V>> entries() {
+
+ @Override
+ public Set<Map.Entry<K, V>> entries() {
synchronized (mutex) {
if (entrySet == null) {
entrySet = set(delegate().entries(), mutex);
@@ -768,6 +787,7 @@ final class Synchronized {
return entrySet;
}
}
+
private static final long serialVersionUID = 0;
}
@@ -779,37 +799,45 @@ final class Synchronized {
return new SynchronizedSortedSetMultimap<K, V>(multimap, mutex);
}
- private static class SynchronizedSortedSetMultimap<K, V>
- extends SynchronizedSetMultimap<K, V> implements SortedSetMultimap<K, V> {
- SynchronizedSortedSetMultimap(
- SortedSetMultimap<K, V> delegate, @Nullable Object mutex) {
+ private static class SynchronizedSortedSetMultimap<K, V> extends SynchronizedSetMultimap<K, V>
+ implements SortedSetMultimap<K, V> {
+ SynchronizedSortedSetMultimap(SortedSetMultimap<K, V> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override SortedSetMultimap<K, V> delegate() {
+
+ @Override
+ SortedSetMultimap<K, V> delegate() {
return (SortedSetMultimap<K, V>) super.delegate();
}
- @Override public SortedSet<V> get(K key) {
+
+ @Override
+ public SortedSet<V> get(K key) {
synchronized (mutex) {
return sortedSet(delegate().get(key), mutex);
}
}
- @Override public SortedSet<V> removeAll(Object key) {
+
+ @Override
+ public SortedSet<V> removeAll(Object key) {
synchronized (mutex) {
return delegate().removeAll(key); // copy not synchronized
}
}
- @Override public SortedSet<V> replaceValues(
- K key, Iterable<? extends V> values) {
+
+ @Override
+ public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
synchronized (mutex) {
return delegate().replaceValues(key, values); // copy not synchronized
}
}
+
@Override
public Comparator<? super V> valueComparator() {
synchronized (mutex) {
return delegate().valueComparator();
}
}
+
private static final long serialVersionUID = 0;
}
@@ -827,8 +855,7 @@ final class Synchronized {
return collection(collection, mutex);
}
- private static <E> Set<E> typePreservingSet(
- Set<E> set, @Nullable Object mutex) {
+ private static <E> Set<E> typePreservingSet(Set<E> set, @Nullable Object mutex) {
if (set instanceof SortedSet) {
return sortedSet((SortedSet<E>) set, mutex);
} else {
@@ -838,26 +865,25 @@ final class Synchronized {
private static class SynchronizedAsMapEntries<K, V>
extends SynchronizedSet<Map.Entry<K, Collection<V>>> {
- SynchronizedAsMapEntries(
- Set<Map.Entry<K, Collection<V>>> delegate, @Nullable Object mutex) {
+ SynchronizedAsMapEntries(Set<Map.Entry<K, Collection<V>>> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override public Iterator<Map.Entry<K, Collection<V>>> iterator() {
+ @Override
+ public Iterator<Map.Entry<K, Collection<V>>> iterator() {
// Must be manually synchronized.
- final Iterator<Map.Entry<K, Collection<V>>> iterator = super.iterator();
- return new ForwardingIterator<Map.Entry<K, Collection<V>>>() {
- @Override protected Iterator<Map.Entry<K, Collection<V>>> delegate() {
- return iterator;
- }
-
- @Override public Map.Entry<K, Collection<V>> next() {
- final Map.Entry<K, Collection<V>> entry = super.next();
+ return new TransformedIterator<Map.Entry<K, Collection<V>>, Map.Entry<K, Collection<V>>>(
+ super.iterator()) {
+ @Override
+ Map.Entry<K, Collection<V>> transform(final Map.Entry<K, Collection<V>> entry) {
return new ForwardingMapEntry<K, Collection<V>>() {
- @Override protected Map.Entry<K, Collection<V>> delegate() {
+ @Override
+ protected Map.Entry<K, Collection<V>> delegate() {
return entry;
}
- @Override public Collection<V> getValue() {
+
+ @Override
+ public Collection<V> getValue() {
return typePreservingCollection(entry.getValue(), mutex);
}
};
@@ -867,27 +893,36 @@ final class Synchronized {
// See Collections.CheckedMap.CheckedEntrySet for details on attacks.
- @Override public Object[] toArray() {
+ @Override
+ public Object[] toArray() {
synchronized (mutex) {
return ObjectArrays.toArrayImpl(delegate());
}
}
- @Override public <T> T[] toArray(T[] array) {
+
+ @Override
+ public <T> T[] toArray(T[] array) {
synchronized (mutex) {
return ObjectArrays.toArrayImpl(delegate(), array);
}
}
- @Override public boolean contains(Object o) {
+
+ @Override
+ public boolean contains(Object o) {
synchronized (mutex) {
return Maps.containsEntryImpl(delegate(), o);
}
}
- @Override public boolean containsAll(Collection<?> c) {
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
synchronized (mutex) {
return Collections2.containsAllImpl(delegate(), c);
}
}
- @Override public boolean equals(Object o) {
+
+ @Override
+ public boolean equals(Object o) {
if (o == this) {
return true;
}
@@ -895,17 +930,23 @@ final class Synchronized {
return Sets.equalsImpl(delegate(), o);
}
}
- @Override public boolean remove(Object o) {
+
+ @Override
+ public boolean remove(Object o) {
synchronized (mutex) {
return Maps.removeEntryImpl(delegate(), o);
}
}
- @Override public boolean removeAll(Collection<?> c) {
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
synchronized (mutex) {
return Iterators.removeAll(delegate().iterator(), c);
}
}
- @Override public boolean retainAll(Collection<?> c) {
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
synchronized (mutex) {
return Iterators.retainAll(delegate().iterator(), c);
}
@@ -919,8 +960,7 @@ final class Synchronized {
return new SynchronizedMap<K, V>(map, mutex);
}
- private static class SynchronizedMap<K, V> extends SynchronizedObject
- implements Map<K, V> {
+ private static class SynchronizedMap<K, V> extends SynchronizedObject implements Map<K, V> {
transient Set<K> keySet;
transient Collection<V> values;
transient Set<Map.Entry<K, V>> entrySet;
@@ -930,7 +970,8 @@ final class Synchronized {
}
@SuppressWarnings("unchecked")
- @Override Map<K, V> delegate() {
+ @Override
+ Map<K, V> delegate() {
return (Map<K, V>) super.delegate();
}
@@ -1027,7 +1068,8 @@ final class Synchronized {
}
}
- @Override public boolean equals(Object o) {
+ @Override
+ public boolean equals(Object o) {
if (o == this) {
return true;
}
@@ -1036,7 +1078,8 @@ final class Synchronized {
}
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
synchronized (mutex) {
return delegate().hashCode();
}
@@ -1045,8 +1088,7 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- static <K, V> SortedMap<K, V> sortedMap(
- SortedMap<K, V> sortedMap, @Nullable Object mutex) {
+ static <K, V> SortedMap<K, V> sortedMap(SortedMap<K, V> sortedMap, @Nullable Object mutex) {
return new SynchronizedSortedMap<K, V>(sortedMap, mutex);
}
@@ -1057,41 +1099,48 @@ final class Synchronized {
super(delegate, mutex);
}
- @Override SortedMap<K, V> delegate() {
+ @Override
+ SortedMap<K, V> delegate() {
return (SortedMap<K, V>) super.delegate();
}
- @Override public Comparator<? super K> comparator() {
+ @Override
+ public Comparator<? super K> comparator() {
synchronized (mutex) {
return delegate().comparator();
}
}
- @Override public K firstKey() {
+ @Override
+ public K firstKey() {
synchronized (mutex) {
return delegate().firstKey();
}
}
- @Override public SortedMap<K, V> headMap(K toKey) {
+ @Override
+ public SortedMap<K, V> headMap(K toKey) {
synchronized (mutex) {
return sortedMap(delegate().headMap(toKey), mutex);
}
}
- @Override public K lastKey() {
+ @Override
+ public K lastKey() {
synchronized (mutex) {
return delegate().lastKey();
}
}
- @Override public SortedMap<K, V> subMap(K fromKey, K toKey) {
+ @Override
+ public SortedMap<K, V> subMap(K fromKey, K toKey) {
synchronized (mutex) {
return sortedMap(delegate().subMap(fromKey, toKey), mutex);
}
}
- @Override public SortedMap<K, V> tailMap(K fromKey) {
+ @Override
+ public SortedMap<K, V> tailMap(K fromKey) {
synchronized (mutex) {
return sortedMap(delegate().tailMap(fromKey), mutex);
}
@@ -1101,29 +1150,31 @@ final class Synchronized {
}
static <K, V> BiMap<K, V> biMap(BiMap<K, V> bimap, @Nullable Object mutex) {
- if (bimap instanceof SynchronizedBiMap ||
- bimap instanceof ImmutableBiMap) {
+ if (bimap instanceof SynchronizedBiMap || bimap instanceof ImmutableBiMap) {
return bimap;
}
return new SynchronizedBiMap<K, V>(bimap, mutex, null);
}
- @VisibleForTesting static class SynchronizedBiMap<K, V>
- extends SynchronizedMap<K, V> implements BiMap<K, V>, Serializable {
+ @VisibleForTesting
+ static class SynchronizedBiMap<K, V> extends SynchronizedMap<K, V>
+ implements BiMap<K, V>, Serializable {
private transient Set<V> valueSet;
private transient BiMap<V, K> inverse;
- private SynchronizedBiMap(BiMap<K, V> delegate, @Nullable Object mutex,
- @Nullable BiMap<V, K> inverse) {
+ private SynchronizedBiMap(
+ BiMap<K, V> delegate, @Nullable Object mutex, @Nullable BiMap<V, K> inverse) {
super(delegate, mutex);
this.inverse = inverse;
}
- @Override BiMap<K, V> delegate() {
+ @Override
+ BiMap<K, V> delegate() {
return (BiMap<K, V>) super.delegate();
}
- @Override public Set<V> values() {
+ @Override
+ public Set<V> values() {
synchronized (mutex) {
if (valueSet == null) {
valueSet = set(delegate().values(), mutex);
@@ -1143,8 +1194,7 @@ final class Synchronized {
public BiMap<V, K> inverse() {
synchronized (mutex) {
if (inverse == null) {
- inverse
- = new SynchronizedBiMap<V, K>(delegate().inverse(), mutex, this);
+ inverse = new SynchronizedBiMap<V, K>(delegate().inverse(), mutex, this);
}
return inverse;
}
@@ -1153,8 +1203,7 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- private static class SynchronizedAsMap<K, V>
- extends SynchronizedMap<K, Collection<V>> {
+ private static class SynchronizedAsMap<K, V> extends SynchronizedMap<K, Collection<V>> {
transient Set<Map.Entry<K, Collection<V>>> asMapEntrySet;
transient Collection<Collection<V>> asMapValues;
@@ -1162,35 +1211,36 @@ final class Synchronized {
super(delegate, mutex);
}
- @Override public Collection<V> get(Object key) {
+ @Override
+ public Collection<V> get(Object key) {
synchronized (mutex) {
Collection<V> collection = super.get(key);
- return (collection == null) ? null
- : typePreservingCollection(collection, mutex);
+ return (collection == null) ? null : typePreservingCollection(collection, mutex);
}
}
- @Override public Set<Map.Entry<K, Collection<V>>> entrySet() {
+ @Override
+ public Set<Map.Entry<K, Collection<V>>> entrySet() {
synchronized (mutex) {
if (asMapEntrySet == null) {
- asMapEntrySet = new SynchronizedAsMapEntries<K, V>(
- delegate().entrySet(), mutex);
+ asMapEntrySet = new SynchronizedAsMapEntries<K, V>(delegate().entrySet(), mutex);
}
return asMapEntrySet;
}
}
- @Override public Collection<Collection<V>> values() {
+ @Override
+ public Collection<Collection<V>> values() {
synchronized (mutex) {
if (asMapValues == null) {
- asMapValues
- = new SynchronizedAsMapValues<V>(delegate().values(), mutex);
+ asMapValues = new SynchronizedAsMapValues<V>(delegate().values(), mutex);
}
return asMapValues;
}
}
- @Override public boolean containsValue(Object o) {
+ @Override
+ public boolean containsValue(Object o) {
// values() and its contains() method are both synchronized.
return values().contains(o);
}
@@ -1198,22 +1248,18 @@ final class Synchronized {
private static final long serialVersionUID = 0;
}
- private static class SynchronizedAsMapValues<V>
- extends SynchronizedCollection<Collection<V>> {
- SynchronizedAsMapValues(
- Collection<Collection<V>> delegate, @Nullable Object mutex) {
+ private static class SynchronizedAsMapValues<V> extends SynchronizedCollection<Collection<V>> {
+ SynchronizedAsMapValues(Collection<Collection<V>> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override public Iterator<Collection<V>> iterator() {
+ @Override
+ public Iterator<Collection<V>> iterator() {
// Must be manually synchronized.
- final Iterator<Collection<V>> iterator = super.iterator();
- return new ForwardingIterator<Collection<V>>() {
- @Override protected Iterator<Collection<V>> delegate() {
- return iterator;
- }
- @Override public Collection<V> next() {
- return typePreservingCollection(super.next(), mutex);
+ return new TransformedIterator<Collection<V>, Collection<V>>(super.iterator()) {
+ @Override
+ Collection<V> transform(Collection<V> from) {
+ return typePreservingCollection(from, mutex);
}
};
}
@@ -1229,27 +1275,30 @@ final class Synchronized {
super(delegate, mutex);
}
- @Override NavigableSet<E> delegate() {
+ @Override
+ NavigableSet<E> delegate() {
return (NavigableSet<E>) super.delegate();
}
- @Override public E ceiling(E e) {
+ @Override
+ public E ceiling(E e) {
synchronized (mutex) {
return delegate().ceiling(e);
}
}
- @Override public Iterator<E> descendingIterator() {
+ @Override
+ public Iterator<E> descendingIterator() {
return delegate().descendingIterator(); // manually synchronized
}
transient NavigableSet<E> descendingSet;
- @Override public NavigableSet<E> descendingSet() {
+ @Override
+ public NavigableSet<E> descendingSet() {
synchronized (mutex) {
if (descendingSet == null) {
- NavigableSet<E> dS =
- Synchronized.navigableSet(delegate().descendingSet(), mutex);
+ NavigableSet<E> dS = Synchronized.navigableSet(delegate().descendingSet(), mutex);
descendingSet = dS;
return dS;
}
@@ -1257,67 +1306,76 @@ final class Synchronized {
}
}
- @Override public E floor(E e) {
+ @Override
+ public E floor(E e) {
synchronized (mutex) {
return delegate().floor(e);
}
}
- @Override public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+ @Override
+ public NavigableSet<E> headSet(E toElement, boolean inclusive) {
synchronized (mutex) {
- return Synchronized.navigableSet(
- delegate().headSet(toElement, inclusive), mutex);
+ return Synchronized.navigableSet(delegate().headSet(toElement, inclusive), mutex);
}
}
- @Override public E higher(E e) {
+ @Override
+ public E higher(E e) {
synchronized (mutex) {
return delegate().higher(e);
}
}
- @Override public E lower(E e) {
+ @Override
+ public E lower(E e) {
synchronized (mutex) {
return delegate().lower(e);
}
}
- @Override public E pollFirst() {
+ @Override
+ public E pollFirst() {
synchronized (mutex) {
return delegate().pollFirst();
}
}
- @Override public E pollLast() {
+ @Override
+ public E pollLast() {
synchronized (mutex) {
return delegate().pollLast();
}
}
- @Override public NavigableSet<E> subSet(E fromElement,
- boolean fromInclusive, E toElement, boolean toInclusive) {
+ @Override
+ public NavigableSet<E> subSet(
+ E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
synchronized (mutex) {
- return Synchronized.navigableSet(delegate().subSet(
- fromElement, fromInclusive, toElement, toInclusive), mutex);
+ return Synchronized.navigableSet(
+ delegate().subSet(fromElement, fromInclusive, toElement, toInclusive), mutex);
}
}
- @Override public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+ @Override
+ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
synchronized (mutex) {
- return Synchronized.navigableSet(
- delegate().tailSet(fromElement, inclusive), mutex);
+ return Synchronized.navigableSet(delegate().tailSet(fromElement, inclusive), mutex);
}
}
- @Override public SortedSet<E> headSet(E toElement) {
+ @Override
+ public SortedSet<E> headSet(E toElement) {
return headSet(toElement, false);
}
- @Override public SortedSet<E> subSet(E fromElement, E toElement) {
+ @Override
+ public SortedSet<E> subSet(E fromElement, E toElement) {
return subSet(fromElement, true, toElement, false);
}
- @Override public SortedSet<E> tailSet(E fromElement) {
+ @Override
+ public SortedSet<E> tailSet(E fromElement) {
return tailSet(fromElement, true);
}
@@ -1325,8 +1383,7 @@ final class Synchronized {
}
@GwtIncompatible("NavigableSet")
- static <E> NavigableSet<E> navigableSet(
- NavigableSet<E> navigableSet, @Nullable Object mutex) {
+ static <E> NavigableSet<E> navigableSet(NavigableSet<E> navigableSet, @Nullable Object mutex) {
return new SynchronizedNavigableSet<E>(navigableSet, mutex);
}
@@ -1336,8 +1393,7 @@ final class Synchronized {
}
@GwtIncompatible("NavigableMap")
- static <K, V> NavigableMap<K, V> navigableMap(
- NavigableMap<K, V> navigableMap) {
+ static <K, V> NavigableMap<K, V> navigableMap(NavigableMap<K, V> navigableMap) {
return navigableMap(navigableMap, null);
}
@@ -1348,25 +1404,28 @@ final class Synchronized {
}
@GwtIncompatible("NavigableMap")
- @VisibleForTesting static class SynchronizedNavigableMap<K, V>
- extends SynchronizedSortedMap<K, V> implements NavigableMap<K, V> {
+ @VisibleForTesting
+ static class SynchronizedNavigableMap<K, V> extends SynchronizedSortedMap<K, V>
+ implements NavigableMap<K, V> {
- SynchronizedNavigableMap(
- NavigableMap<K, V> delegate, @Nullable Object mutex) {
+ SynchronizedNavigableMap(NavigableMap<K, V> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override NavigableMap<K, V> delegate() {
+ @Override
+ NavigableMap<K, V> delegate() {
return (NavigableMap<K, V>) super.delegate();
}
- @Override public Entry<K, V> ceilingEntry(K key) {
+ @Override
+ public Entry<K, V> ceilingEntry(K key) {
synchronized (mutex) {
return nullableSynchronizedEntry(delegate().ceilingEntry(key), mutex);
}
}
- @Override public K ceilingKey(K key) {
+ @Override
+ public K ceilingKey(K key) {
synchronized (mutex) {
return delegate().ceilingKey(key);
}
@@ -1374,11 +1433,11 @@ final class Synchronized {
transient NavigableSet<K> descendingKeySet;
- @Override public NavigableSet<K> descendingKeySet() {
+ @Override
+ public NavigableSet<K> descendingKeySet() {
synchronized (mutex) {
if (descendingKeySet == null) {
- return descendingKeySet =
- Synchronized.navigableSet(delegate().descendingKeySet(), mutex);
+ return descendingKeySet = Synchronized.navigableSet(delegate().descendingKeySet(), mutex);
}
return descendingKeySet;
}
@@ -1386,124 +1445,137 @@ final class Synchronized {
transient NavigableMap<K, V> descendingMap;
- @Override public NavigableMap<K, V> descendingMap() {
+ @Override
+ public NavigableMap<K, V> descendingMap() {
synchronized (mutex) {
if (descendingMap == null) {
- return descendingMap =
- navigableMap(delegate().descendingMap(), mutex);
+ return descendingMap = navigableMap(delegate().descendingMap(), mutex);
}
return descendingMap;
}
}
- @Override public Entry<K, V> firstEntry() {
+ @Override
+ public Entry<K, V> firstEntry() {
synchronized (mutex) {
return nullableSynchronizedEntry(delegate().firstEntry(), mutex);
}
}
- @Override public Entry<K, V> floorEntry(K key) {
+ @Override
+ public Entry<K, V> floorEntry(K key) {
synchronized (mutex) {
return nullableSynchronizedEntry(delegate().floorEntry(key), mutex);
}
}
- @Override public K floorKey(K key) {
+ @Override
+ public K floorKey(K key) {
synchronized (mutex) {
return delegate().floorKey(key);
}
}
- @Override public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
+ @Override
+ public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
synchronized (mutex) {
- return navigableMap(
- delegate().headMap(toKey, inclusive), mutex);
+ return navigableMap(delegate().headMap(toKey, inclusive), mutex);
}
}
- @Override public Entry<K, V> higherEntry(K key) {
+ @Override
+ public Entry<K, V> higherEntry(K key) {
synchronized (mutex) {
return nullableSynchronizedEntry(delegate().higherEntry(key), mutex);
}
}
- @Override public K higherKey(K key) {
+ @Override
+ public K higherKey(K key) {
synchronized (mutex) {
return delegate().higherKey(key);
}
}
- @Override public Entry<K, V> lastEntry() {
+ @Override
+ public Entry<K, V> lastEntry() {
synchronized (mutex) {
return nullableSynchronizedEntry(delegate().lastEntry(), mutex);
}
}
- @Override public Entry<K, V> lowerEntry(K key) {
+ @Override
+ public Entry<K, V> lowerEntry(K key) {
synchronized (mutex) {
return nullableSynchronizedEntry(delegate().lowerEntry(key), mutex);
}
}
- @Override public K lowerKey(K key) {
+ @Override
+ public K lowerKey(K key) {
synchronized (mutex) {
return delegate().lowerKey(key);
}
}
- @Override public Set<K> keySet() {
+ @Override
+ public Set<K> keySet() {
return navigableKeySet();
}
transient NavigableSet<K> navigableKeySet;
- @Override public NavigableSet<K> navigableKeySet() {
+ @Override
+ public NavigableSet<K> navigableKeySet() {
synchronized (mutex) {
if (navigableKeySet == null) {
- return navigableKeySet =
- Synchronized.navigableSet(delegate().navigableKeySet(), mutex);
+ return navigableKeySet = Synchronized.navigableSet(delegate().navigableKeySet(), mutex);
}
return navigableKeySet;
}
}
- @Override public Entry<K, V> pollFirstEntry() {
+ @Override
+ public Entry<K, V> pollFirstEntry() {
synchronized (mutex) {
return nullableSynchronizedEntry(delegate().pollFirstEntry(), mutex);
}
}
- @Override public Entry<K, V> pollLastEntry() {
+ @Override
+ public Entry<K, V> pollLastEntry() {
synchronized (mutex) {
return nullableSynchronizedEntry(delegate().pollLastEntry(), mutex);
}
}
- @Override public NavigableMap<K, V> subMap(
+ @Override
+ public NavigableMap<K, V> subMap(
K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
synchronized (mutex) {
- return navigableMap(
- delegate().subMap(fromKey, fromInclusive, toKey, toInclusive),
- mutex);
+ return navigableMap(delegate().subMap(fromKey, fromInclusive, toKey, toInclusive), mutex);
}
}
- @Override public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
+ @Override
+ public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
synchronized (mutex) {
- return navigableMap(
- delegate().tailMap(fromKey, inclusive), mutex);
+ return navigableMap(delegate().tailMap(fromKey, inclusive), mutex);
}
}
- @Override public SortedMap<K, V> headMap(K toKey) {
+ @Override
+ public SortedMap<K, V> headMap(K toKey) {
return headMap(toKey, false);
}
- @Override public SortedMap<K, V> subMap(K fromKey, K toKey) {
+ @Override
+ public SortedMap<K, V> subMap(K fromKey, K toKey) {
return subMap(fromKey, true, toKey, false);
}
- @Override public SortedMap<K, V> tailMap(K fromKey) {
+ @Override
+ public SortedMap<K, V> tailMap(K fromKey) {
return tailMap(fromKey, true);
}
@@ -1520,43 +1592,48 @@ final class Synchronized {
}
@GwtIncompatible("works but is needed only for NavigableMap")
- private static class SynchronizedEntry<K, V> extends SynchronizedObject
- implements Entry<K, V> {
+ private static class SynchronizedEntry<K, V> extends SynchronizedObject implements Entry<K, V> {
SynchronizedEntry(Entry<K, V> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
@SuppressWarnings("unchecked") // guaranteed by the constructor
- @Override Entry<K, V> delegate() {
+ @Override
+ Entry<K, V> delegate() {
return (Entry<K, V>) super.delegate();
}
- @Override public boolean equals(Object obj) {
+ @Override
+ public boolean equals(Object obj) {
synchronized (mutex) {
return delegate().equals(obj);
}
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
synchronized (mutex) {
return delegate().hashCode();
}
}
- @Override public K getKey() {
+ @Override
+ public K getKey() {
synchronized (mutex) {
return delegate().getKey();
}
}
- @Override public V getValue() {
+ @Override
+ public V getValue() {
synchronized (mutex) {
return delegate().getValue();
}
}
- @Override public V setValue(V value) {
+ @Override
+ public V setValue(V value) {
synchronized (mutex) {
return delegate().setValue(value);
}
@@ -1566,19 +1643,17 @@ final class Synchronized {
}
static <E> Queue<E> queue(Queue<E> queue, @Nullable Object mutex) {
- return (queue instanceof SynchronizedQueue)
- ? queue
- : new SynchronizedQueue<E>(queue, mutex);
+ return (queue instanceof SynchronizedQueue) ? queue : new SynchronizedQueue<E>(queue, mutex);
}
- private static class SynchronizedQueue<E> extends SynchronizedCollection<E>
- implements Queue<E> {
+ private static class SynchronizedQueue<E> extends SynchronizedCollection<E> implements Queue<E> {
SynchronizedQueue(Queue<E> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override Queue<E> delegate() {
+ @Override
+ Queue<E> delegate() {
return (Queue<E>) super.delegate();
}
@@ -1626,14 +1701,14 @@ final class Synchronized {
}
@GwtIncompatible("Deque")
- private static final class SynchronizedDeque<E>
- extends SynchronizedQueue<E> implements Deque<E> {
+ private static final class SynchronizedDeque<E> extends SynchronizedQueue<E> implements Deque<E> {
SynchronizedDeque(Deque<E> delegate, @Nullable Object mutex) {
super(delegate, mutex);
}
- @Override Deque<E> delegate() {
+ @Override
+ Deque<E> delegate() {
return (Deque<E>) super.delegate();
}
diff --git a/guava/src/com/google/common/collect/Table.java b/guava/src/com/google/common/collect/Table.java
index c384bf8..b993fb7 100644
--- a/guava/src/com/google/common/collect/Table.java
+++ b/guava/src/com/google/common/collect/Table.java
@@ -43,9 +43,9 @@ import javax.annotation.Nullable;
* <p>All methods that modify the table are optional, and the views returned by
* the table may or may not be modifiable. When modification isn't supported,
* those methods will throw an {@link UnsupportedOperationException}.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#table">
* {@code Table}</a>.
*
* @author Jared Levy
@@ -140,6 +140,7 @@ public interface Table<R, C, V> {
* @return the value previously associated with the keys, or {@code null} if
* no mapping existed for the keys
*/
+ @Nullable
V put(R rowKey, C columnKey, V value);
/**
@@ -159,6 +160,7 @@ public interface Table<R, C, V> {
* @return the value previously associated with the keys, or {@code null} if
* no such value existed
*/
+ @Nullable
V remove(@Nullable Object rowKey, @Nullable Object columnKey);
// Views
@@ -265,16 +267,19 @@ public interface Table<R, C, V> {
/**
* Returns the row key of this cell.
*/
+ @Nullable
R getRowKey();
/**
* Returns the column key of this cell.
*/
+ @Nullable
C getColumnKey();
/**
* Returns the value of this cell.
*/
+ @Nullable
V getValue();
/**
diff --git a/guava/src/com/google/common/collect/Tables.java b/guava/src/com/google/common/collect/Tables.java
index db8cfcc..8f438a5 100644
--- a/guava/src/com/google/common/collect/Tables.java
+++ b/guava/src/com/google/common/collect/Tables.java
@@ -39,9 +39,9 @@ import javax.annotation.Nullable;
/**
* Provides static methods that involve a {@code Table}.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Tables">
+ * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#tables">
* {@code Tables}</a>.
*
* @author Jared Levy
@@ -67,14 +67,12 @@ public final class Tables {
return new ImmutableCell<R, C, V>(rowKey, columnKey, value);
}
- static final class ImmutableCell<R, C, V>
- extends AbstractCell<R, C, V> implements Serializable {
+ static final class ImmutableCell<R, C, V> extends AbstractCell<R, C, V> implements Serializable {
private final R rowKey;
private final C columnKey;
private final V value;
- ImmutableCell(
- @Nullable R rowKey, @Nullable C columnKey, @Nullable V value) {
+ ImmutableCell(@Nullable R rowKey, @Nullable C columnKey, @Nullable V value) {
this.rowKey = rowKey;
this.columnKey = columnKey;
this.value = value;
@@ -84,10 +82,12 @@ public final class Tables {
public R getRowKey() {
return rowKey;
}
+
@Override
public C getColumnKey() {
return columnKey;
}
+
@Override
public V getValue() {
return value;
@@ -100,7 +100,8 @@ public final class Tables {
// needed for serialization
AbstractCell() {}
- @Override public boolean equals(Object obj) {
+ @Override
+ public boolean equals(Object obj) {
if (obj == this) {
return true;
}
@@ -113,11 +114,13 @@ public final class Tables {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Objects.hashCode(getRowKey(), getColumnKey(), getValue());
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "(" + getRowKey() + "," + getColumnKey() + ")=" + getValue();
}
}
@@ -170,8 +173,7 @@ public final class Tables {
}
@Override
- public boolean contains(
- @Nullable Object rowKey, @Nullable Object columnKey) {
+ public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
return original.contains(columnKey, rowKey);
}
@@ -240,8 +242,7 @@ public final class Tables {
new Function<Cell<?, ?, ?>, Cell<?, ?, ?>>() {
@Override
public Cell<?, ?, ?> apply(Cell<?, ?, ?> cell) {
- return immutableCell(
- cell.getColumnKey(), cell.getRowKey(), cell.getValue());
+ return immutableCell(cell.getColumnKey(), cell.getRowKey(), cell.getValue());
}
};
@@ -334,64 +335,70 @@ public final class Tables {
return new TransformedTable<R, C, V1, V2>(fromTable, function);
}
- private static class TransformedTable<R, C, V1, V2>
- extends AbstractTable<R, C, V2> {
+ private static class TransformedTable<R, C, V1, V2> extends AbstractTable<R, C, V2> {
final Table<R, C, V1> fromTable;
final Function<? super V1, V2> function;
- TransformedTable(
- Table<R, C, V1> fromTable, Function<? super V1, V2> function) {
+ TransformedTable(Table<R, C, V1> fromTable, Function<? super V1, V2> function) {
this.fromTable = checkNotNull(fromTable);
this.function = checkNotNull(function);
}
- @Override public boolean contains(Object rowKey, Object columnKey) {
+ @Override
+ public boolean contains(Object rowKey, Object columnKey) {
return fromTable.contains(rowKey, columnKey);
}
- @Override public V2 get(Object rowKey, Object columnKey) {
+ @Override
+ public V2 get(Object rowKey, Object columnKey) {
// The function is passed a null input only when the table contains a null
// value.
- return contains(rowKey, columnKey)
- ? function.apply(fromTable.get(rowKey, columnKey)) : null;
+ return contains(rowKey, columnKey) ? function.apply(fromTable.get(rowKey, columnKey)) : null;
}
- @Override public int size() {
+ @Override
+ public int size() {
return fromTable.size();
}
- @Override public void clear() {
+ @Override
+ public void clear() {
fromTable.clear();
}
- @Override public V2 put(R rowKey, C columnKey, V2 value) {
+ @Override
+ public V2 put(R rowKey, C columnKey, V2 value) {
throw new UnsupportedOperationException();
}
- @Override public void putAll(
- Table<? extends R, ? extends C, ? extends V2> table) {
+ @Override
+ public void putAll(Table<? extends R, ? extends C, ? extends V2> table) {
throw new UnsupportedOperationException();
}
- @Override public V2 remove(Object rowKey, Object columnKey) {
+ @Override
+ public V2 remove(Object rowKey, Object columnKey) {
return contains(rowKey, columnKey)
- ? function.apply(fromTable.remove(rowKey, columnKey)) : null;
+ ? function.apply(fromTable.remove(rowKey, columnKey))
+ : null;
}
- @Override public Map<C, V2> row(R rowKey) {
+ @Override
+ public Map<C, V2> row(R rowKey) {
return Maps.transformValues(fromTable.row(rowKey), function);
}
- @Override public Map<R, V2> column(C columnKey) {
+ @Override
+ public Map<R, V2> column(C columnKey) {
return Maps.transformValues(fromTable.column(columnKey), function);
}
Function<Cell<R, C, V1>, Cell<R, C, V2>> cellFunction() {
return new Function<Cell<R, C, V1>, Cell<R, C, V2>>() {
- @Override public Cell<R, C, V2> apply(Cell<R, C, V1> cell) {
+ @Override
+ public Cell<R, C, V2> apply(Cell<R, C, V1> cell) {
return immutableCell(
- cell.getRowKey(), cell.getColumnKey(),
- function.apply(cell.getValue()));
+ cell.getRowKey(), cell.getColumnKey(), function.apply(cell.getValue()));
}
};
}
@@ -401,11 +408,13 @@ public final class Tables {
return Iterators.transform(fromTable.cellSet().iterator(), cellFunction());
}
- @Override public Set<R> rowKeySet() {
+ @Override
+ public Set<R> rowKeySet() {
return fromTable.rowKeySet();
}
- @Override public Set<C> columnKeySet() {
+ @Override
+ public Set<C> columnKeySet() {
return fromTable.columnKeySet();
}
@@ -414,37 +423,41 @@ public final class Tables {
return Collections2.transform(fromTable.values(), function);
}
- @Override public Map<R, Map<C, V2>> rowMap() {
+ @Override
+ public Map<R, Map<C, V2>> rowMap() {
Function<Map<C, V1>, Map<C, V2>> rowFunction =
new Function<Map<C, V1>, Map<C, V2>>() {
- @Override public Map<C, V2> apply(Map<C, V1> row) {
+ @Override
+ public Map<C, V2> apply(Map<C, V1> row) {
return Maps.transformValues(row, function);
}
};
return Maps.transformValues(fromTable.rowMap(), rowFunction);
}
- @Override public Map<C, Map<R, V2>> columnMap() {
+ @Override
+ public Map<C, Map<R, V2>> columnMap() {
Function<Map<R, V1>, Map<R, V2>> columnFunction =
new Function<Map<R, V1>, Map<R, V2>>() {
- @Override public Map<R, V2> apply(Map<R, V1> column) {
+ @Override
+ public Map<R, V2> apply(Map<R, V1> column) {
return Maps.transformValues(column, function);
}
};
return Maps.transformValues(fromTable.columnMap(), columnFunction);
}
}
-
+
/**
* Returns an unmodifiable view of the specified table. This method allows modules to provide
* users with "read-only" access to internal tables. Query operations on the returned table
* "read through" to the specified table, and attempts to modify the returned table, whether
* direct or via its collection views, result in an {@code UnsupportedOperationException}.
- *
+ *
* <p>The returned table will be serializable if the specified table is serializable.
*
* <p>Consider using an {@link ImmutableTable}, which is guaranteed never to change.
- *
+ *
* @param table
* the table for which an unmodifiable view is to be returned
* @return an unmodifiable view of the specified table
@@ -454,9 +467,9 @@ public final class Tables {
Table<? extends R, ? extends C, ? extends V> table) {
return new UnmodifiableTable<R, C, V>(table);
}
-
- private static class UnmodifiableTable<R, C, V>
- extends ForwardingTable<R, C, V> implements Serializable {
+
+ private static class UnmodifiableTable<R, C, V> extends ForwardingTable<R, C, V>
+ implements Serializable {
final Table<? extends R, ? extends C, ? extends V> delegate;
UnmodifiableTable(Table<? extends R, ? extends C, ? extends V> delegate) {
@@ -530,7 +543,7 @@ public final class Tables {
public Collection<V> values() {
return Collections.unmodifiableCollection(super.values());
}
-
+
private static final long serialVersionUID = 0;
}
@@ -539,9 +552,9 @@ public final class Tables {
* provide users with "read-only" access to internal tables. Query operations on the returned
* table "read through" to the specified table, and attemps to modify the returned table, whether
* direct or via its collection views, result in an {@code UnsupportedOperationException}.
- *
+ *
* <p>The returned table will be serializable if the specified table is serializable.
- *
+ *
* @param table the row-sorted table for which an unmodifiable view is to be returned
* @return an unmodifiable view of the specified table
* @since 11.0
@@ -556,7 +569,7 @@ public final class Tables {
*/
return new UnmodifiableRowSortedMap<R, C, V>(table);
}
-
+
static final class UnmodifiableRowSortedMap<R, C, V> extends UnmodifiableTable<R, C, V>
implements RowSortedTable<R, C, V> {
@@ -595,7 +608,7 @@ public final class Tables {
return Collections.unmodifiableMap(input);
}
};
-
+
static boolean equalsImpl(Table<?, ?, ?> table, @Nullable Object obj) {
if (obj == table) {
return true;
diff --git a/guava/src/com/google/common/collect/TreeBasedTable.java b/guava/src/com/google/common/collect/TreeBasedTable.java
index 29bf65a..10023d3 100644
--- a/guava/src/com/google/common/collect/TreeBasedTable.java
+++ b/guava/src/com/google/common/collect/TreeBasedTable.java
@@ -67,7 +67,7 @@ import javax.annotation.Nullable;
* must be synchronized externally.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#table">
* {@code Table}</a>.
*
* @author Jared Levy
@@ -79,16 +79,18 @@ import javax.annotation.Nullable;
public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
private final Comparator<? super C> columnComparator;
- private static class Factory<C, V>
- implements Supplier<TreeMap<C, V>>, Serializable {
+ private static class Factory<C, V> implements Supplier<TreeMap<C, V>>, Serializable {
final Comparator<? super C> comparator;
+
Factory(Comparator<? super C> comparator) {
this.comparator = comparator;
}
+
@Override
public TreeMap<C, V> get() {
return new TreeMap<C, V>(comparator);
}
+
private static final long serialVersionUID = 0;
}
@@ -101,10 +103,8 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
* and the same for {@code C}. That's necessary to support classes defined
* without generics.
*/
- public static <R extends Comparable, C extends Comparable, V>
- TreeBasedTable<R, C, V> create() {
- return new TreeBasedTable<R, C, V>(Ordering.natural(),
- Ordering.natural());
+ public static <R extends Comparable, C extends Comparable, V> TreeBasedTable<R, C, V> create() {
+ return new TreeBasedTable<R, C, V>(Ordering.natural(), Ordering.natural());
}
/**
@@ -115,8 +115,7 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
* @param columnComparator the comparator that orders the column keys
*/
public static <R, C, V> TreeBasedTable<R, C, V> create(
- Comparator<? super R> rowComparator,
- Comparator<? super C> columnComparator) {
+ Comparator<? super R> rowComparator, Comparator<? super C> columnComparator) {
checkNotNull(rowComparator);
checkNotNull(columnComparator);
return new TreeBasedTable<R, C, V>(rowComparator, columnComparator);
@@ -126,19 +125,15 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
* Creates a {@code TreeBasedTable} with the same mappings and sort order
* as the specified {@code TreeBasedTable}.
*/
- public static <R, C, V> TreeBasedTable<R, C, V> create(
- TreeBasedTable<R, C, ? extends V> table) {
- TreeBasedTable<R, C, V> result
- = new TreeBasedTable<R, C, V>(
- table.rowComparator(), table.columnComparator());
+ public static <R, C, V> TreeBasedTable<R, C, V> create(TreeBasedTable<R, C, ? extends V> table) {
+ TreeBasedTable<R, C, V> result =
+ new TreeBasedTable<R, C, V>(table.rowComparator(), table.columnComparator());
result.putAll(table);
return result;
}
- TreeBasedTable(Comparator<? super R> rowComparator,
- Comparator<? super C> columnComparator) {
- super(new TreeMap<R, Map<C, V>>(rowComparator),
- new Factory<C, V>(columnComparator));
+ TreeBasedTable(Comparator<? super R> rowComparator, Comparator<? super C> columnComparator) {
+ super(new TreeMap<R, Map<C, V>>(rowComparator), new Factory<C, V>(columnComparator));
this.columnComparator = columnComparator;
}
@@ -160,7 +155,7 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
return columnComparator;
}
- // TODO(user): make column return a SortedMap
+ // TODO(lowasser): make column return a SortedMap
/**
* {@inheritDoc}
@@ -169,7 +164,7 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
* row, this method returns a {@link SortedMap}, instead of the {@link Map}
* specified in the {@link Table} interface.
* @since 10.0
- * (<a href="http://code.google.com/p/guava-libraries/wiki/Compatibility"
+ * (<a href="https://github.com/google/guava/wiki/Compatibility"
* >mostly source-compatible</a> since 7.0)
*/
@Override
@@ -189,15 +184,17 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
super(rowKey);
this.lowerBound = lowerBound;
this.upperBound = upperBound;
- checkArgument(lowerBound == null || upperBound == null
- || compare(lowerBound, upperBound) <= 0);
+ checkArgument(
+ lowerBound == null || upperBound == null || compare(lowerBound, upperBound) <= 0);
}
- @Override public SortedSet<C> keySet() {
+ @Override
+ public SortedSet<C> keySet() {
return new Maps.SortedKeySet<C, V>(this);
}
- @Override public Comparator<? super C> comparator() {
+ @Override
+ public Comparator<? super C> comparator() {
return columnComparator();
}
@@ -209,27 +206,31 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
}
boolean rangeContains(@Nullable Object o) {
- return o != null && (lowerBound == null || compare(lowerBound, o) <= 0)
+ return o != null
+ && (lowerBound == null || compare(lowerBound, o) <= 0)
&& (upperBound == null || compare(upperBound, o) > 0);
}
- @Override public SortedMap<C, V> subMap(C fromKey, C toKey) {
- checkArgument(rangeContains(checkNotNull(fromKey))
- && rangeContains(checkNotNull(toKey)));
+ @Override
+ public SortedMap<C, V> subMap(C fromKey, C toKey) {
+ checkArgument(rangeContains(checkNotNull(fromKey)) && rangeContains(checkNotNull(toKey)));
return new TreeRow(rowKey, fromKey, toKey);
}
- @Override public SortedMap<C, V> headMap(C toKey) {
+ @Override
+ public SortedMap<C, V> headMap(C toKey) {
checkArgument(rangeContains(checkNotNull(toKey)));
return new TreeRow(rowKey, lowerBound, toKey);
}
- @Override public SortedMap<C, V> tailMap(C fromKey) {
+ @Override
+ public SortedMap<C, V> tailMap(C fromKey) {
checkArgument(rangeContains(checkNotNull(fromKey)));
return new TreeRow(rowKey, fromKey, upperBound);
}
- @Override public C firstKey() {
+ @Override
+ public C firstKey() {
SortedMap<C, V> backing = backingRowMap();
if (backing == null) {
throw new NoSuchElementException();
@@ -237,7 +238,8 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
return backingRowMap().firstKey();
}
- @Override public C lastKey() {
+ @Override
+ public C lastKey() {
SortedMap<C, V> backing = backingRowMap();
if (backing == null) {
throw new NoSuchElementException();
@@ -252,8 +254,7 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
* time we're queried.
*/
SortedMap<C, V> wholeRow() {
- if (wholeRow == null
- || (wholeRow.isEmpty() && backingMap.containsKey(rowKey))) {
+ if (wholeRow == null || (wholeRow.isEmpty() && backingMap.containsKey(rowKey))) {
wholeRow = (SortedMap<C, V>) backingMap.get(rowKey);
}
return wholeRow;
@@ -288,11 +289,13 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
}
}
- @Override public boolean containsKey(Object key) {
+ @Override
+ public boolean containsKey(Object key) {
return rangeContains(key) && super.containsKey(key);
}
- @Override public V put(C key, V value) {
+ @Override
+ public V put(C key, V value) {
checkArgument(rangeContains(checkNotNull(key)));
return super.put(key, value);
}
@@ -300,11 +303,13 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
// rowKeySet() and rowMap() are defined here so they appear in the Javadoc.
- @Override public SortedSet<R> rowKeySet() {
+ @Override
+ public SortedSet<R> rowKeySet() {
return super.rowKeySet();
}
- @Override public SortedMap<R, Map<C, V>> rowMap() {
+ @Override
+ public SortedMap<R, Map<C, V>> rowMap() {
return super.rowMap();
}
@@ -317,13 +322,16 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
final Comparator<? super C> comparator = columnComparator();
final Iterator<C> merged =
- Iterators.mergeSorted(Iterables.transform(backingMap.values(),
- new Function<Map<C, V>, Iterator<C>>() {
- @Override
- public Iterator<C> apply(Map<C, V> input) {
- return input.keySet().iterator();
- }
- }), comparator);
+ Iterators.mergeSorted(
+ Iterables.transform(
+ backingMap.values(),
+ new Function<Map<C, V>, Iterator<C>>() {
+ @Override
+ public Iterator<C> apply(Map<C, V> input) {
+ return input.keySet().iterator();
+ }
+ }),
+ comparator);
return new AbstractIterator<C>() {
C lastValue;
@@ -332,8 +340,7 @@ public class TreeBasedTable<R, C, V> extends StandardRowSortedTable<R, C, V> {
protected C computeNext() {
while (merged.hasNext()) {
C next = merged.next();
- boolean duplicate =
- lastValue != null && comparator.compare(next, lastValue) == 0;
+ boolean duplicate = lastValue != null && comparator.compare(next, lastValue) == 0;
// Keep looping till we find a non-duplicate value.
if (!duplicate) {
diff --git a/guava/src/com/google/common/collect/TreeMultimap.java b/guava/src/com/google/common/collect/TreeMultimap.java
index 433774d..e3586e0 100644
--- a/guava/src/com/google/common/collect/TreeMultimap.java
+++ b/guava/src/com/google/common/collect/TreeMultimap.java
@@ -68,12 +68,12 @@ import javax.annotation.Nullable;
* Multimaps#synchronizedSortedSetMultimap}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">
* {@code Multimap}</a>.
*
* @author Jared Levy
* @author Louis Wasserman
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(serializable = true, emulated = true)
public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V> {
@@ -84,8 +84,7 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
* Creates an empty {@code TreeMultimap} ordered by the natural ordering of
* its keys and values.
*/
- public static <K extends Comparable, V extends Comparable>
- TreeMultimap<K, V> create() {
+ public static <K extends Comparable, V extends Comparable> TreeMultimap<K, V> create() {
return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural());
}
@@ -98,10 +97,8 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
* @param valueComparator the comparator that determines the value ordering
*/
public static <K, V> TreeMultimap<K, V> create(
- Comparator<? super K> keyComparator,
- Comparator<? super V> valueComparator) {
- return new TreeMultimap<K, V>(checkNotNull(keyComparator),
- checkNotNull(valueComparator));
+ Comparator<? super K> keyComparator, Comparator<? super V> valueComparator) {
+ return new TreeMultimap<K, V>(checkNotNull(keyComparator), checkNotNull(valueComparator));
}
/**
@@ -110,20 +107,19 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
*
* @param multimap the multimap whose contents are copied to this multimap
*/
- public static <K extends Comparable, V extends Comparable>
- TreeMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
- return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural(),
- multimap);
+ public static <K extends Comparable, V extends Comparable> TreeMultimap<K, V> create(
+ Multimap<? extends K, ? extends V> multimap) {
+ return new TreeMultimap<K, V>(Ordering.natural(), Ordering.natural(), multimap);
}
- TreeMultimap(Comparator<? super K> keyComparator,
- Comparator<? super V> valueComparator) {
+ TreeMultimap(Comparator<? super K> keyComparator, Comparator<? super V> valueComparator) {
super(new TreeMap<K, Collection<V>>(keyComparator));
this.keyComparator = keyComparator;
this.valueComparator = valueComparator;
}
- private TreeMultimap(Comparator<? super K> keyComparator,
+ private TreeMultimap(
+ Comparator<? super K> keyComparator,
Comparator<? super V> valueComparator,
Multimap<? extends K, ? extends V> multimap) {
this(keyComparator, valueComparator);
@@ -138,7 +134,8 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
* @return a new {@code TreeSet} containing a collection of values for one
* key
*/
- @Override SortedSet<V> createCollection() {
+ @Override
+ SortedSet<V> createCollection() {
return new TreeSet<V>(valueComparator);
}
@@ -163,17 +160,17 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
}
/*
- * The following @GwtIncompatible methods override the methods in
+ * The following @GwtIncompatible methods override the methods in
* AbstractSortedKeySortedSetMultimap, so GWT will fall back to the ASKSSM implementations,
* which return SortedSets and SortedMaps.
*/
-
+
@Override
@GwtIncompatible("NavigableMap")
NavigableMap<K, Collection<V>> backingMap() {
return (NavigableMap<K, Collection<V>>) super.backingMap();
}
-
+
/**
* @since 14.0 (present with return type {@code SortedSet} since 2.0)
*/
@@ -201,11 +198,11 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
* <p>Because a {@code TreeMultimap} has unique sorted keys, this method
* returns a {@link NavigableSet}, instead of the {@link java.util.Set} specified
* in the {@link Multimap} interface.
- *
+ *
* @since 14.0 (present with return type {@code SortedSet} since 2.0)
*/
@Override
- @GwtIncompatible("NavigableSet")
+ @GwtIncompatible("NavigableSet")
public NavigableSet<K> keySet() {
return (NavigableSet<K>) super.keySet();
}
@@ -222,10 +219,10 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
* <p>Because a {@code TreeMultimap} has unique sorted keys, this method
* returns a {@link NavigableMap}, instead of the {@link java.util.Map} specified
* in the {@link Multimap} interface.
- *
+ *
* @since 14.0 (present with return type {@code SortedMap} since 2.0)
*/
- @Override
+ @Override
@GwtIncompatible("NavigableMap")
public NavigableMap<K, Collection<V>> asMap() {
return (NavigableMap<K, Collection<V>>) super.asMap();
@@ -252,8 +249,7 @@ public class TreeMultimap<K, V> extends AbstractSortedKeySortedSetMultimap<K, V>
@GwtIncompatible("java.io.ObjectInputStream")
@SuppressWarnings("unchecked") // reading data stored by writeObject
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
keyComparator = checkNotNull((Comparator<? super K>) stream.readObject());
valueComparator = checkNotNull((Comparator<? super V>) stream.readObject());
diff --git a/guava/src/com/google/common/collect/TreeMultiset.java b/guava/src/com/google/common/collect/TreeMultiset.java
index cd4c445..5d0fbb8 100644
--- a/guava/src/com/google/common/collect/TreeMultiset.java
+++ b/guava/src/com/google/common/collect/TreeMultiset.java
@@ -48,12 +48,12 @@ import javax.annotation.Nullable;
* {@link java.util.Collection} contract, which is specified in terms of {@link Object#equals}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">
* {@code Multiset}</a>.
*
* @author Louis Wasserman
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible(emulated = true)
public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements Serializable {
@@ -153,6 +153,7 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
return (root == null) ? 0 : root.distinctElements;
}
};
+
abstract int nodeAggregate(AvlNode<?> node);
abstract long treeAggregate(@Nullable AvlNode<?> root);
@@ -187,7 +188,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
throw new AssertionError();
}
} else {
- return aggr.treeAggregate(node.left) + aggr.nodeAggregate(node)
+ return aggr.treeAggregate(node.left)
+ + aggr.nodeAggregate(node)
+ aggregateBelowRange(aggr, node.right);
}
}
@@ -209,7 +211,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
throw new AssertionError();
}
} else {
- return aggr.treeAggregate(node.right) + aggr.nodeAggregate(node)
+ return aggr.treeAggregate(node.right)
+ + aggr.nodeAggregate(node)
+ aggregateAboveRange(aggr, node.left);
}
}
@@ -353,7 +356,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
/**
* Returns the first node in the tree that is in range.
*/
- @Nullable private AvlNode<E> firstNode() {
+ @Nullable
+ private AvlNode<E> firstNode() {
AvlNode<E> root = rootReference.get();
if (root == null) {
return null;
@@ -375,7 +379,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
return (node == header || !range.contains(node.getElement())) ? null : node;
}
- @Nullable private AvlNode<E> lastNode() {
+ @Nullable
+ private AvlNode<E> lastNode() {
AvlNode<E> root = rootReference.get();
if (root == null) {
return null;
@@ -483,18 +488,18 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
@Override
public SortedMultiset<E> headMultiset(@Nullable E upperBound, BoundType boundType) {
- return new TreeMultiset<E>(rootReference, range.intersect(GeneralRange.upTo(
- comparator(),
- upperBound,
- boundType)), header);
+ return new TreeMultiset<E>(
+ rootReference,
+ range.intersect(GeneralRange.upTo(comparator(), upperBound, boundType)),
+ header);
}
@Override
public SortedMultiset<E> tailMultiset(@Nullable E lowerBound, BoundType boundType) {
- return new TreeMultiset<E>(rootReference, range.intersect(GeneralRange.downTo(
- comparator(),
- lowerBound,
- boundType)), header);
+ return new TreeMultiset<E>(
+ rootReference,
+ range.intersect(GeneralRange.downTo(comparator(), lowerBound, boundType)),
+ header);
}
static int distinctElements(@Nullable AvlNode<?> node) {
@@ -504,7 +509,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
private static final class Reference<T> {
@Nullable private T value;
- @Nullable public T get() {
+ @Nullable
+ public T get() {
return value;
}
@@ -828,8 +834,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
}
private void recomputeMultiset() {
- this.distinctElements = 1 + TreeMultiset.distinctElements(left)
- + TreeMultiset.distinctElements(right);
+ this.distinctElements =
+ 1 + TreeMultiset.distinctElements(left) + TreeMultiset.distinctElements(right);
this.totalCount = elemCount + totalCount(left) + totalCount(right);
}
@@ -896,7 +902,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
return (node == null) ? 0 : node.height;
}
- @Nullable private AvlNode<E> ceiling(Comparator<? super E> comparator, E e) {
+ @Nullable
+ private AvlNode<E> ceiling(Comparator<? super E> comparator, E e) {
int cmp = comparator.compare(e, elem);
if (cmp < 0) {
return (left == null) ? this : MoreObjects.firstNonNull(left.ceiling(comparator, e), this);
@@ -907,7 +914,8 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
}
}
- @Nullable private AvlNode<E> floor(Comparator<? super E> comparator, E e) {
+ @Nullable
+ private AvlNode<E> floor(Comparator<? super E> comparator, E e) {
int cmp = comparator.compare(e, elem);
if (cmp > 0) {
return (right == null) ? this : MoreObjects.firstNonNull(right.floor(comparator, e), this);
@@ -968,17 +976,16 @@ public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements
// reading data stored by writeObject
Comparator<? super E> comparator = (Comparator<? super E>) stream.readObject();
Serialization.getFieldSetter(AbstractSortedMultiset.class, "comparator").set(this, comparator);
- Serialization.getFieldSetter(TreeMultiset.class, "range").set(
- this,
- GeneralRange.all(comparator));
- Serialization.getFieldSetter(TreeMultiset.class, "rootReference").set(
- this,
- new Reference<AvlNode<E>>());
+ Serialization.getFieldSetter(TreeMultiset.class, "range")
+ .set(this, GeneralRange.all(comparator));
+ Serialization.getFieldSetter(TreeMultiset.class, "rootReference")
+ .set(this, new Reference<AvlNode<E>>());
AvlNode<E> header = new AvlNode<E>(null, 1);
Serialization.getFieldSetter(TreeMultiset.class, "header").set(this, header);
successor(header, header);
Serialization.populateMultiset(this, stream);
}
- @GwtIncompatible("not needed in emulated source") private static final long serialVersionUID = 1;
+ @GwtIncompatible("not needed in emulated source")
+ private static final long serialVersionUID = 1;
}
diff --git a/guava/src/com/google/common/collect/TreeRangeMap.java b/guava/src/com/google/common/collect/TreeRangeMap.java
index 82c3206..3495707 100644
--- a/guava/src/com/google/common/collect/TreeRangeMap.java
+++ b/guava/src/com/google/common/collect/TreeRangeMap.java
@@ -26,9 +26,9 @@ import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.MoreObjects;
import com.google.common.base.Predicate;
+import com.google.common.collect.Maps.IteratorBasedAbstractMap;
import java.util.AbstractMap;
-import java.util.AbstractSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
@@ -150,8 +150,7 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
throw new NoSuchElementException();
}
return Range.create(
- firstEntry.getValue().getKey().lowerBound,
- lastEntry.getValue().getKey().upperBound);
+ firstEntry.getValue().getKey().lowerBound, lastEntry.getValue().getKey().upperBound);
}
private void putRangeMapEntry(Cut<K> lowerBound, Cut<K> upperBound, V value) {
@@ -178,11 +177,15 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
if (rangeMapEntry.getUpperBound().compareTo(rangeToRemove.upperBound) > 0) {
// we know ( [ ] ), so insert the range ] ) back into the map --
// it's being split apart
- putRangeMapEntry(rangeToRemove.upperBound, rangeMapEntry.getUpperBound(),
+ putRangeMapEntry(
+ rangeToRemove.upperBound,
+ rangeMapEntry.getUpperBound(),
mapEntryBelowToTruncate.getValue().getValue());
}
// overwrite mapEntryToTruncateBelow with a truncated range
- putRangeMapEntry(rangeMapEntry.getLowerBound(), rangeToRemove.lowerBound,
+ putRangeMapEntry(
+ rangeMapEntry.getLowerBound(),
+ rangeToRemove.lowerBound,
mapEntryBelowToTruncate.getValue().getValue());
}
}
@@ -195,7 +198,9 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
if (rangeMapEntry.getUpperBound().compareTo(rangeToRemove.upperBound) > 0) {
// we know ( ] ), and since we dealt with truncating below already,
// we know [ ( ] )
- putRangeMapEntry(rangeToRemove.upperBound, rangeMapEntry.getUpperBound(),
+ putRangeMapEntry(
+ rangeToRemove.upperBound,
+ rangeMapEntry.getUpperBound(),
mapEntryAboveToTruncate.getValue().getValue());
entriesByLowerBound.remove(rangeToRemove.lowerBound);
}
@@ -205,10 +210,22 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
@Override
public Map<Range<K>, V> asMapOfRanges() {
- return new AsMapOfRanges();
+ return new AsMapOfRanges(entriesByLowerBound.values());
}
- private final class AsMapOfRanges extends AbstractMap<Range<K>, V> {
+ @Override
+ public Map<Range<K>, V> asDescendingMapOfRanges() {
+ return new AsMapOfRanges(entriesByLowerBound.descendingMap().values());
+ }
+
+ private final class AsMapOfRanges extends IteratorBasedAbstractMap<Range<K>, V> {
+
+ final Iterable<Entry<Range<K>, V>> entryIterable;
+
+ @SuppressWarnings("unchecked") // it's safe to upcast iterables
+ AsMapOfRanges(Iterable<RangeMapEntry<K, V>> entryIterable) {
+ this.entryIterable = (Iterable) entryIterable;
+ }
@Override
public boolean containsKey(@Nullable Object key) {
@@ -228,23 +245,16 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
}
@Override
- public Set<Entry<Range<K>, V>> entrySet() {
- return new AbstractSet<Entry<Range<K>, V>>() {
-
- @SuppressWarnings("unchecked") // it's safe to upcast iterators
- @Override
- public Iterator<Entry<Range<K>, V>> iterator() {
- return (Iterator) entriesByLowerBound.values().iterator();
- }
+ public int size() {
+ return entriesByLowerBound.size();
+ }
- @Override
- public int size() {
- return entriesByLowerBound.size();
- }
- };
+ @Override
+ Iterator<Entry<Range<K>, V>> entryIterator() {
+ return entryIterable.iterator();
}
}
-
+
@Override
public RangeMap<K, V> subRangeMap(Range<K> subRange) {
if (subRange.equals(Range.all())) {
@@ -253,13 +263,13 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
return new SubRangeMap(subRange);
}
}
-
+
@SuppressWarnings("unchecked")
private RangeMap<K, V> emptySubRangeMap() {
return EMPTY_SUB_RANGE_MAP;
}
-
- private static final RangeMap EMPTY_SUB_RANGE_MAP =
+
+ private static final RangeMap EMPTY_SUB_RANGE_MAP =
new RangeMap() {
@Override
@Nullable
@@ -307,16 +317,21 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
}
@Override
+ public Map<Range, Object> asDescendingMapOfRanges() {
+ return Collections.emptyMap();
+ }
+
+ @Override
public RangeMap subRangeMap(Range range) {
checkNotNull(range);
return this;
}
};
-
+
private class SubRangeMap implements RangeMap<K, V> {
private final Range<K> subRange;
-
+
SubRangeMap(Range<K> subRange) {
this.subRange = subRange;
}
@@ -324,9 +339,7 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
@Override
@Nullable
public V get(K key) {
- return subRange.contains(key)
- ? TreeRangeMap.this.get(key)
- : null;
+ return subRange.contains(key) ? TreeRangeMap.this.get(key) : null;
}
@Override
@@ -346,8 +359,8 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
Cut<K> lowerBound;
Entry<Cut<K>, RangeMapEntry<K, V>> lowerEntry =
entriesByLowerBound.floorEntry(subRange.lowerBound);
- if (lowerEntry != null &&
- lowerEntry.getValue().getUpperBound().compareTo(subRange.lowerBound) > 0) {
+ if (lowerEntry != null
+ && lowerEntry.getValue().getUpperBound().compareTo(subRange.lowerBound) > 0) {
lowerBound = subRange.lowerBound;
} else {
lowerBound = entriesByLowerBound.ceilingKey(subRange.lowerBound);
@@ -355,9 +368,9 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
throw new NoSuchElementException();
}
}
-
+
Cut<K> upperBound;
- Entry<Cut<K>, RangeMapEntry<K, V>> upperEntry =
+ Entry<Cut<K>, RangeMapEntry<K, V>> upperEntry =
entriesByLowerBound.lowerEntry(subRange.upperBound);
if (upperEntry == null) {
throw new NoSuchElementException();
@@ -371,8 +384,8 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
@Override
public void put(Range<K> range, V value) {
- checkArgument(subRange.encloses(range),
- "Cannot put range %s into a subRangeMap(%s)", range, subRange);
+ checkArgument(
+ subRange.encloses(range), "Cannot put range %s into a subRangeMap(%s)", range, subRange);
TreeRangeMap.this.put(range, value);
}
@@ -382,8 +395,11 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
return;
}
Range<K> span = rangeMap.span();
- checkArgument(subRange.encloses(span),
- "Cannot putAll rangeMap with span %s into a subRangeMap(%s)", span, subRange);
+ checkArgument(
+ subRange.encloses(span),
+ "Cannot putAll rangeMap with span %s into a subRangeMap(%s)",
+ span,
+ subRange);
TreeRangeMap.this.putAll(rangeMap);
}
@@ -414,6 +430,39 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
}
@Override
+ public Map<Range<K>, V> asDescendingMapOfRanges() {
+ return new SubRangeMapAsMap() {
+
+ @Override
+ Iterator<Entry<Range<K>, V>> entryIterator() {
+ if (subRange.isEmpty()) {
+ return Iterators.emptyIterator();
+ }
+ final Iterator<RangeMapEntry<K, V>> backingItr =
+ entriesByLowerBound
+ .headMap(subRange.upperBound, false)
+ .descendingMap()
+ .values()
+ .iterator();
+ return new AbstractIterator<Entry<Range<K>, V>>() {
+
+ @Override
+ protected Entry<Range<K>, V> computeNext() {
+ while (backingItr.hasNext()) {
+ RangeMapEntry<K, V> entry = backingItr.next();
+ if (entry.getUpperBound().compareTo(subRange.lowerBound) <= 0) {
+ return endOfData();
+ }
+ return Maps.immutableEntry(entry.getKey().intersection(subRange), entry.getValue());
+ }
+ return endOfData();
+ }
+ };
+ }
+ };
+ }
+
+ @Override
public boolean equals(@Nullable Object o) {
if (o instanceof RangeMap) {
RangeMap<?, ?> rangeMap = (RangeMap<?, ?>) o;
@@ -431,9 +480,9 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
public String toString() {
return asMapOfRanges().toString();
}
-
+
class SubRangeMapAsMap extends AbstractMap<Range<K>, V> {
-
+
@Override
public boolean containsKey(Object key) {
return get(key) != null;
@@ -451,7 +500,7 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
RangeMapEntry<K, V> candidate = null;
if (r.lowerBound.compareTo(subRange.lowerBound) == 0) {
// r could be truncated on the left
- Entry<Cut<K>, RangeMapEntry<K, V>> entry =
+ Entry<Cut<K>, RangeMapEntry<K, V>> entry =
entriesByLowerBound.floorEntry(r.lowerBound);
if (entry != null) {
candidate = entry.getValue();
@@ -459,8 +508,9 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
} else {
candidate = entriesByLowerBound.get(r.lowerBound);
}
-
- if (candidate != null && candidate.getKey().isConnected(subRange)
+
+ if (candidate != null
+ && candidate.getKey().isConnected(subRange)
&& candidate.getKey().intersection(subRange).equals(r)) {
return candidate.getValue();
}
@@ -487,7 +537,7 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
public void clear() {
SubRangeMap.this.clear();
}
-
+
private boolean removeEntryIf(Predicate<? super Entry<Range<K>, V>> predicate) {
List<Range<K>> toRemove = Lists.newArrayList();
for (Entry<Range<K>, V> entry : entrySet()) {
@@ -508,7 +558,7 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
public boolean remove(@Nullable Object o) {
return SubRangeMapAsMap.this.remove(o) != null;
}
-
+
@Override
public boolean retainAll(Collection<?> c) {
return removeEntryIf(compose(not(in(c)), Maps.<Range<K>>keyFunction()));
@@ -526,57 +576,61 @@ public final class TreeRangeMap<K extends Comparable, V> implements RangeMap<K,
@Override
public Iterator<Entry<Range<K>, V>> iterator() {
- if (subRange.isEmpty()) {
- return Iterators.emptyIterator();
- }
- Cut<K> cutToStart = MoreObjects.firstNonNull(
- entriesByLowerBound.floorKey(subRange.lowerBound), subRange.lowerBound);
- final Iterator<RangeMapEntry<K, V>> backingItr =
- entriesByLowerBound.tailMap(cutToStart, true).values().iterator();
- return new AbstractIterator<Entry<Range<K>, V>>() {
-
- @Override
- protected Entry<Range<K>, V> computeNext() {
- while (backingItr.hasNext()) {
- RangeMapEntry<K, V> entry = backingItr.next();
- if (entry.getLowerBound().compareTo(subRange.upperBound) >= 0) {
- break;
- } else if (entry.getUpperBound().compareTo(subRange.lowerBound) > 0) {
- // this might not be true e.g. at the start of the iteration
- return Maps.immutableEntry(
- entry.getKey().intersection(subRange), entry.getValue());
- }
- }
- return endOfData();
- }
- };
+ return entryIterator();
}
-
+
@Override
public boolean retainAll(Collection<?> c) {
return removeEntryIf(not(in(c)));
}
-
+
@Override
public int size() {
return Iterators.size(iterator());
}
-
+
@Override
public boolean isEmpty() {
return !iterator().hasNext();
}
};
}
-
+
+ Iterator<Entry<Range<K>, V>> entryIterator() {
+ if (subRange.isEmpty()) {
+ return Iterators.emptyIterator();
+ }
+ Cut<K> cutToStart =
+ MoreObjects.firstNonNull(
+ entriesByLowerBound.floorKey(subRange.lowerBound), subRange.lowerBound);
+ final Iterator<RangeMapEntry<K, V>> backingItr =
+ entriesByLowerBound.tailMap(cutToStart, true).values().iterator();
+ return new AbstractIterator<Entry<Range<K>, V>>() {
+
+ @Override
+ protected Entry<Range<K>, V> computeNext() {
+ while (backingItr.hasNext()) {
+ RangeMapEntry<K, V> entry = backingItr.next();
+ if (entry.getLowerBound().compareTo(subRange.upperBound) >= 0) {
+ return endOfData();
+ } else if (entry.getUpperBound().compareTo(subRange.lowerBound) > 0) {
+ // this might not be true e.g. at the start of the iteration
+ return Maps.immutableEntry(entry.getKey().intersection(subRange), entry.getValue());
+ }
+ }
+ return endOfData();
+ }
+ };
+ }
+
@Override
public Collection<V> values() {
- return new Maps.Values<Range<K>, V>(this) {
+ return new Maps.Values<Range<K>, V>(this) {
@Override
public boolean removeAll(Collection<?> c) {
- return removeEntryIf(compose(in(c), Maps.<V>valueFunction()));
+ return removeEntryIf(compose(in(c), Maps.<V>valueFunction()));
}
-
+
@Override
public boolean retainAll(Collection<?> c) {
return removeEntryIf(compose(not(in(c)), Maps.<V>valueFunction()));
diff --git a/guava/src/com/google/common/collect/TreeRangeSet.java b/guava/src/com/google/common/collect/TreeRangeSet.java
index 606b3bc..9bb5c2f 100644
--- a/guava/src/com/google/common/collect/TreeRangeSet.java
+++ b/guava/src/com/google/common/collect/TreeRangeSet.java
@@ -41,11 +41,9 @@ import javax.annotation.Nullable;
*/
@Beta
@GwtIncompatible("uses NavigableMap")
-public class TreeRangeSet<C extends Comparable<?>>
- extends AbstractRangeSet<C> {
+public class TreeRangeSet<C extends Comparable<?>> extends AbstractRangeSet<C> {
- @VisibleForTesting
- final NavigableMap<Cut<C>, Range<C>> rangesByLowerBound;
+ @VisibleForTesting final NavigableMap<Cut<C>, Range<C>> rangesByLowerBound;
/**
* Creates an empty {@code TreeRangeSet} instance.
@@ -53,7 +51,7 @@ public class TreeRangeSet<C extends Comparable<?>>
public static <C extends Comparable<?>> TreeRangeSet<C> create() {
return new TreeRangeSet<C>(new TreeMap<Cut<C>, Range<C>>());
}
-
+
/**
* Returns a {@code TreeRangeSet} initialized with the ranges in the specified range set.
*/
@@ -68,17 +66,33 @@ public class TreeRangeSet<C extends Comparable<?>>
}
private transient Set<Range<C>> asRanges;
+ private transient Set<Range<C>> asDescendingSetOfRanges;
@Override
public Set<Range<C>> asRanges() {
Set<Range<C>> result = asRanges;
- return (result == null) ? asRanges = new AsRanges() : result;
+ return (result == null) ? asRanges = new AsRanges(rangesByLowerBound.values()) : result;
+ }
+
+ @Override
+ public Set<Range<C>> asDescendingSetOfRanges() {
+ Set<Range<C>> result = asDescendingSetOfRanges;
+ return (result == null)
+ ? asDescendingSetOfRanges = new AsRanges(rangesByLowerBound.descendingMap().values())
+ : result;
}
final class AsRanges extends ForwardingCollection<Range<C>> implements Set<Range<C>> {
+
+ final Collection<Range<C>> delegate;
+
+ AsRanges(Collection<Range<C>> delegate) {
+ this.delegate = delegate;
+ }
+
@Override
protected Collection<Range<C>> delegate() {
- return rangesByLowerBound.values();
+ return delegate;
}
@Override
@@ -111,7 +125,7 @@ public class TreeRangeSet<C extends Comparable<?>>
Entry<Cut<C>, Range<C>> floorEntry = rangesByLowerBound.floorEntry(range.lowerBound);
return floorEntry != null && floorEntry.getValue().encloses(range);
}
-
+
@Nullable
private Range<C> rangeEnclosing(Range<C> range) {
checkNotNull(range);
@@ -236,18 +250,18 @@ public class TreeRangeSet<C extends Comparable<?>>
RangeSet<C> result = complement;
return (result == null) ? complement = new Complement() : result;
}
-
+
@VisibleForTesting
static final class RangesByUpperBound<C extends Comparable<?>>
extends AbstractNavigableMap<Cut<C>, Range<C>> {
private final NavigableMap<Cut<C>, Range<C>> rangesByLowerBound;
-
+
/**
* upperBoundWindow represents the headMap/subMap/tailMap view of the entire "ranges by upper
* bound" map; it's a constraint on the *keys*, and does not affect the values.
*/
private final Range<Cut<C>> upperBoundWindow;
-
+
RangesByUpperBound(NavigableMap<Cut<C>, Range<C>> rangesByLowerBound) {
this.rangesByLowerBound = rangesByLowerBound;
this.upperBoundWindow = Range.all();
@@ -270,9 +284,10 @@ public class TreeRangeSet<C extends Comparable<?>>
@Override
public NavigableMap<Cut<C>, Range<C>> subMap(
Cut<C> fromKey, boolean fromInclusive, Cut<C> toKey, boolean toInclusive) {
- return subMap(Range.range(
- fromKey, BoundType.forBoolean(fromInclusive),
- toKey, BoundType.forBoolean(toInclusive)));
+ return subMap(
+ Range.range(
+ fromKey, BoundType.forBoolean(fromInclusive),
+ toKey, BoundType.forBoolean(toInclusive)));
}
@Override
@@ -332,8 +347,10 @@ public class TreeRangeSet<C extends Comparable<?>>
} else if (upperBoundWindow.lowerBound.isLessThan(lowerEntry.getValue().upperBound)) {
backingItr = rangesByLowerBound.tailMap(lowerEntry.getKey(), true).values().iterator();
} else {
- backingItr = rangesByLowerBound.tailMap(upperBoundWindow.lowerEndpoint(), true)
- .values().iterator();
+ backingItr = rangesByLowerBound
+ .tailMap(upperBoundWindow.lowerEndpoint(), true)
+ .values()
+ .iterator();
}
}
return new AbstractIterator<Entry<Cut<C>, Range<C>>>() {
@@ -356,8 +373,11 @@ public class TreeRangeSet<C extends Comparable<?>>
Iterator<Entry<Cut<C>, Range<C>>> descendingEntryIterator() {
Collection<Range<C>> candidates;
if (upperBoundWindow.hasUpperBound()) {
- candidates = rangesByLowerBound.headMap(upperBoundWindow.upperEndpoint(), false)
- .descendingMap().values();
+ candidates =
+ rangesByLowerBound
+ .headMap(upperBoundWindow.upperEndpoint(), false)
+ .descendingMap()
+ .values();
} else {
candidates = rangesByLowerBound.descendingMap().values();
}
@@ -373,7 +393,7 @@ public class TreeRangeSet<C extends Comparable<?>>
return endOfData();
}
Range<C> range = backingItr.next();
- return upperBoundWindow.lowerBound.isLessThan(range.upperBound)
+ return upperBoundWindow.lowerBound.isLessThan(range.upperBound)
? Maps.immutableEntry(range.upperBound, range)
: endOfData();
}
@@ -387,7 +407,7 @@ public class TreeRangeSet<C extends Comparable<?>>
}
return Iterators.size(entryIterator());
}
-
+
@Override
public boolean isEmpty() {
return upperBoundWindow.equals(Range.all())
@@ -395,25 +415,25 @@ public class TreeRangeSet<C extends Comparable<?>>
: !entryIterator().hasNext();
}
}
-
+
private static final class ComplementRangesByLowerBound<C extends Comparable<?>>
extends AbstractNavigableMap<Cut<C>, Range<C>> {
private final NavigableMap<Cut<C>, Range<C>> positiveRangesByLowerBound;
private final NavigableMap<Cut<C>, Range<C>> positiveRangesByUpperBound;
-
+
/**
* complementLowerBoundWindow represents the headMap/subMap/tailMap view of the entire
* "complement ranges by lower bound" map; it's a constraint on the *keys*, and does not affect
* the values.
*/
private final Range<Cut<C>> complementLowerBoundWindow;
-
+
ComplementRangesByLowerBound(NavigableMap<Cut<C>, Range<C>> positiveRangesByLowerBound) {
this(positiveRangesByLowerBound, Range.<Cut<C>>all());
}
- private ComplementRangesByLowerBound(NavigableMap<Cut<C>, Range<C>> positiveRangesByLowerBound,
- Range<Cut<C>> window) {
+ private ComplementRangesByLowerBound(
+ NavigableMap<Cut<C>, Range<C>> positiveRangesByLowerBound, Range<Cut<C>> window) {
this.positiveRangesByLowerBound = positiveRangesByLowerBound;
this.positiveRangesByUpperBound = new RangesByUpperBound<C>(positiveRangesByLowerBound);
this.complementLowerBoundWindow = window;
@@ -421,7 +441,7 @@ public class TreeRangeSet<C extends Comparable<?>>
private NavigableMap<Cut<C>, Range<C>> subMap(Range<Cut<C>> subWindow) {
if (!complementLowerBoundWindow.isConnected(subWindow)) {
- return ImmutableSortedMap.of();
+ return ImmutableSortedMap.of();
} else {
subWindow = subWindow.intersection(complementLowerBoundWindow);
return new ComplementRangesByLowerBound<C>(positiveRangesByLowerBound, subWindow);
@@ -431,9 +451,10 @@ public class TreeRangeSet<C extends Comparable<?>>
@Override
public NavigableMap<Cut<C>, Range<C>> subMap(
Cut<C> fromKey, boolean fromInclusive, Cut<C> toKey, boolean toInclusive) {
- return subMap(Range.range(
- fromKey, BoundType.forBoolean(fromInclusive),
- toKey, BoundType.forBoolean(toInclusive)));
+ return subMap(
+ Range.range(
+ fromKey, BoundType.forBoolean(fromInclusive),
+ toKey, BoundType.forBoolean(toInclusive)));
}
@Override
@@ -464,17 +485,20 @@ public class TreeRangeSet<C extends Comparable<?>>
*/
Collection<Range<C>> positiveRanges;
if (complementLowerBoundWindow.hasLowerBound()) {
- positiveRanges = positiveRangesByUpperBound.tailMap(
- complementLowerBoundWindow.lowerEndpoint(),
- complementLowerBoundWindow.lowerBoundType() == BoundType.CLOSED).values();
+ positiveRanges =
+ positiveRangesByUpperBound
+ .tailMap(
+ complementLowerBoundWindow.lowerEndpoint(),
+ complementLowerBoundWindow.lowerBoundType() == BoundType.CLOSED)
+ .values();
} else {
positiveRanges = positiveRangesByUpperBound.values();
}
- final PeekingIterator<Range<C>> positiveItr = Iterators.peekingIterator(
- positiveRanges.iterator());
+ final PeekingIterator<Range<C>> positiveItr =
+ Iterators.peekingIterator(positiveRanges.iterator());
final Cut<C> firstComplementRangeLowerBound;
- if (complementLowerBoundWindow.contains(Cut.<C>belowAll()) &&
- (!positiveItr.hasNext() || positiveItr.peek().lowerBound != Cut.<C>belowAll())) {
+ if (complementLowerBoundWindow.contains(Cut.<C>belowAll())
+ && (!positiveItr.hasNext() || positiveItr.peek().lowerBound != Cut.<C>belowAll())) {
firstComplementRangeLowerBound = Cut.belowAll();
} else if (positiveItr.hasNext()) {
firstComplementRangeLowerBound = positiveItr.next().upperBound;
@@ -514,18 +538,24 @@ public class TreeRangeSet<C extends Comparable<?>>
* firstComplementRangeUpperBound. (Positive range upper bounds correspond to complement range
* lower bounds.)
*/
- Cut<C> startingPoint = complementLowerBoundWindow.hasUpperBound()
- ? complementLowerBoundWindow.upperEndpoint()
- : Cut.<C>aboveAll();
- boolean inclusive = complementLowerBoundWindow.hasUpperBound()
- && complementLowerBoundWindow.upperBoundType() == BoundType.CLOSED;
+ Cut<C> startingPoint =
+ complementLowerBoundWindow.hasUpperBound()
+ ? complementLowerBoundWindow.upperEndpoint()
+ : Cut.<C>aboveAll();
+ boolean inclusive =
+ complementLowerBoundWindow.hasUpperBound()
+ && complementLowerBoundWindow.upperBoundType() == BoundType.CLOSED;
final PeekingIterator<Range<C>> positiveItr =
- Iterators.peekingIterator(positiveRangesByUpperBound.headMap(startingPoint, inclusive)
- .descendingMap().values().iterator());
+ Iterators.peekingIterator(
+ positiveRangesByUpperBound
+ .headMap(startingPoint, inclusive)
+ .descendingMap()
+ .values()
+ .iterator());
Cut<C> cut;
if (positiveItr.hasNext()) {
- cut = (positiveItr.peek().upperBound == Cut.<C>aboveAll())
- ? positiveItr.next().lowerBound
+ cut = (positiveItr.peek().upperBound == Cut.<C>aboveAll())
+ ? positiveItr.next().lowerBound
: positiveRangesByLowerBound.higherKey(positiveItr.peek().upperBound);
} else if (!complementLowerBoundWindow.contains(Cut.<C>belowAll())
|| positiveRangesByLowerBound.containsKey(Cut.belowAll())) {
@@ -551,8 +581,7 @@ public class TreeRangeSet<C extends Comparable<?>>
return Maps.immutableEntry(negativeRange.lowerBound, negativeRange);
}
} else if (complementLowerBoundWindow.lowerBound.isLessThan(Cut.<C>belowAll())) {
- Range<C> negativeRange =
- Range.create(Cut.<C>belowAll(), nextComplementRangeUpperBound);
+ Range<C> negativeRange = Range.create(Cut.<C>belowAll(), nextComplementRangeUpperBound);
nextComplementRangeUpperBound = Cut.belowAll();
return Maps.immutableEntry(Cut.<C>belowAll(), negativeRange);
}
@@ -610,7 +639,7 @@ public class TreeRangeSet<C extends Comparable<?>>
public boolean contains(C value) {
return !TreeRangeSet.this.contains(value);
}
-
+
@Override
public RangeSet<C> complement() {
return TreeRangeSet.this;
@@ -634,7 +663,9 @@ public class TreeRangeSet<C extends Comparable<?>>
private final NavigableMap<Cut<C>, Range<C>> rangesByLowerBound;
private final NavigableMap<Cut<C>, Range<C>> rangesByUpperBound;
- private SubRangeSetRangesByLowerBound(Range<Cut<C>> lowerBoundWindow, Range<C> restriction,
+ private SubRangeSetRangesByLowerBound(
+ Range<Cut<C>> lowerBoundWindow,
+ Range<C> restriction,
NavigableMap<Cut<C>, Range<C>> rangesByLowerBound) {
this.lowerBoundWindow = checkNotNull(lowerBoundWindow);
this.restriction = checkNotNull(restriction);
@@ -654,8 +685,12 @@ public class TreeRangeSet<C extends Comparable<?>>
@Override
public NavigableMap<Cut<C>, Range<C>> subMap(
Cut<C> fromKey, boolean fromInclusive, Cut<C> toKey, boolean toInclusive) {
- return subMap(Range.range(
- fromKey, BoundType.forBoolean(fromInclusive), toKey, BoundType.forBoolean(toInclusive)));
+ return subMap(
+ Range.range(
+ fromKey,
+ BoundType.forBoolean(fromInclusive),
+ toKey,
+ BoundType.forBoolean(toInclusive)));
}
@Override
@@ -685,7 +720,8 @@ public class TreeRangeSet<C extends Comparable<?>>
try {
@SuppressWarnings("unchecked") // we catch CCE's
Cut<C> cut = (Cut<C>) key;
- if (!lowerBoundWindow.contains(cut) || cut.compareTo(restriction.lowerBound) < 0
+ if (!lowerBoundWindow.contains(cut)
+ || cut.compareTo(restriction.lowerBound) < 0
|| cut.compareTo(restriction.upperBound) >= 0) {
return null;
} else if (cut.equals(restriction.lowerBound)) {
@@ -721,11 +757,17 @@ public class TreeRangeSet<C extends Comparable<?>>
rangesByUpperBound.tailMap(restriction.lowerBound, false).values().iterator();
} else {
// starts at the first range with lower bound above lowerBoundWindow.lowerBound
- completeRangeItr = rangesByLowerBound.tailMap(lowerBoundWindow.lowerBound.endpoint(),
- lowerBoundWindow.lowerBoundType() == BoundType.CLOSED).values().iterator();
+ completeRangeItr =
+ rangesByLowerBound
+ .tailMap(
+ lowerBoundWindow.lowerBound.endpoint(),
+ lowerBoundWindow.lowerBoundType() == BoundType.CLOSED)
+ .values()
+ .iterator();
}
- final Cut<Cut<C>> upperBoundOnLowerBounds = Ordering.natural()
- .min(lowerBoundWindow.upperBound, Cut.belowValue(restriction.upperBound));
+ final Cut<Cut<C>> upperBoundOnLowerBounds =
+ Ordering.natural()
+ .min(lowerBoundWindow.upperBound, Cut.belowValue(restriction.upperBound));
return new AbstractIterator<Entry<Cut<C>, Range<C>>>() {
@Override
protected Entry<Cut<C>, Range<C>> computeNext() {
@@ -748,12 +790,17 @@ public class TreeRangeSet<C extends Comparable<?>>
if (restriction.isEmpty()) {
return Iterators.emptyIterator();
}
- Cut<Cut<C>> upperBoundOnLowerBounds = Ordering.natural()
- .min(lowerBoundWindow.upperBound, Cut.belowValue(restriction.upperBound));
- final Iterator<Range<C>> completeRangeItr = rangesByLowerBound.headMap(
- upperBoundOnLowerBounds.endpoint(),
- upperBoundOnLowerBounds.typeAsUpperBound() == BoundType.CLOSED)
- .descendingMap().values().iterator();
+ Cut<Cut<C>> upperBoundOnLowerBounds =
+ Ordering.natural()
+ .min(lowerBoundWindow.upperBound, Cut.belowValue(restriction.upperBound));
+ final Iterator<Range<C>> completeRangeItr =
+ rangesByLowerBound
+ .headMap(
+ upperBoundOnLowerBounds.endpoint(),
+ upperBoundOnLowerBounds.typeAsUpperBound() == BoundType.CLOSED)
+ .descendingMap()
+ .values()
+ .iterator();
return new AbstractIterator<Entry<Cut<C>, Range<C>>>() {
@Override
protected Entry<Cut<C>, Range<C>> computeNext() {
@@ -779,12 +826,12 @@ public class TreeRangeSet<C extends Comparable<?>>
return Iterators.size(entryIterator());
}
}
-
+
@Override
public RangeSet<C> subRangeSet(Range<C> view) {
return view.equals(Range.<C>all()) ? this : new SubRangeSet(view);
}
-
+
private final class SubRangeSet extends TreeRangeSet<C> {
private final Range<C> restriction;
@@ -815,8 +862,11 @@ public class TreeRangeSet<C extends Comparable<?>>
@Override
public void add(Range<C> rangeToAdd) {
- checkArgument(restriction.encloses(rangeToAdd), "Cannot add range %s to subRangeSet(%s)",
- rangeToAdd, restriction);
+ checkArgument(
+ restriction.encloses(rangeToAdd),
+ "Cannot add range %s to subRangeSet(%s)",
+ rangeToAdd,
+ restriction);
super.add(rangeToAdd);
}
diff --git a/guava/src/com/google/common/collect/TreeTraverser.java b/guava/src/com/google/common/collect/TreeTraverser.java
index 60459ae..2f3183c 100644
--- a/guava/src/com/google/common/collect/TreeTraverser.java
+++ b/guava/src/com/google/common/collect/TreeTraverser.java
@@ -52,7 +52,7 @@ import java.util.Queue;
@Beta
@GwtCompatible(emulated = true)
public abstract class TreeTraverser<T> {
- // TODO(user): make this GWT-compatible when we've checked in ArrayDeque emulation
+ // TODO(lowasser): make this GWT-compatible when we've checked in ArrayDeque emulation
/**
* Returns the children of the specified node. Must not contain null.
diff --git a/guava/src/com/google/common/collect/UnmodifiableIterator.java b/guava/src/com/google/common/collect/UnmodifiableIterator.java
index 55ceef9..73e8c90 100644
--- a/guava/src/com/google/common/collect/UnmodifiableIterator.java
+++ b/guava/src/com/google/common/collect/UnmodifiableIterator.java
@@ -23,8 +23,12 @@ import java.util.Iterator;
/**
* An iterator that does not support {@link #remove}.
*
+ * <p>{@code UnmodifiableIterator} is used primarily in conjunction with implementations of
+ * {@link ImmutableCollection}, such as {@link ImmutableList}. You can, however, convert an existing
+ * iterator to an {@code UnmodifiableIterator} using {@link Iterators#unmodifiableIterator}.
+ *
* @author Jared Levy
- * @since 2.0 (imported from Google Collections Library)
+ * @since 2.0
*/
@GwtCompatible
public abstract class UnmodifiableIterator<E> implements Iterator<E> {
diff --git a/guava/src/com/google/common/collect/UnmodifiableListIterator.java b/guava/src/com/google/common/collect/UnmodifiableListIterator.java
index 8e535a3..37e1bbf 100644
--- a/guava/src/com/google/common/collect/UnmodifiableListIterator.java
+++ b/guava/src/com/google/common/collect/UnmodifiableListIterator.java
@@ -28,8 +28,8 @@ import java.util.ListIterator;
* @author Louis Wasserman
*/
@GwtCompatible
-public abstract class UnmodifiableListIterator<E>
- extends UnmodifiableIterator<E> implements ListIterator<E> {
+public abstract class UnmodifiableListIterator<E> extends UnmodifiableIterator<E>
+ implements ListIterator<E> {
/** Constructor for use by subclasses. */
protected UnmodifiableListIterator() {}
@@ -39,7 +39,9 @@ public abstract class UnmodifiableListIterator<E>
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public final void add(E e) {
+ @Deprecated
+ @Override
+ public final void add(E e) {
throw new UnsupportedOperationException();
}
@@ -49,7 +51,9 @@ public abstract class UnmodifiableListIterator<E>
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
- @Deprecated @Override public final void set(E e) {
+ @Deprecated
+ @Override
+ public final void set(E e) {
throw new UnsupportedOperationException();
}
}
diff --git a/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java b/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java
index 4b353cb..446da96 100644
--- a/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java
+++ b/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java
@@ -26,12 +26,12 @@ import java.util.NavigableSet;
* Implementation of {@link Multisets#unmodifiableSortedMultiset(SortedMultiset)},
* split out into its own file so it can be GWT emulated (to deal with the differing
* elementSet() types in GWT and non-GWT).
- *
+ *
* @author Louis Wasserman
*/
@GwtCompatible(emulated = true)
-final class UnmodifiableSortedMultiset<E>
- extends UnmodifiableMultiset<E> implements SortedMultiset<E> {
+final class UnmodifiableSortedMultiset<E> extends UnmodifiableMultiset<E>
+ implements SortedMultiset<E> {
UnmodifiableSortedMultiset(SortedMultiset<E> delegate) {
super(delegate);
}
@@ -62,8 +62,7 @@ final class UnmodifiableSortedMultiset<E>
public SortedMultiset<E> descendingMultiset() {
UnmodifiableSortedMultiset<E> result = descendingMultiset;
if (result == null) {
- result = new UnmodifiableSortedMultiset<E>(
- delegate().descendingMultiset());
+ result = new UnmodifiableSortedMultiset<E>(delegate().descendingMultiset());
result.descendingMultiset = this;
return descendingMultiset = result;
}
@@ -92,23 +91,20 @@ final class UnmodifiableSortedMultiset<E>
@Override
public SortedMultiset<E> headMultiset(E upperBound, BoundType boundType) {
- return Multisets.unmodifiableSortedMultiset(
- delegate().headMultiset(upperBound, boundType));
+ return Multisets.unmodifiableSortedMultiset(delegate().headMultiset(upperBound, boundType));
}
@Override
public SortedMultiset<E> subMultiset(
- E lowerBound, BoundType lowerBoundType,
- E upperBound, BoundType upperBoundType) {
- return Multisets.unmodifiableSortedMultiset(delegate().subMultiset(
- lowerBound, lowerBoundType, upperBound, upperBoundType));
+ E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) {
+ return Multisets.unmodifiableSortedMultiset(
+ delegate().subMultiset(lowerBound, lowerBoundType, upperBound, upperBoundType));
}
@Override
public SortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
- return Multisets.unmodifiableSortedMultiset(
- delegate().tailMultiset(lowerBound, boundType));
+ return Multisets.unmodifiableSortedMultiset(delegate().tailMultiset(lowerBound, boundType));
}
private static final long serialVersionUID = 0;
-}
\ No newline at end of file
+}
diff --git a/guava/src/com/google/common/collect/UsingToStringOrdering.java b/guava/src/com/google/common/collect/UsingToStringOrdering.java
index adb6aa7..d4ce5bb 100644
--- a/guava/src/com/google/common/collect/UsingToStringOrdering.java
+++ b/guava/src/com/google/common/collect/UsingToStringOrdering.java
@@ -25,11 +25,11 @@ import java.io.Serializable;
* values.
*/
@GwtCompatible(serializable = true)
-final class UsingToStringOrdering
- extends Ordering<Object> implements Serializable {
+final class UsingToStringOrdering extends Ordering<Object> implements Serializable {
static final UsingToStringOrdering INSTANCE = new UsingToStringOrdering();
- @Override public int compare(Object left, Object right) {
+ @Override
+ public int compare(Object left, Object right) {
return left.toString().compareTo(right.toString());
}
@@ -38,7 +38,8 @@ final class UsingToStringOrdering
return INSTANCE;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Ordering.usingToString()";
}
diff --git a/guava/src/com/google/common/collect/WellBehavedMap.java b/guava/src/com/google/common/collect/WellBehavedMap.java
index c68cc5e..16993d0 100644
--- a/guava/src/com/google/common/collect/WellBehavedMap.java
+++ b/guava/src/com/google/common/collect/WellBehavedMap.java
@@ -17,6 +17,7 @@
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.Iterator;
import java.util.Map;
@@ -52,11 +53,13 @@ final class WellBehavedMap<K, V> extends ForwardingMap<K, V> {
return new WellBehavedMap<K, V>(delegate);
}
- @Override protected Map<K, V> delegate() {
+ @Override
+ protected Map<K, V> delegate() {
return delegate;
}
- @Override public Set<Entry<K, V>> entrySet() {
+ @Override
+ public Set<Entry<K, V>> entrySet() {
Set<Entry<K, V>> es = entrySet;
if (es != null) {
return es;
@@ -64,6 +67,7 @@ final class WellBehavedMap<K, V> extends ForwardingMap<K, V> {
return entrySet = new EntrySet();
}
+ @WeakOuter
private final class EntrySet extends Maps.EntrySet<K, V> {
@Override
Map<K, V> map() {
diff --git a/guava/src/com/google/common/escape/CharEscaper.java b/guava/src/com/google/common/escape/CharEscaper.java
index 4be21a6..2648540 100644
--- a/guava/src/com/google/common/escape/CharEscaper.java
+++ b/guava/src/com/google/common/escape/CharEscaper.java
@@ -34,9 +34,9 @@ import com.google.common.annotations.GwtCompatible;
* <p>A {@code CharEscaper} instance is required to be stateless, and safe when used concurrently by
* multiple threads.
*
- * <p>Several popular escapers are defined as constants in classes like {@link
- * com.google.common.html.HtmlEscapers}, {@link com.google.common.xml.XmlEscapers}, and {@link
- * SourceCodeEscapers}. To create your own escapers extend this class and implement the {@link
+ * <p>Popular escapers are defined as constants in classes like {@link
+ * com.google.common.html.HtmlEscapers} and {@link com.google.common.xml.XmlEscapers}.
+ * To create your own escapers extend this class and implement the {@link
* #escape(char)} method.
*
* @author Sven Mawson
diff --git a/guava/src/com/google/common/escape/Escaper.java b/guava/src/com/google/common/escape/Escaper.java
index 396a388..f0ddfc1 100644
--- a/guava/src/com/google/common/escape/Escaper.java
+++ b/guava/src/com/google/common/escape/Escaper.java
@@ -48,10 +48,10 @@ import com.google.common.base.Function;
* extend one of these classes. If you find that you are unable to achieve the desired behavior
* using either of these classes, please contact the Java libraries team for advice.
*
- * <p>Several popular escapers are defined as constants in classes like {@link
- * com.google.common.html.HtmlEscapers}, {@link com.google.common.xml.XmlEscapers}, and {@link
- * SourceCodeEscapers}. To create your own escapers, use {@link CharEscaperBuilder}, or extend
- * {@code CharEscaper} or {@code UnicodeEscaper}.
+ * <p>Popular escapers are defined as constants in classes like {@link
+ * com.google.common.html.HtmlEscapers} and {@link com.google.common.xml.XmlEscapers}.
+ * To create your own escapers, use {@link CharEscaperBuilder}, or extend {@code CharEscaper}
+ * or {@code UnicodeEscaper}.
*
* @author David Beaumont
* @since 15.0
diff --git a/guava/src/com/google/common/escape/UnicodeEscaper.java b/guava/src/com/google/common/escape/UnicodeEscaper.java
index dec65e9..92e98b9 100644
--- a/guava/src/com/google/common/escape/UnicodeEscaper.java
+++ b/guava/src/com/google/common/escape/UnicodeEscaper.java
@@ -46,10 +46,9 @@ import com.google.common.annotations.GwtCompatible;
* <p>A {@code UnicodeEscaper} instance is required to be stateless, and safe
* when used concurrently by multiple threads.
*
- * <p>Several popular escapers are defined as constants in classes like {@link
- * com.google.common.html.HtmlEscapers}, {@link
- * com.google.common.xml.XmlEscapers}, and {@link SourceCodeEscapers}. To create
- * your own escapers extend this class and implement the {@link #escape(int)}
+ * <p>Popular escapers are defined as constants in classes like {@link
+ * com.google.common.html.HtmlEscapers} and {@link com.google.common.xml.XmlEscapers}.
+ * To create your own escapers extend this class and implement the {@link #escape(int)}
* method.
*
* @author David Beaumont
diff --git a/guava/src/com/google/common/eventbus/AnnotatedSubscriberFinder.java b/guava/src/com/google/common/eventbus/AnnotatedSubscriberFinder.java
deleted file mode 100644
index b1c38ff..0000000
--- a/guava/src/com/google/common/eventbus/AnnotatedSubscriberFinder.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2007 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.eventbus;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Throwables;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.reflect.TypeToken;
-import com.google.common.util.concurrent.UncheckedExecutionException;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-/**
- * A {@link SubscriberFindingStrategy} for collecting all event subscriber methods that are marked
- * with the {@link Subscribe} annotation.
- *
- * @author Cliff Biffle
- * @author Louis Wasserman
- */
-class AnnotatedSubscriberFinder implements SubscriberFindingStrategy {
- /**
- * A thread-safe cache that contains the mapping from each class to all methods in that class and
- * all super-classes, that are annotated with {@code @Subscribe}. The cache is shared across all
- * instances of this class; this greatly improves performance if multiple EventBus instances are
- * created and objects of the same class are registered on all of them.
- */
- private static final LoadingCache<Class<?>, ImmutableList<Method>> subscriberMethodsCache =
- CacheBuilder.newBuilder()
- .weakKeys()
- .build(new CacheLoader<Class<?>, ImmutableList<Method>>() {
- @Override
- public ImmutableList<Method> load(Class<?> concreteClass) throws Exception {
- return getAnnotatedMethodsInternal(concreteClass);
- }
- });
-
- /**
- * {@inheritDoc}
- *
- * This implementation finds all methods marked with a {@link Subscribe} annotation.
- */
- @Override
- public Multimap<Class<?>, EventSubscriber> findAllSubscribers(Object listener) {
- Multimap<Class<?>, EventSubscriber> methodsInListener = HashMultimap.create();
- Class<?> clazz = listener.getClass();
- for (Method method : getAnnotatedMethods(clazz)) {
- Class<?>[] parameterTypes = method.getParameterTypes();
- Class<?> eventType = parameterTypes[0];
- EventSubscriber subscriber = makeSubscriber(listener, method);
- methodsInListener.put(eventType, subscriber);
- }
- return methodsInListener;
- }
-
- private static ImmutableList<Method> getAnnotatedMethods(Class<?> clazz) {
- try {
- return subscriberMethodsCache.getUnchecked(clazz);
- } catch (UncheckedExecutionException e) {
- throw Throwables.propagate(e.getCause());
- }
- }
-
- private static final class MethodIdentifier {
- private final String name;
- private final List<Class<?>> parameterTypes;
-
- MethodIdentifier(Method method) {
- this.name = method.getName();
- this.parameterTypes = Arrays.asList(method.getParameterTypes());
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(name, parameterTypes);
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (o instanceof MethodIdentifier) {
- MethodIdentifier ident = (MethodIdentifier) o;
- return name.equals(ident.name) && parameterTypes.equals(ident.parameterTypes);
- }
- return false;
- }
- }
-
- private static ImmutableList<Method> getAnnotatedMethodsInternal(Class<?> clazz) {
- Set<? extends Class<?>> supers = TypeToken.of(clazz).getTypes().rawTypes();
- Map<MethodIdentifier, Method> identifiers = Maps.newHashMap();
- for (Class<?> superClazz : supers) {
- for (Method superClazzMethod : superClazz.getMethods()) {
- if (superClazzMethod.isAnnotationPresent(Subscribe.class)
- && !superClazzMethod.isBridge()) {
- Class<?>[] parameterTypes = superClazzMethod.getParameterTypes();
- if (parameterTypes.length != 1) {
- throw new IllegalArgumentException("Method " + superClazzMethod
- + " has @Subscribe annotation, but requires " + parameterTypes.length
- + " arguments. Event subscriber methods must require a single argument.");
- }
-
- MethodIdentifier ident = new MethodIdentifier(superClazzMethod);
- if (!identifiers.containsKey(ident)) {
- identifiers.put(ident, superClazzMethod);
- }
- }
- }
- }
- return ImmutableList.copyOf(identifiers.values());
- }
-
- /**
- * Creates an {@code EventSubscriber} for subsequently calling {@code method} on
- * {@code listener}.
- * Selects an EventSubscriber implementation based on the annotations on
- * {@code method}.
- *
- * @param listener object bearing the event subscriber method.
- * @param method the event subscriber method to wrap in an EventSubscriber.
- * @return an EventSubscriber that will call {@code method} on {@code listener}
- * when invoked.
- */
- private static EventSubscriber makeSubscriber(Object listener, Method method) {
- EventSubscriber wrapper;
- if (methodIsDeclaredThreadSafe(method)) {
- wrapper = new EventSubscriber(listener, method);
- } else {
- wrapper = new SynchronizedEventSubscriber(listener, method);
- }
- return wrapper;
- }
-
- /**
- * Checks whether {@code method} is thread-safe, as indicated by the
- * {@link AllowConcurrentEvents} annotation.
- *
- * @param method subscriber method to check.
- * @return {@code true} if {@code subscriber} is marked as thread-safe,
- * {@code false} otherwise.
- */
- private static boolean methodIsDeclaredThreadSafe(Method method) {
- return method.getAnnotation(AllowConcurrentEvents.class) != null;
- }
-}
diff --git a/guava/src/com/google/common/eventbus/AsyncEventBus.java b/guava/src/com/google/common/eventbus/AsyncEventBus.java
index 4fd3550..a150a8a 100644
--- a/guava/src/com/google/common/eventbus/AsyncEventBus.java
+++ b/guava/src/com/google/common/eventbus/AsyncEventBus.java
@@ -16,11 +16,8 @@
package com.google.common.eventbus;
-import static com.google.common.base.Preconditions.checkNotNull;
-
import com.google.common.annotations.Beta;
-import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
/**
@@ -32,11 +29,6 @@ import java.util.concurrent.Executor;
*/
@Beta
public class AsyncEventBus extends EventBus {
- private final Executor executor;
-
- /** the queue of events is shared across all threads */
- private final ConcurrentLinkedQueue<EventWithSubscriber> eventsToDispatch =
- new ConcurrentLinkedQueue<EventWithSubscriber>();
/**
* Creates a new AsyncEventBus that will use {@code executor} to dispatch
@@ -48,8 +40,7 @@ public class AsyncEventBus extends EventBus {
* been posted to this event bus.
*/
public AsyncEventBus(String identifier, Executor executor) {
- super(identifier);
- this.executor = checkNotNull(executor);
+ super(identifier, executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE);
}
/**
@@ -64,8 +55,7 @@ public class AsyncEventBus extends EventBus {
* @since 16.0
*/
public AsyncEventBus(Executor executor, SubscriberExceptionHandler subscriberExceptionHandler) {
- super(subscriberExceptionHandler);
- this.executor = checkNotNull(executor);
+ super("default", executor, Dispatcher.legacyAsync(), subscriberExceptionHandler);
}
/**
@@ -77,45 +67,6 @@ public class AsyncEventBus extends EventBus {
* been posted to this event bus.
*/
public AsyncEventBus(Executor executor) {
- super("default");
- this.executor = checkNotNull(executor);
- }
-
- @Override
- void enqueueEvent(Object event, EventSubscriber subscriber) {
- eventsToDispatch.offer(new EventWithSubscriber(event, subscriber));
- }
-
- /**
- * Dispatch {@code events} in the order they were posted, regardless of
- * the posting thread.
- */
- @SuppressWarnings("deprecation") // only deprecated for external subclasses
- @Override
- protected void dispatchQueuedEvents() {
- while (true) {
- EventWithSubscriber eventWithSubscriber = eventsToDispatch.poll();
- if (eventWithSubscriber == null) {
- break;
- }
-
- dispatch(eventWithSubscriber.event, eventWithSubscriber.subscriber);
- }
- }
-
- /**
- * Calls the {@link #executor} to dispatch {@code event} to {@code subscriber}.
- */
- @Override
- void dispatch(final Object event, final EventSubscriber subscriber) {
- checkNotNull(event);
- checkNotNull(subscriber);
- executor.execute(
- new Runnable() {
- @Override
- public void run() {
- AsyncEventBus.super.dispatch(event, subscriber);
- }
- });
+ super("default", executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE);
}
}
diff --git a/guava/src/com/google/common/eventbus/DeadEvent.java b/guava/src/com/google/common/eventbus/DeadEvent.java
index 41f15d3..90929f7 100644
--- a/guava/src/com/google/common/eventbus/DeadEvent.java
+++ b/guava/src/com/google/common/eventbus/DeadEvent.java
@@ -19,6 +19,7 @@ package com.google.common.eventbus;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
/**
* Wraps an event that was posted, but which had no subscribers and thus could
@@ -68,4 +69,11 @@ public class DeadEvent {
return event;
}
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("source", source)
+ .add("event", event)
+ .toString();
+ }
}
diff --git a/guava/src/com/google/common/eventbus/Dispatcher.java b/guava/src/com/google/common/eventbus/Dispatcher.java
new file mode 100644
index 0000000..c406c7e
--- /dev/null
+++ b/guava/src/com/google/common/eventbus/Dispatcher.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.eventbus;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.collect.Queues;
+
+import java.util.Iterator;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * Handler for dispatching events to subscribers, providing different event ordering guarantees that
+ * make sense for different situations.
+ *
+ * <p><b>Note:</b> The dispatcher is orthogonal to the subscriber's {@code Executor}. The dispatcher
+ * controls the order in which events are dispatched, while the executor controls how (i.e. on which
+ * thread) the subscriber is actually called when an event is dispatched to it.
+ *
+ * @author Colin Decker
+ */
+abstract class Dispatcher {
+
+ /**
+ * Returns a dispatcher that queues events that are posted reentrantly on a thread that is already
+ * dispatching an event, guaranteeing that all events posted on a single thread are dispatched to
+ * all subscribers in the order they are posted.
+ *
+ * <p>When all subscribers are dispatched to using a <i>direct</i> executor (which dispatches on
+ * the same thread that posts the event), this yields a breadth-first dispatch order on each
+ * thread. That is, all subscribers to a single event A will be called before any subscribers to
+ * any events B and C that are posted to the event bus by the subscribers to A.
+ */
+ static Dispatcher perThreadDispatchQueue() {
+ return new PerThreadQueuedDispatcher();
+ }
+
+ /**
+ * Returns a dispatcher that queues events that are posted in a single global queue. This
+ * behavior matches the original behavior of AsyncEventBus exactly, but is otherwise not
+ * especially useful. For async dispatch, an {@linkplain #immediate() immediate} dispatcher
+ * should generally be preferable.
+ */
+ static Dispatcher legacyAsync() {
+ return new LegacyAsyncDispatcher();
+ }
+
+ /**
+ * Returns a dispatcher that dispatches events to subscribers immediately as they're posted
+ * without using an intermediate queue to change the dispatch order. This is effectively a
+ * depth-first dispatch order, vs. breadth-first when using a queue.
+ */
+ static Dispatcher immediate() {
+ return ImmediateDispatcher.INSTANCE;
+ }
+
+ /**
+ * Dispatches the given {@code event} to the given {@code subscribers}.
+ */
+ abstract void dispatch(Object event, Iterator<Subscriber> subscribers);
+
+ /**
+ * Implementation of a {@link #perThreadDispatchQueue()} dispatcher.
+ */
+ private static final class PerThreadQueuedDispatcher extends Dispatcher {
+
+ // This dispatcher matches the original dispatch behavior of EventBus.
+
+ /**
+ * Per-thread queue of events to dispatch.
+ */
+ private final ThreadLocal<Queue<Event>> queue =
+ new ThreadLocal<Queue<Event>>() {
+ @Override
+ protected Queue<Event> initialValue() {
+ return Queues.newArrayDeque();
+ }
+ };
+
+ /**
+ * Per-thread dispatch state, used to avoid reentrant event dispatching.
+ */
+ private final ThreadLocal<Boolean> dispatching =
+ new ThreadLocal<Boolean>() {
+ @Override
+ protected Boolean initialValue() {
+ return false;
+ }
+ };
+
+ @Override
+ void dispatch(Object event, Iterator<Subscriber> subscribers) {
+ checkNotNull(event);
+ checkNotNull(subscribers);
+ Queue<Event> queueForThread = queue.get();
+ queueForThread.offer(new Event(event, subscribers));
+
+ if (!dispatching.get()) {
+ dispatching.set(true);
+ try {
+ Event nextEvent;
+ while ((nextEvent = queueForThread.poll()) != null) {
+ while (nextEvent.subscribers.hasNext()) {
+ nextEvent.subscribers.next().dispatchEvent(nextEvent.event);
+ }
+ }
+ } finally {
+ dispatching.remove();
+ queue.remove();
+ }
+ }
+ }
+
+ private static final class Event {
+ private final Object event;
+ private final Iterator<Subscriber> subscribers;
+
+ private Event(Object event, Iterator<Subscriber> subscribers) {
+ this.event = event;
+ this.subscribers = subscribers;
+ }
+ }
+ }
+
+ /**
+ * Implementation of a {@link #legacyAsync()} dispatcher.
+ */
+ private static final class LegacyAsyncDispatcher extends Dispatcher {
+
+ // This dispatcher matches the original dispatch behavior of AsyncEventBus.
+ //
+ // We can't really make any guarantees about the overall dispatch order for this dispatcher in
+ // a multithreaded environment for a couple reasons:
+ //
+ // 1. Subscribers to events posted on different threads can be interleaved with each other
+ // freely. (A event on one thread, B event on another could yield any of
+ // [a1, a2, a3, b1, b2], [a1, b2, a2, a3, b2], [a1, b2, b3, a2, a3], etc.)
+ // 2. It's possible for subscribers to actually be dispatched to in a different order than they
+ // were added to the queue. It's easily possible for one thread to take the head of the
+ // queue, immediately followed by another thread taking the next element in the queue. That
+ // second thread can then dispatch to the subscriber it took before the first thread does.
+ //
+ // All this makes me really wonder if there's any value in queueing here at all. A dispatcher
+ // that simply loops through the subscribers and dispatches the event to each would actually
+ // probably provide a stronger order guarantee, though that order would obviously be different
+ // in some cases.
+
+ /**
+ * Global event queue.
+ */
+ private final ConcurrentLinkedQueue<EventWithSubscriber> queue =
+ Queues.newConcurrentLinkedQueue();
+
+ @Override
+ void dispatch(Object event, Iterator<Subscriber> subscribers) {
+ checkNotNull(event);
+ while (subscribers.hasNext()) {
+ queue.add(new EventWithSubscriber(event, subscribers.next()));
+ }
+
+ EventWithSubscriber e;
+ while ((e = queue.poll()) != null) {
+ e.subscriber.dispatchEvent(e.event);
+ }
+ }
+
+ private static final class EventWithSubscriber {
+ private final Object event;
+ private final Subscriber subscriber;
+
+ private EventWithSubscriber(Object event, Subscriber subscriber) {
+ this.event = event;
+ this.subscriber = subscriber;
+ }
+ }
+ }
+
+ /**
+ * Implementation of {@link #immediate()}.
+ */
+ private static final class ImmediateDispatcher extends Dispatcher {
+ private static final ImmediateDispatcher INSTANCE = new ImmediateDispatcher();
+
+ @Override
+ void dispatch(Object event, Iterator<Subscriber> subscribers) {
+ checkNotNull(event);
+ while (subscribers.hasNext()) {
+ subscribers.next().dispatchEvent(event);
+ }
+ }
+ }
+}
diff --git a/guava/src/com/google/common/eventbus/EventBus.java b/guava/src/com/google/common/eventbus/EventBus.java
index 6f3df55..08aa78d 100644
--- a/guava/src/com/google/common/eventbus/EventBus.java
+++ b/guava/src/com/google/common/eventbus/EventBus.java
@@ -19,25 +19,13 @@ package com.google.common.eventbus;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Throwables;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.SetMultimap;
-import com.google.common.reflect.TypeToken;
-import com.google.common.util.concurrent.UncheckedExecutionException;
+import com.google.common.base.MoreObjects;
+import com.google.common.util.concurrent.MoreExecutors;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.Map.Entry;
-import java.util.Queue;
-import java.util.Set;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.concurrent.Executor;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -104,7 +92,7 @@ import java.util.logging.Logger;
* <p>This class is safe for concurrent use.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/EventBusExplained">
+ * "https://github.com/google/guava/wiki/EventBusExplained">
* {@code EventBus}</a>.
*
* @author Cliff Biffle
@@ -113,56 +101,14 @@ import java.util.logging.Logger;
@Beta
public class EventBus {
- /**
- * A thread-safe cache for flattenHierarchy(). The Class class is immutable. This cache is shared
- * across all EventBus instances, which greatly improves performance if multiple such instances
- * are created and objects of the same class are posted on all of them.
- */
- private static final LoadingCache<Class<?>, Set<Class<?>>> flattenHierarchyCache =
- CacheBuilder.newBuilder()
- .weakKeys()
- .build(new CacheLoader<Class<?>, Set<Class<?>>>() {
- @SuppressWarnings({"unchecked", "rawtypes"}) // safe cast
- @Override
- public Set<Class<?>> load(Class<?> concreteClass) {
- return (Set) TypeToken.of(concreteClass).getTypes().rawTypes();
- }
- });
-
- /**
- * All registered event subscribers, indexed by event type.
- *
- * <p>This SetMultimap is NOT safe for concurrent use; all access should be
- * made after acquiring a read or write lock via {@link #subscribersByTypeLock}.
- */
- private final SetMultimap<Class<?>, EventSubscriber> subscribersByType =
- HashMultimap.create();
- private final ReadWriteLock subscribersByTypeLock = new ReentrantReadWriteLock();
-
- /**
- * Strategy for finding subscriber methods in registered objects. Currently,
- * only the {@link AnnotatedSubscriberFinder} is supported, but this is
- * encapsulated for future expansion.
- */
- private final SubscriberFindingStrategy finder = new AnnotatedSubscriberFinder();
+ private static final Logger logger = Logger.getLogger(EventBus.class.getName());
- /** queues of events for the current thread to dispatch */
- private final ThreadLocal<Queue<EventWithSubscriber>> eventsToDispatch =
- new ThreadLocal<Queue<EventWithSubscriber>>() {
- @Override protected Queue<EventWithSubscriber> initialValue() {
- return new LinkedList<EventWithSubscriber>();
- }
- };
-
- /** true if the current thread is currently dispatching an event */
- private final ThreadLocal<Boolean> isDispatching =
- new ThreadLocal<Boolean>() {
- @Override protected Boolean initialValue() {
- return false;
- }
- };
+ private final String identifier;
+ private final Executor executor;
+ private final SubscriberExceptionHandler exceptionHandler;
- private SubscriberExceptionHandler subscriberExceptionHandler;
+ private final SubscriberRegistry subscribers = new SubscriberRegistry(this);
+ private final Dispatcher dispatcher;
/**
* Creates a new EventBus named "default".
@@ -178,36 +124,68 @@ public class EventBus {
* be a valid Java identifier.
*/
public EventBus(String identifier) {
- this(new LoggingSubscriberExceptionHandler(identifier));
+ this(identifier, MoreExecutors.directExecutor(),
+ Dispatcher.perThreadDispatchQueue(), LoggingHandler.INSTANCE);
}
/**
* Creates a new EventBus with the given {@link SubscriberExceptionHandler}.
*
- * @param subscriberExceptionHandler Handler for subscriber exceptions.
+ * @param exceptionHandler Handler for subscriber exceptions.
* @since 16.0
*/
- public EventBus(SubscriberExceptionHandler subscriberExceptionHandler) {
- this.subscriberExceptionHandler = checkNotNull(subscriberExceptionHandler);
+ public EventBus(SubscriberExceptionHandler exceptionHandler) {
+ this("default",
+ MoreExecutors.directExecutor(), Dispatcher.perThreadDispatchQueue(), exceptionHandler);
+ }
+
+ EventBus(String identifier, Executor executor, Dispatcher dispatcher,
+ SubscriberExceptionHandler exceptionHandler) {
+ this.identifier = checkNotNull(identifier);
+ this.executor = checkNotNull(executor);
+ this.dispatcher = checkNotNull(dispatcher);
+ this.exceptionHandler = checkNotNull(exceptionHandler);
+ }
+
+ /**
+ * Returns the identifier for this event bus.
+ *
+ * @since 19.0
+ */
+ public final String identifier() {
+ return identifier;
+ }
+
+ /**
+ * Returns the default executor this event bus uses for dispatching events to subscribers.
+ */
+ final Executor executor() {
+ return executor;
+ }
+
+ /**
+ * Handles the given exception thrown by a subscriber with the given context.
+ */
+ void handleSubscriberException(Throwable e, SubscriberExceptionContext context) {
+ checkNotNull(e);
+ checkNotNull(context);
+ try {
+ exceptionHandler.handleException(e, context);
+ } catch (Throwable e2) {
+ // if the handler threw an exception... well, just log it
+ logger.log(Level.SEVERE,
+ String.format(Locale.ROOT, "Exception %s thrown while handling exception: %s", e2, e),
+ e2);
+ }
}
/**
* Registers all subscriber methods on {@code object} to receive events.
- * Subscriber methods are selected and classified using this EventBus's
- * {@link SubscriberFindingStrategy}; the default strategy is the
- * {@link AnnotatedSubscriberFinder}.
*
* @param object object whose subscriber methods should be registered.
*/
public void register(Object object) {
- Multimap<Class<?>, EventSubscriber> methodsInListener =
- finder.findAllSubscribers(object);
- subscribersByTypeLock.writeLock().lock();
- try {
- subscribersByType.putAll(methodsInListener);
- } finally {
- subscribersByTypeLock.writeLock().unlock();
- }
+ subscribers.register(object);
}
/**
@@ -217,24 +195,7 @@ public class EventBus {
* @throws IllegalArgumentException if the object was not previously registered.
*/
public void unregister(Object object) {
- Multimap<Class<?>, EventSubscriber> methodsInListener = finder.findAllSubscribers(object);
- for (Entry<Class<?>, Collection<EventSubscriber>> entry :
- methodsInListener.asMap().entrySet()) {
- Class<?> eventType = entry.getKey();
- Collection<EventSubscriber> eventMethodsInListener = entry.getValue();
-
- subscribersByTypeLock.writeLock().lock();
- try {
- Set<EventSubscriber> currentSubscribers = subscribersByType.get(eventType);
- if (!currentSubscribers.containsAll(eventMethodsInListener)) {
- throw new IllegalArgumentException(
- "missing event subscriber for an annotated method. Is " + object + " registered?");
- }
- currentSubscribers.removeAll(eventMethodsInListener);
- } finally {
- subscribersByTypeLock.writeLock().unlock();
- }
- }
+ subscribers.unregister(object);
}
/**
@@ -249,151 +210,46 @@ public class EventBus {
* @param event event to post.
*/
public void post(Object event) {
- Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());
-
- boolean dispatched = false;
- for (Class<?> eventType : dispatchTypes) {
- subscribersByTypeLock.readLock().lock();
- try {
- Set<EventSubscriber> wrappers = subscribersByType.get(eventType);
-
- if (!wrappers.isEmpty()) {
- dispatched = true;
- for (EventSubscriber wrapper : wrappers) {
- enqueueEvent(event, wrapper);
- }
- }
- } finally {
- subscribersByTypeLock.readLock().unlock();
- }
- }
-
- if (!dispatched && !(event instanceof DeadEvent)) {
+ Iterator<Subscriber> eventSubscribers = subscribers.getSubscribers(event);
+ if (eventSubscribers.hasNext()) {
+ dispatcher.dispatch(event, eventSubscribers);
+ } else if (!(event instanceof DeadEvent)) {
+ // the event had no subscribers and was not itself a DeadEvent
post(new DeadEvent(this, event));
}
-
- dispatchQueuedEvents();
}
- /**
- * Queue the {@code event} for dispatch during
- * {@link #dispatchQueuedEvents()}. Events are queued in-order of occurrence
- * so they can be dispatched in the same order.
- */
- void enqueueEvent(Object event, EventSubscriber subscriber) {
- eventsToDispatch.get().offer(new EventWithSubscriber(event, subscriber));
- }
-
- /**
- * Drain the queue of events to be dispatched. As the queue is being drained,
- * new events may be posted to the end of the queue.
- */
- void dispatchQueuedEvents() {
- // don't dispatch if we're already dispatching, that would allow reentrancy
- // and out-of-order events. Instead, leave the events to be dispatched
- // after the in-progress dispatch is complete.
- if (isDispatching.get()) {
- return;
- }
-
- isDispatching.set(true);
- try {
- Queue<EventWithSubscriber> events = eventsToDispatch.get();
- EventWithSubscriber eventWithSubscriber;
- while ((eventWithSubscriber = events.poll()) != null) {
- dispatch(eventWithSubscriber.event, eventWithSubscriber.subscriber);
- }
- } finally {
- isDispatching.remove();
- eventsToDispatch.remove();
- }
- }
-
- /**
- * Dispatches {@code event} to the subscriber in {@code wrapper}. This method
- * is an appropriate override point for subclasses that wish to make
- * event delivery asynchronous.
- *
- * @param event event to dispatch.
- * @param wrapper wrapper that will call the subscriber.
- */
- void dispatch(Object event, EventSubscriber wrapper) {
- try {
- wrapper.handleEvent(event);
- } catch (InvocationTargetException e) {
- try {
- subscriberExceptionHandler.handleException(
- e.getCause(),
- new SubscriberExceptionContext(
- this,
- event,
- wrapper.getSubscriber(),
- wrapper.getMethod()));
- } catch (Throwable t) {
- // If the exception handler throws, log it. There isn't much else to do!
- Logger.getLogger(EventBus.class.getName()).log(Level.SEVERE,
- String.format(
- "Exception %s thrown while handling exception: %s", t,
- e.getCause()),
- t);
- }
- }
- }
-
- /**
- * Flattens a class's type hierarchy into a set of Class objects. The set
- * will include all superclasses (transitively), and all interfaces
- * implemented by these superclasses.
- *
- * @param concreteClass class whose type hierarchy will be retrieved.
- * @return {@code clazz}'s complete type hierarchy, flattened and uniqued.
- */
- @VisibleForTesting
- Set<Class<?>> flattenHierarchy(Class<?> concreteClass) {
- try {
- return flattenHierarchyCache.getUnchecked(concreteClass);
- } catch (UncheckedExecutionException e) {
- throw Throwables.propagate(e.getCause());
- }
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .addValue(identifier)
+ .toString();
}
/**
* Simple logging handler for subscriber exceptions.
*/
- private static final class LoggingSubscriberExceptionHandler
- implements SubscriberExceptionHandler {
-
- /**
- * Logger for event dispatch failures. Named by the fully-qualified name of
- * this class, followed by the identifier provided at construction.
- */
- private final Logger logger;
+ static final class LoggingHandler implements SubscriberExceptionHandler {
+ static final LoggingHandler INSTANCE = new LoggingHandler();
- /**
- * @param identifier a brief name for this bus, for logging purposes. Should
- * be a valid Java identifier.
- */
- public LoggingSubscriberExceptionHandler(String identifier) {
- logger = Logger.getLogger(
- EventBus.class.getName() + "." + checkNotNull(identifier));
+ @Override
+ public void handleException(Throwable exception, SubscriberExceptionContext context) {
+ Logger logger = logger(context);
+ if (logger.isLoggable(Level.SEVERE)) {
+ logger.log(Level.SEVERE, message(context), exception);
+ }
}
- @Override
- public void handleException(Throwable exception,
- SubscriberExceptionContext context) {
- logger.log(Level.SEVERE, "Could not dispatch event: "
- + context.getSubscriber() + " to " + context.getSubscriberMethod(),
- exception.getCause());
+ private static Logger logger(SubscriberExceptionContext context) {
+ return Logger.getLogger(EventBus.class.getName() + "." + context.getEventBus().identifier());
}
- }
- /** simple struct representing an event and it's subscriber */
- static class EventWithSubscriber {
- final Object event;
- final EventSubscriber subscriber;
- public EventWithSubscriber(Object event, EventSubscriber subscriber) {
- this.event = checkNotNull(event);
- this.subscriber = checkNotNull(subscriber);
+ private static String message(SubscriberExceptionContext context) {
+ Method method = context.getSubscriberMethod();
+ return "Exception thrown by subscriber method "
+ + method.getName() + '(' + method.getParameterTypes()[0].getName() + ')'
+ + " on subscriber " + context.getSubscriber()
+ + " when dispatching event: " + context.getEvent();
}
}
}
diff --git a/guava/src/com/google/common/eventbus/EventSubscriber.java b/guava/src/com/google/common/eventbus/EventSubscriber.java
deleted file mode 100644
index 058aeab..0000000
--- a/guava/src/com/google/common/eventbus/EventSubscriber.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2007 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.eventbus;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.common.base.Preconditions;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import javax.annotation.Nullable;
-
-/**
- * Wraps a single-argument subscriber method on a specific object.
- *
- * <p>This class only verifies the suitability of the method and event type if
- * something fails. Callers are expected to verify their uses of this class.
- *
- * <p>Two EventSubscribers are equivalent when they refer to the same method on the
- * same object (not class). This property is used to ensure that no subscriber
- * method is registered more than once.
- *
- * @author Cliff Biffle
- */
-class EventSubscriber {
-
- /** Object sporting the subscriber method. */
- private final Object target;
- /** Subscriber method. */
- private final Method method;
-
- /**
- * Creates a new EventSubscriber to wrap {@code method} on @{code target}.
- *
- * @param target object to which the method applies.
- * @param method subscriber method.
- */
- EventSubscriber(Object target, Method method) {
- Preconditions.checkNotNull(target,
- "EventSubscriber target cannot be null.");
- Preconditions.checkNotNull(method, "EventSubscriber method cannot be null.");
-
- this.target = target;
- this.method = method;
- method.setAccessible(true);
- }
-
- /**
- * Invokes the wrapped subscriber method to handle {@code event}.
- *
- * @param event event to handle
- * @throws InvocationTargetException if the wrapped method throws any
- * {@link Throwable} that is not an {@link Error} ({@code Error} instances are
- * propagated as-is).
- */
- public void handleEvent(Object event) throws InvocationTargetException {
- checkNotNull(event);
- try {
- method.invoke(target, new Object[] { event });
- } catch (IllegalArgumentException e) {
- throw new Error("Method rejected target/argument: " + event, e);
- } catch (IllegalAccessException e) {
- throw new Error("Method became inaccessible: " + event, e);
- } catch (InvocationTargetException e) {
- if (e.getCause() instanceof Error) {
- throw (Error) e.getCause();
- }
- throw e;
- }
- }
-
- @Override public String toString() {
- return "[wrapper " + method + "]";
- }
-
- @Override public int hashCode() {
- final int PRIME = 31;
- return (PRIME + method.hashCode()) * PRIME
- + System.identityHashCode(target);
- }
-
- @Override public boolean equals(@Nullable Object obj) {
- if (obj instanceof EventSubscriber) {
- EventSubscriber that = (EventSubscriber) obj;
- // Use == so that different equal instances will still receive events.
- // We only guard against the case that the same object is registered
- // multiple times
- return target == that.target && method.equals(that.method);
- }
- return false;
- }
-
- public Object getSubscriber() {
- return target;
- }
-
- public Method getMethod() {
- return method;
- }
-}
diff --git a/guava/src/com/google/common/eventbus/Subscriber.java b/guava/src/com/google/common/eventbus/Subscriber.java
new file mode 100644
index 0000000..9e38f08
--- /dev/null
+++ b/guava/src/com/google/common/eventbus/Subscriber.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.eventbus;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.j2objc.annotations.Weak;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.Executor;
+
+import javax.annotation.Nullable;
+
+/**
+ * A subscriber method on a specific object, plus the executor that should be used for
+ * dispatching events to it.
+ *
+ * <p>Two subscribers are equivalent when they refer to the same method on the same object (not
+ * class). This property is used to ensure that no subscriber method is registered more than once.
+ *
+ * @author Colin Decker
+ */
+class Subscriber {
+
+ /**
+ * Creates a {@code Subscriber} for {@code method} on {@code listener}.
+ */
+ static Subscriber create(EventBus bus, Object listener, Method method) {
+ return isDeclaredThreadSafe(method)
+ ? new Subscriber(bus, listener, method)
+ : new SynchronizedSubscriber(bus, listener, method);
+ }
+
+ /** The event bus this subscriber belongs to. */
+ @Weak private EventBus bus;
+
+ /** Object sporting the subscriber method. */
+ @VisibleForTesting
+ final Object target;
+
+ /** Subscriber method. */
+ private final Method method;
+
+ /** Executor to use for dispatching events to this subscriber. */
+ private final Executor executor;
+
+ private Subscriber(EventBus bus, Object target, Method method) {
+ this.bus = bus;
+ this.target = checkNotNull(target);
+ this.method = method;
+ method.setAccessible(true);
+
+ this.executor = bus.executor();
+ }
+
+ /**
+ * Dispatches {@code event} to this subscriber using the proper executor.
+ */
+ final void dispatchEvent(final Object event) {
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ invokeSubscriberMethod(event);
+ } catch (InvocationTargetException e) {
+ bus.handleSubscriberException(e.getCause(), context(event));
+ }
+ }
+ });
+ }
+
+ /**
+ * Invokes the subscriber method. This method can be overridden to make the invocation
+ * synchronized.
+ */
+ @VisibleForTesting
+ void invokeSubscriberMethod(Object event) throws InvocationTargetException {
+ try {
+ method.invoke(target, checkNotNull(event));
+ } catch (IllegalArgumentException e) {
+ throw new Error("Method rejected target/argument: " + event, e);
+ } catch (IllegalAccessException e) {
+ throw new Error("Method became inaccessible: " + event, e);
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof Error) {
+ throw (Error) e.getCause();
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Gets the context for the given event.
+ */
+ private SubscriberExceptionContext context(Object event) {
+ return new SubscriberExceptionContext(bus, event, target, method);
+ }
+
+ @Override
+ public final int hashCode() {
+ return (31 + method.hashCode()) * 31 + System.identityHashCode(target);
+ }
+
+ @Override
+ public final boolean equals(@Nullable Object obj) {
+ if (obj instanceof Subscriber) {
+ Subscriber that = (Subscriber) obj;
+ // Use == so that different equal instances will still receive events.
+ // We only guard against the case that the same object is registered
+ // multiple times
+ return target == that.target && method.equals(that.method);
+ }
+ return false;
+ }
+
+ /**
+ * Checks whether {@code method} is thread-safe, as indicated by the presence of the
+ * {@link AllowConcurrentEvents} annotation.
+ */
+ private static boolean isDeclaredThreadSafe(Method method) {
+ return method.getAnnotation(AllowConcurrentEvents.class) != null;
+ }
+
+ /**
+ * Subscriber that synchronizes invocations of a method to ensure that only one thread may enter
+ * the method at a time.
+ */
+ @VisibleForTesting
+ static final class SynchronizedSubscriber extends Subscriber {
+
+ private SynchronizedSubscriber(EventBus bus, Object target, Method method) {
+ super(bus, target, method);
+ }
+
+ @Override
+ void invokeSubscriberMethod(Object event) throws InvocationTargetException {
+ synchronized (this) {
+ super.invokeSubscriberMethod(event);
+ }
+ }
+ }
+}
diff --git a/guava/src/com/google/common/eventbus/SubscriberFindingStrategy.java b/guava/src/com/google/common/eventbus/SubscriberFindingStrategy.java
deleted file mode 100644
index e238e42..0000000
--- a/guava/src/com/google/common/eventbus/SubscriberFindingStrategy.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2007 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.eventbus;
-
-import com.google.common.collect.Multimap;
-
-/**
- * A method for finding event subscriber methods in objects, for use by
- * {@link EventBus}.
- *
- * @author Cliff Biffle
- */
-interface SubscriberFindingStrategy {
-
- /**
- * Finds all suitable event subscriber methods in {@code source}, organizes them
- * by the type of event they handle, and wraps them in {@link EventSubscriber} instances.
- *
- * @param source object whose subscribers are desired.
- * @return EventSubscriber objects for each subscriber method, organized by event
- * type.
- *
- * @throws IllegalArgumentException if {@code source} is not appropriate for
- * this strategy (in ways that this interface does not define).
- */
- Multimap<Class<?>, EventSubscriber> findAllSubscribers(Object source);
-
-}
diff --git a/guava/src/com/google/common/eventbus/SubscriberRegistry.java b/guava/src/com/google/common/eventbus/SubscriberRegistry.java
new file mode 100644
index 0000000..f0c220d
--- /dev/null
+++ b/guava/src/com/google/common/eventbus/SubscriberRegistry.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.eventbus;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.base.Throwables;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.reflect.TypeToken;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+import com.google.j2objc.annotations.Weak;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import javax.annotation.Nullable;
+
+/**
+ * Registry of subscribers to a single event bus.
+ *
+ * @author Colin Decker
+ */
+final class SubscriberRegistry {
+
+ /**
+ * All registered subscribers, indexed by event type.
+ *
+ * <p>The {@link CopyOnWriteArraySet} values make it easy and relatively lightweight to get an
+ * immutable snapshot of all current subscribers to an event without any locking.
+ */
+ private final ConcurrentMap<Class<?>, CopyOnWriteArraySet<Subscriber>> subscribers =
+ Maps.newConcurrentMap();
+
+ /**
+ * The event bus this registry belongs to.
+ */
+ @Weak private final EventBus bus;
+
+ SubscriberRegistry(EventBus bus) {
+ this.bus = checkNotNull(bus);
+ }
+
+ /**
+ * Registers all subscriber methods on the given listener object.
+ */
+ void register(Object listener) {
+ Multimap<Class<?>, Subscriber> listenerMethods = findAllSubscribers(listener);
+
+ for (Map.Entry<Class<?>, Collection<Subscriber>> entry : listenerMethods.asMap().entrySet()) {
+ Class<?> eventType = entry.getKey();
+ Collection<Subscriber> eventMethodsInListener = entry.getValue();
+
+ CopyOnWriteArraySet<Subscriber> eventSubscribers = subscribers.get(eventType);
+
+ if (eventSubscribers == null) {
+ CopyOnWriteArraySet<Subscriber> newSet = new CopyOnWriteArraySet<Subscriber>();
+ eventSubscribers = MoreObjects.firstNonNull(
+ subscribers.putIfAbsent(eventType, newSet), newSet);
+ }
+
+ eventSubscribers.addAll(eventMethodsInListener);
+ }
+ }
+
+ /**
+ * Unregisters all subscribers on the given listener object.
+ */
+ void unregister(Object listener) {
+ Multimap<Class<?>, Subscriber> listenerMethods = findAllSubscribers(listener);
+
+ for (Map.Entry<Class<?>, Collection<Subscriber>> entry : listenerMethods.asMap().entrySet()) {
+ Class<?> eventType = entry.getKey();
+ Collection<Subscriber> listenerMethodsForType = entry.getValue();
+
+ CopyOnWriteArraySet<Subscriber> currentSubscribers = subscribers.get(eventType);
+ if (currentSubscribers == null || !currentSubscribers.removeAll(listenerMethodsForType)) {
+ // if removeAll returns true, all we really know is that at least one subscriber was
+ // removed... however, barring something very strange we can assume that if at least one
+ // subscriber was removed, all subscribers on listener for that event type were... after
+ // all, the definition of subscribers on a particular class is totally static
+ throw new IllegalArgumentException(
+ "missing event subscriber for an annotated method. Is " + listener + " registered?");
+ }
+
+ // don't try to remove the set if it's empty; that can't be done safely without a lock
+ // anyway, if the set is empty it'll just be wrapping an array of length 0
+ }
+ }
+
+ @VisibleForTesting
+ Set<Subscriber> getSubscribersForTesting(Class<?> eventType) {
+ return MoreObjects.firstNonNull(subscribers.get(eventType), ImmutableSet.<Subscriber>of());
+ }
+
+ /**
+ * Gets an iterator representing an immutable snapshot of all subscribers to the given event at
+ * the time this method is called.
+ */
+ Iterator<Subscriber> getSubscribers(Object event) {
+ ImmutableSet<Class<?>> eventTypes = flattenHierarchy(event.getClass());
+
+ List<Iterator<Subscriber>> subscriberIterators =
+ Lists.newArrayListWithCapacity(eventTypes.size());
+
+ for (Class<?> eventType : eventTypes) {
+ CopyOnWriteArraySet<Subscriber> eventSubscribers = subscribers.get(eventType);
+ if (eventSubscribers != null) {
+ // eager no-copy snapshot
+ subscriberIterators.add(eventSubscribers.iterator());
+ }
+ }
+
+ return Iterators.concat(subscriberIterators.iterator());
+ }
+
+ /**
+ * A thread-safe cache that contains the mapping from each class to all methods in that class and
+ * all super-classes, that are annotated with {@code @Subscribe}. The cache is shared across all
+ * instances of this class; this greatly improves performance if multiple EventBus instances are
+ * created and objects of the same class are registered on all of them.
+ */
+ private static final LoadingCache<Class<?>, ImmutableList<Method>> subscriberMethodsCache =
+ CacheBuilder.newBuilder()
+ .weakKeys()
+ .build(new CacheLoader<Class<?>, ImmutableList<Method>>() {
+ @Override
+ public ImmutableList<Method> load(Class<?> concreteClass) throws Exception {
+ return getAnnotatedMethodsNotCached(concreteClass);
+ }
+ });
+
+ /**
+ * Returns all subscribers for the given listener grouped by the type of event they subscribe to.
+ */
+ private Multimap<Class<?>, Subscriber> findAllSubscribers(Object listener) {
+ Multimap<Class<?>, Subscriber> methodsInListener = HashMultimap.create();
+ Class<?> clazz = listener.getClass();
+ for (Method method : getAnnotatedMethods(clazz)) {
+ Class<?>[] parameterTypes = method.getParameterTypes();
+ Class<?> eventType = parameterTypes[0];
+ methodsInListener.put(eventType, Subscriber.create(bus, listener, method));
+ }
+ return methodsInListener;
+ }
+
+ private static ImmutableList<Method> getAnnotatedMethods(Class<?> clazz) {
+ return subscriberMethodsCache.getUnchecked(clazz);
+ }
+
+ private static ImmutableList<Method> getAnnotatedMethodsNotCached(Class<?> clazz) {
+ Set<? extends Class<?>> supertypes = TypeToken.of(clazz).getTypes().rawTypes();
+ Map<MethodIdentifier, Method> identifiers = Maps.newHashMap();
+ for (Class<?> supertype : supertypes) {
+ for (Method method : supertype.getDeclaredMethods()) {
+ if (method.isAnnotationPresent(Subscribe.class) && !method.isSynthetic()) {
+ // TODO(cgdecker): Should check for a generic parameter type and error out
+ Class<?>[] parameterTypes = method.getParameterTypes();
+ checkArgument(parameterTypes.length == 1,
+ "Method %s has @Subscribe annotation but has %s parameters."
+ + "Subscriber methods must have exactly 1 parameter.",
+ method, parameterTypes.length);
+
+ MethodIdentifier ident = new MethodIdentifier(method);
+ if (!identifiers.containsKey(ident)) {
+ identifiers.put(ident, method);
+ }
+ }
+ }
+ }
+ return ImmutableList.copyOf(identifiers.values());
+ }
+
+ /**
+ * Global cache of classes to their flattened hierarchy of supertypes.
+ */
+ private static final LoadingCache<Class<?>, ImmutableSet<Class<?>>> flattenHierarchyCache =
+ CacheBuilder.newBuilder()
+ .weakKeys()
+ .build(new CacheLoader<Class<?>, ImmutableSet<Class<?>>>() {
+ @SuppressWarnings("RedundantTypeArguments") // <Class<?>> is actually needed to compile
+ @Override
+ public ImmutableSet<Class<?>> load(Class<?> concreteClass) {
+ return ImmutableSet.<Class<?>>copyOf(
+ TypeToken.of(concreteClass).getTypes().rawTypes());
+ }
+ });
+
+ /**
+ * Flattens a class's type hierarchy into a set of {@code Class} objects including all
+ * superclasses (transitively) and all interfaces implemented by these superclasses.
+ */
+ @VisibleForTesting
+ static ImmutableSet<Class<?>> flattenHierarchy(Class<?> concreteClass) {
+ try {
+ return flattenHierarchyCache.getUnchecked(concreteClass);
+ } catch (UncheckedExecutionException e) {
+ throw Throwables.propagate(e.getCause());
+ }
+ }
+
+ private static final class MethodIdentifier {
+
+ private final String name;
+ private final List<Class<?>> parameterTypes;
+
+ MethodIdentifier(Method method) {
+ this.name = method.getName();
+ this.parameterTypes = Arrays.asList(method.getParameterTypes());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name, parameterTypes);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (o instanceof MethodIdentifier) {
+ MethodIdentifier ident = (MethodIdentifier) o;
+ return name.equals(ident.name) && parameterTypes.equals(ident.parameterTypes);
+ }
+ return false;
+ }
+ }
+}
diff --git a/guava/src/com/google/common/eventbus/SynchronizedEventSubscriber.java b/guava/src/com/google/common/eventbus/SynchronizedEventSubscriber.java
deleted file mode 100644
index a074818..0000000
--- a/guava/src/com/google/common/eventbus/SynchronizedEventSubscriber.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2007 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.eventbus;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Wraps a single-argument subscriber method on a specific object, and ensures
- * that only one thread may enter the method at a time.
- *
- * <p>Beyond synchronization, this class behaves identically to
- * {@link EventSubscriber}.
- *
- * @author Cliff Biffle
- */
-final class SynchronizedEventSubscriber extends EventSubscriber {
- /**
- * Creates a new SynchronizedEventSubscriber to wrap {@code method} on
- * {@code target}.
- *
- * @param target object to which the method applies.
- * @param method subscriber method.
- */
- public SynchronizedEventSubscriber(Object target, Method method) {
- super(target, method);
- }
-
- @Override
- public void handleEvent(Object event) throws InvocationTargetException {
- // https://code.google.com/p/guava-libraries/issues/detail?id=1403
- synchronized (this) {
- super.handleEvent(event);
- }
- }
-}
diff --git a/guava/src/com/google/common/eventbus/package-info.java b/guava/src/com/google/common/eventbus/package-info.java
index 84c2d9b..f7b333c 100644
--- a/guava/src/com/google/common/eventbus/package-info.java
+++ b/guava/src/com/google/common/eventbus/package-info.java
@@ -23,7 +23,7 @@
* intended for interprocess communication.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/EventBusExplained">
+ * "https://github.com/google/guava/wiki/EventBusExplained">
* {@code EventBus}</a>.
*
* <h2>One-Minute Guide</h2>
diff --git a/guava/src/com/google/common/hash/AbstractByteHasher.java b/guava/src/com/google/common/hash/AbstractByteHasher.java
index 90210df..dbddf9c 100644
--- a/guava/src/com/google/common/hash/AbstractByteHasher.java
+++ b/guava/src/com/google/common/hash/AbstractByteHasher.java
@@ -34,7 +34,6 @@ import java.nio.ByteOrder;
* @author Colin Decker
*/
abstract class AbstractByteHasher extends AbstractHasher {
-
private final ByteBuffer scratch = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN);
/**
diff --git a/guava/src/com/google/common/hash/AbstractCompositeHashFunction.java b/guava/src/com/google/common/hash/AbstractCompositeHashFunction.java
index 43d5fa9..2122908 100644
--- a/guava/src/com/google/common/hash/AbstractCompositeHashFunction.java
+++ b/guava/src/com/google/common/hash/AbstractCompositeHashFunction.java
@@ -52,98 +52,112 @@ abstract class AbstractCompositeHashFunction extends AbstractStreamingHashFuncti
hashers[i] = functions[i].newHasher();
}
return new Hasher() {
- @Override public Hasher putByte(byte b) {
+ @Override
+ public Hasher putByte(byte b) {
for (Hasher hasher : hashers) {
hasher.putByte(b);
}
return this;
}
- @Override public Hasher putBytes(byte[] bytes) {
+ @Override
+ public Hasher putBytes(byte[] bytes) {
for (Hasher hasher : hashers) {
hasher.putBytes(bytes);
}
return this;
}
- @Override public Hasher putBytes(byte[] bytes, int off, int len) {
+ @Override
+ public Hasher putBytes(byte[] bytes, int off, int len) {
for (Hasher hasher : hashers) {
hasher.putBytes(bytes, off, len);
}
return this;
}
- @Override public Hasher putShort(short s) {
+ @Override
+ public Hasher putShort(short s) {
for (Hasher hasher : hashers) {
hasher.putShort(s);
}
return this;
}
- @Override public Hasher putInt(int i) {
+ @Override
+ public Hasher putInt(int i) {
for (Hasher hasher : hashers) {
hasher.putInt(i);
}
return this;
}
- @Override public Hasher putLong(long l) {
+ @Override
+ public Hasher putLong(long l) {
for (Hasher hasher : hashers) {
hasher.putLong(l);
}
return this;
}
- @Override public Hasher putFloat(float f) {
+ @Override
+ public Hasher putFloat(float f) {
for (Hasher hasher : hashers) {
hasher.putFloat(f);
}
return this;
}
- @Override public Hasher putDouble(double d) {
+ @Override
+ public Hasher putDouble(double d) {
for (Hasher hasher : hashers) {
hasher.putDouble(d);
}
return this;
}
- @Override public Hasher putBoolean(boolean b) {
+ @Override
+ public Hasher putBoolean(boolean b) {
for (Hasher hasher : hashers) {
hasher.putBoolean(b);
}
return this;
}
- @Override public Hasher putChar(char c) {
+ @Override
+ public Hasher putChar(char c) {
for (Hasher hasher : hashers) {
hasher.putChar(c);
}
return this;
}
- @Override public Hasher putUnencodedChars(CharSequence chars) {
+ @Override
+ public Hasher putUnencodedChars(CharSequence chars) {
for (Hasher hasher : hashers) {
hasher.putUnencodedChars(chars);
}
return this;
}
- @Override public Hasher putString(CharSequence chars, Charset charset) {
+ @Override
+ public Hasher putString(CharSequence chars, Charset charset) {
for (Hasher hasher : hashers) {
hasher.putString(chars, charset);
}
return this;
}
- @Override public <T> Hasher putObject(T instance, Funnel<? super T> funnel) {
+ @Override
+ public <T> Hasher putObject(T instance, Funnel<? super T> funnel) {
for (Hasher hasher : hashers) {
hasher.putObject(instance, funnel);
}
return this;
}
- @Override public HashCode hash() {
+ @Override
+ public HashCode hash() {
return makeHash(hashers);
}
};
diff --git a/guava/src/com/google/common/hash/AbstractHasher.java b/guava/src/com/google/common/hash/AbstractHasher.java
index a23786f..df572e5 100644
--- a/guava/src/com/google/common/hash/AbstractHasher.java
+++ b/guava/src/com/google/common/hash/AbstractHasher.java
@@ -24,26 +24,31 @@ import java.nio.charset.Charset;
* @author Dimitris Andreou
*/
abstract class AbstractHasher implements Hasher {
- @Override public final Hasher putBoolean(boolean b) {
+ @Override
+ public final Hasher putBoolean(boolean b) {
return putByte(b ? (byte) 1 : (byte) 0);
}
- @Override public final Hasher putDouble(double d) {
+ @Override
+ public final Hasher putDouble(double d) {
return putLong(Double.doubleToRawLongBits(d));
}
- @Override public final Hasher putFloat(float f) {
+ @Override
+ public final Hasher putFloat(float f) {
return putInt(Float.floatToRawIntBits(f));
}
- @Override public Hasher putUnencodedChars(CharSequence charSequence) {
+ @Override
+ public Hasher putUnencodedChars(CharSequence charSequence) {
for (int i = 0, len = charSequence.length(); i < len; i++) {
putChar(charSequence.charAt(i));
}
return this;
}
- @Override public Hasher putString(CharSequence charSequence, Charset charset) {
+ @Override
+ public Hasher putString(CharSequence charSequence, Charset charset) {
return putBytes(charSequence.toString().getBytes(charset));
}
}
diff --git a/guava/src/com/google/common/hash/AbstractNonStreamingHashFunction.java b/guava/src/com/google/common/hash/AbstractNonStreamingHashFunction.java
index 7c08b70..f1838ee 100644
--- a/guava/src/com/google/common/hash/AbstractNonStreamingHashFunction.java
+++ b/guava/src/com/google/common/hash/AbstractNonStreamingHashFunction.java
@@ -41,11 +41,13 @@ abstract class AbstractNonStreamingHashFunction implements HashFunction {
return new BufferingHasher(expectedInputSize);
}
- @Override public <T> HashCode hashObject(T instance, Funnel<? super T> funnel) {
+ @Override
+ public <T> HashCode hashObject(T instance, Funnel<? super T> funnel) {
return newHasher().putObject(instance, funnel).hash();
}
- @Override public HashCode hashUnencodedChars(CharSequence input) {
+ @Override
+ public HashCode hashUnencodedChars(CharSequence input) {
int len = input.length();
Hasher hasher = newHasher(len * 2);
for (int i = 0; i < len; i++) {
@@ -54,19 +56,23 @@ abstract class AbstractNonStreamingHashFunction implements HashFunction {
return hasher.hash();
}
- @Override public HashCode hashString(CharSequence input, Charset charset) {
+ @Override
+ public HashCode hashString(CharSequence input, Charset charset) {
return hashBytes(input.toString().getBytes(charset));
}
- @Override public HashCode hashInt(int input) {
+ @Override
+ public HashCode hashInt(int input) {
return newHasher(4).putInt(input).hash();
}
- @Override public HashCode hashLong(long input) {
+ @Override
+ public HashCode hashLong(long input) {
return newHasher(8).putLong(input).hash();
}
- @Override public HashCode hashBytes(byte[] input) {
+ @Override
+ public HashCode hashBytes(byte[] input) {
return hashBytes(input, 0, input.length);
}
@@ -106,7 +112,7 @@ abstract class AbstractNonStreamingHashFunction implements HashFunction {
@Override
public Hasher putShort(short s) {
stream.write(s & BOTTOM_BYTE);
- stream.write((s >>> 8) & BOTTOM_BYTE);
+ stream.write((s >>> 8) & BOTTOM_BYTE);
return this;
}
@@ -151,9 +157,11 @@ abstract class AbstractNonStreamingHashFunction implements HashFunction {
ExposedByteArrayOutputStream(int expectedInputSize) {
super(expectedInputSize);
}
+
byte[] byteArray() {
return buf;
}
+
int length() {
return count;
}
diff --git a/guava/src/com/google/common/hash/AbstractStreamingHashFunction.java b/guava/src/com/google/common/hash/AbstractStreamingHashFunction.java
index 302399f..8d8bf9b 100644
--- a/guava/src/com/google/common/hash/AbstractStreamingHashFunction.java
+++ b/guava/src/com/google/common/hash/AbstractStreamingHashFunction.java
@@ -33,35 +33,43 @@ import java.nio.charset.Charset;
* @author Kevin Bourrillion
*/
abstract class AbstractStreamingHashFunction implements HashFunction {
- @Override public <T> HashCode hashObject(T instance, Funnel<? super T> funnel) {
+ @Override
+ public <T> HashCode hashObject(T instance, Funnel<? super T> funnel) {
return newHasher().putObject(instance, funnel).hash();
}
- @Override public HashCode hashUnencodedChars(CharSequence input) {
+ @Override
+ public HashCode hashUnencodedChars(CharSequence input) {
return newHasher().putUnencodedChars(input).hash();
}
- @Override public HashCode hashString(CharSequence input, Charset charset) {
+ @Override
+ public HashCode hashString(CharSequence input, Charset charset) {
return newHasher().putString(input, charset).hash();
}
- @Override public HashCode hashInt(int input) {
+ @Override
+ public HashCode hashInt(int input) {
return newHasher().putInt(input).hash();
}
- @Override public HashCode hashLong(long input) {
+ @Override
+ public HashCode hashLong(long input) {
return newHasher().putLong(input).hash();
}
- @Override public HashCode hashBytes(byte[] input) {
+ @Override
+ public HashCode hashBytes(byte[] input) {
return newHasher().putBytes(input).hash();
}
- @Override public HashCode hashBytes(byte[] input, int off, int len) {
+ @Override
+ public HashCode hashBytes(byte[] input, int off, int len) {
return newHasher().putBytes(input, off, len).hash();
}
- @Override public Hasher newHasher(int expectedInputSize) {
+ @Override
+ public Hasher newHasher(int expectedInputSize) {
Preconditions.checkArgument(expectedInputSize >= 0);
return newHasher();
}
@@ -109,9 +117,8 @@ abstract class AbstractStreamingHashFunction implements HashFunction {
checkArgument(bufferSize % chunkSize == 0);
// TODO(user): benchmark performance difference with longer buffer
- this.buffer = ByteBuffer
- .allocate(bufferSize + 7) // always space for a single primitive
- .order(ByteOrder.LITTLE_ENDIAN);
+ // always space for a single primitive
+ this.buffer = ByteBuffer.allocate(bufferSize + 7).order(ByteOrder.LITTLE_ENDIAN);
this.bufferSize = bufferSize;
this.chunkSize = chunkSize;
}
@@ -183,6 +190,16 @@ abstract class AbstractStreamingHashFunction implements HashFunction {
return this;
}
+ /*
+ * Note: hashString(CharSequence, Charset) is intentionally not overridden.
+ *
+ * While intuitively, using CharsetEncoder to encode the CharSequence directly to the buffer
+ * (or even to an intermediate buffer) should be considerably more efficient than potentially
+ * copying the CharSequence to a String and then calling getBytes(Charset) on that String, in
+ * reality there are optimizations that make the getBytes(Charset) approach considerably faster,
+ * at least for commonly used charsets like UTF-8.
+ */
+
@Override
public final Hasher putByte(byte b) {
buffer.put(b);
diff --git a/guava/src/com/google/common/hash/BloomFilter.java b/guava/src/com/google/common/hash/BloomFilter.java
index 1c04f8d..4c70575 100644
--- a/guava/src/com/google/common/hash/BloomFilter.java
+++ b/guava/src/com/google/common/hash/BloomFilter.java
@@ -32,6 +32,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -108,12 +109,11 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
/**
* Creates a BloomFilter.
*/
- private BloomFilter(BitArray bits, int numHashFunctions, Funnel<? super T> funnel,
- Strategy strategy) {
- checkArgument(numHashFunctions > 0,
- "numHashFunctions (%s) must be > 0", numHashFunctions);
- checkArgument(numHashFunctions <= 255,
- "numHashFunctions (%s) must be <= 255", numHashFunctions);
+ private BloomFilter(
+ BitArray bits, int numHashFunctions, Funnel<? super T> funnel, Strategy strategy) {
+ checkArgument(numHashFunctions > 0, "numHashFunctions (%s) must be > 0", numHashFunctions);
+ checkArgument(
+ numHashFunctions <= 255, "numHashFunctions (%s) must be <= 255", numHashFunctions);
this.bits = checkNotNull(bits);
this.numHashFunctions = numHashFunctions;
this.funnel = checkNotNull(funnel);
@@ -126,6 +126,7 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
*
* @since 12.0
*/
+ @CheckReturnValue
public BloomFilter<T> copy() {
return new BloomFilter<T>(bits.copy(), numHashFunctions, funnel, strategy);
}
@@ -134,6 +135,7 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
* Returns {@code true} if the element <i>might</i> have been put in this Bloom filter,
* {@code false} if this is <i>definitely</i> not the case.
*/
+ @CheckReturnValue
public boolean mightContain(T object) {
return strategy.mightContain(object, funnel, numHashFunctions, bits);
}
@@ -144,6 +146,7 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
*/
@Deprecated
@Override
+ @CheckReturnValue
public boolean apply(T input) {
return mightContain(input);
}
@@ -175,6 +178,7 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
*
* @since 14.0 (since 11.0 as expectedFalsePositiveProbability())
*/
+ @CheckReturnValue
public double expectedFpp() {
// You down with FPP? (Yeah you know me!) Who's down with FPP? (Every last homie!)
return Math.pow((double) bits.bitCount() / bitSize(), numHashFunctions);
@@ -183,7 +187,8 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
/**
* Returns the number of bits in the underlying bit array.
*/
- @VisibleForTesting long bitSize() {
+ @VisibleForTesting
+ long bitSize() {
return bits.bitSize();
}
@@ -202,13 +207,14 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
* @param that The bloom filter to check for compatibility.
* @since 15.0
*/
+ @CheckReturnValue
public boolean isCompatible(BloomFilter<T> that) {
checkNotNull(that);
- return (this != that) &&
- (this.numHashFunctions == that.numHashFunctions) &&
- (this.bitSize() == that.bitSize()) &&
- (this.strategy.equals(that.strategy)) &&
- (this.funnel.equals(that.funnel));
+ return (this != that)
+ && (this.numHashFunctions == that.numHashFunctions)
+ && (this.bitSize() == that.bitSize())
+ && (this.strategy.equals(that.strategy))
+ && (this.funnel.equals(that.funnel));
}
/**
@@ -224,18 +230,26 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
public void putAll(BloomFilter<T> that) {
checkNotNull(that);
checkArgument(this != that, "Cannot combine a BloomFilter with itself.");
- checkArgument(this.numHashFunctions == that.numHashFunctions,
+ checkArgument(
+ this.numHashFunctions == that.numHashFunctions,
"BloomFilters must have the same number of hash functions (%s != %s)",
- this.numHashFunctions, that.numHashFunctions);
- checkArgument(this.bitSize() == that.bitSize(),
+ this.numHashFunctions,
+ that.numHashFunctions);
+ checkArgument(
+ this.bitSize() == that.bitSize(),
"BloomFilters must have the same size underlying bit arrays (%s != %s)",
- this.bitSize(), that.bitSize());
- checkArgument(this.strategy.equals(that.strategy),
+ this.bitSize(),
+ that.bitSize());
+ checkArgument(
+ this.strategy.equals(that.strategy),
"BloomFilters must have equal strategies (%s != %s)",
- this.strategy, that.strategy);
- checkArgument(this.funnel.equals(that.funnel),
+ this.strategy,
+ that.strategy);
+ checkArgument(
+ this.funnel.equals(that.funnel),
"BloomFilters must have equal funnels (%s != %s)",
- this.funnel, that.funnel);
+ this.funnel,
+ that.funnel);
this.bits.putAll(that.bits);
}
@@ -259,8 +273,32 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
return Objects.hashCode(numHashFunctions, funnel, strategy, bits);
}
- private static final Strategy DEFAULT_STRATEGY =
- BloomFilterStrategies.MURMUR128_MITZ_64;
+ /**
+ * Creates a {@link BloomFilter BloomFilter<T>} with the expected number of
+ * insertions and expected false positive probability.
+ *
+ * <p>Note that overflowing a {@code BloomFilter} with significantly more elements
+ * than specified, will result in its saturation, and a sharp deterioration of its
+ * false positive probability.
+ *
+ * <p>The constructed {@code BloomFilter<T>} will be serializable if the provided
+ * {@code Funnel<T>} is.
+ *
+ * <p>It is recommended that the funnel be implemented as a Java enum. This has the
+ * benefit of ensuring proper serialization and deserialization, which is important
+ * since {@link #equals} also relies on object identity of funnels.
+ *
+ * @param funnel the funnel of T's that the constructed {@code BloomFilter<T>} will use
+ * @param expectedInsertions the number of expected insertions to the constructed
+ * {@code BloomFilter<T>}; must be positive
+ * @param fpp the desired false positive probability (must be positive and less than 1.0)
+ * @return a {@code BloomFilter}
+ */
+ @CheckReturnValue
+ public static <T> BloomFilter<T> create(
+ Funnel<? super T> funnel, int expectedInsertions, double fpp) {
+ return create(funnel, (long) expectedInsertions, fpp);
+ }
/**
* Creates a {@link BloomFilter BloomFilter<T>} with the expected number of
@@ -282,18 +320,20 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
* {@code BloomFilter<T>}; must be positive
* @param fpp the desired false positive probability (must be positive and less than 1.0)
* @return a {@code BloomFilter}
+ * @since 19.0
*/
+ @CheckReturnValue
public static <T> BloomFilter<T> create(
- Funnel<? super T> funnel, int expectedInsertions /* n */, double fpp) {
- return create(funnel, expectedInsertions, fpp, DEFAULT_STRATEGY);
+ Funnel<? super T> funnel, long expectedInsertions, double fpp) {
+ return create(funnel, expectedInsertions, fpp, BloomFilterStrategies.MURMUR128_MITZ_64);
}
@VisibleForTesting
static <T> BloomFilter<T> create(
- Funnel<? super T> funnel, int expectedInsertions /* n */, double fpp, Strategy strategy) {
+ Funnel<? super T> funnel, long expectedInsertions, double fpp, Strategy strategy) {
checkNotNull(funnel);
- checkArgument(expectedInsertions >= 0, "Expected insertions (%s) must be >= 0",
- expectedInsertions);
+ checkArgument(
+ expectedInsertions >= 0, "Expected insertions (%s) must be >= 0", expectedInsertions);
checkArgument(fpp > 0.0, "False positive probability (%s) must be > 0.0", fpp);
checkArgument(fpp < 1.0, "False positive probability (%s) must be < 1.0", fpp);
checkNotNull(strategy);
@@ -327,13 +367,43 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
* <p>The constructed {@code BloomFilter<T>} will be serializable if the provided
* {@code Funnel<T>} is.
*
+ * <p>It is recommended that the funnel be implemented as a Java enum. This has the
+ * benefit of ensuring proper serialization and deserialization, which is important
+ * since {@link #equals} also relies on object identity of funnels.
+ *
* @param funnel the funnel of T's that the constructed {@code BloomFilter<T>} will use
* @param expectedInsertions the number of expected insertions to the constructed
* {@code BloomFilter<T>}; must be positive
* @return a {@code BloomFilter}
*/
- public static <T> BloomFilter<T> create(
- Funnel<? super T> funnel, int expectedInsertions /* n */) {
+ @CheckReturnValue
+ public static <T> BloomFilter<T> create(Funnel<? super T> funnel, int expectedInsertions) {
+ return create(funnel, (long) expectedInsertions);
+ }
+
+ /**
+ * Creates a {@link BloomFilter BloomFilter<T>} with the expected number of
+ * insertions and a default expected false positive probability of 3%.
+ *
+ * <p>Note that overflowing a {@code BloomFilter} with significantly more elements
+ * than specified, will result in its saturation, and a sharp deterioration of its
+ * false positive probability.
+ *
+ * <p>The constructed {@code BloomFilter<T>} will be serializable if the provided
+ * {@code Funnel<T>} is.
+ *
+ * <p>It is recommended that the funnel be implemented as a Java enum. This has the
+ * benefit of ensuring proper serialization and deserialization, which is important
+ * since {@link #equals} also relies on object identity of funnels.
+ *
+ * @param funnel the funnel of T's that the constructed {@code BloomFilter<T>} will use
+ * @param expectedInsertions the number of expected insertions to the constructed
+ * {@code BloomFilter<T>}; must be positive
+ * @return a {@code BloomFilter}
+ * @since 19.0
+ */
+ @CheckReturnValue
+ public static <T> BloomFilter<T> create(Funnel<? super T> funnel, long expectedInsertions) {
return create(funnel, expectedInsertions, 0.03); // FYI, for 3%, we always get 5 hash functions
}
@@ -399,9 +469,11 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
this.funnel = bf.funnel;
this.strategy = bf.strategy;
}
+
Object readResolve() {
return new BloomFilter<T>(new BitArray(data), numHashFunctions, funnel, strategy);
}
+
private static final long serialVersionUID = 1;
}
@@ -441,6 +513,7 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
* not appear to be a BloomFilter serialized using the
* {@linkplain #writeTo(OutputStream)} method.
*/
+ @CheckReturnValue
public static <T> BloomFilter<T> readFrom(InputStream in, Funnel<T> funnel) throws IOException {
checkNotNull(in, "InputStream");
checkNotNull(funnel, "Funnel");
@@ -465,9 +538,9 @@ public final class BloomFilter<T> implements Predicate<T>, Serializable {
} catch (RuntimeException e) {
IOException ioException = new IOException(
"Unable to deserialize BloomFilter from InputStream."
- + " strategyOrdinal: " + strategyOrdinal
- + " numHashFunctions: " + numHashFunctions
- + " dataLength: " + dataLength);
+ + " strategyOrdinal: " + strategyOrdinal
+ + " numHashFunctions: " + numHashFunctions
+ + " dataLength: " + dataLength);
ioException.initCause(e);
throw ioException;
}
diff --git a/guava/src/com/google/common/hash/BloomFilterStrategies.java b/guava/src/com/google/common/hash/BloomFilterStrategies.java
index 3dd8535..2d464cc 100644
--- a/guava/src/com/google/common/hash/BloomFilterStrategies.java
+++ b/guava/src/com/google/common/hash/BloomFilterStrategies.java
@@ -42,8 +42,9 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
* performance of a Bloom filter (yet only needs two 32bit hash functions).
*/
MURMUR128_MITZ_32() {
- @Override public <T> boolean put(T object, Funnel<? super T> funnel,
- int numHashFunctions, BitArray bits) {
+ @Override
+ public <T> boolean put(
+ T object, Funnel<? super T> funnel, int numHashFunctions, BitArray bits) {
long bitSize = bits.bitSize();
long hash64 = Hashing.murmur3_128().hashObject(object, funnel).asLong();
int hash1 = (int) hash64;
@@ -61,8 +62,9 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
return bitsChanged;
}
- @Override public <T> boolean mightContain(T object, Funnel<? super T> funnel,
- int numHashFunctions, BitArray bits) {
+ @Override
+ public <T> boolean mightContain(
+ T object, Funnel<? super T> funnel, int numHashFunctions, BitArray bits) {
long bitSize = bits.bitSize();
long hash64 = Hashing.murmur3_128().hashObject(object, funnel).asLong();
int hash1 = (int) hash64;
@@ -89,8 +91,8 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
*/
MURMUR128_MITZ_64() {
@Override
- public <T> boolean put(T object, Funnel<? super T> funnel,
- int numHashFunctions, BitArray bits) {
+ public <T> boolean put(
+ T object, Funnel<? super T> funnel, int numHashFunctions, BitArray bits) {
long bitSize = bits.bitSize();
byte[] bytes = Hashing.murmur3_128().hashObject(object, funnel).getBytesInternal();
long hash1 = lowerEight(bytes);
@@ -107,8 +109,8 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
}
@Override
- public <T> boolean mightContain(T object, Funnel<? super T> funnel,
- int numHashFunctions, BitArray bits) {
+ public <T> boolean mightContain(
+ T object, Funnel<? super T> funnel, int numHashFunctions, BitArray bits) {
long bitSize = bits.bitSize();
byte[] bytes = Hashing.murmur3_128().hashObject(object, funnel).getBytesInternal();
long hash1 = lowerEight(bytes);
@@ -186,8 +188,11 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
/** Combines the two BitArrays using bitwise OR. */
void putAll(BitArray array) {
- checkArgument(data.length == array.data.length,
- "BitArrays must be of equal length (%s != %s)", data.length, array.data.length);
+ checkArgument(
+ data.length == array.data.length,
+ "BitArrays must be of equal length (%s != %s)",
+ data.length,
+ array.data.length);
bitCount = 0;
for (int i = 0; i < data.length; i++) {
data[i] |= array.data[i];
@@ -195,7 +200,8 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
}
}
- @Override public boolean equals(Object o) {
+ @Override
+ public boolean equals(Object o) {
if (o instanceof BitArray) {
BitArray bitArray = (BitArray) o;
return Arrays.equals(data, bitArray.data);
@@ -203,7 +209,8 @@ enum BloomFilterStrategies implements BloomFilter.Strategy {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Arrays.hashCode(data);
}
}
diff --git a/guava/src/com/google/common/hash/ChecksumHashFunction.java b/guava/src/com/google/common/hash/ChecksumHashFunction.java
index c99ccb7..ebcc1d6 100644
--- a/guava/src/com/google/common/hash/ChecksumHashFunction.java
+++ b/guava/src/com/google/common/hash/ChecksumHashFunction.java
@@ -28,7 +28,6 @@ import java.util.zip.Checksum;
* @author Colin Decker
*/
final class ChecksumHashFunction extends AbstractStreamingHashFunction implements Serializable {
-
private final Supplier<? extends Checksum> checksumSupplier;
private final int bits;
private final String toString;
@@ -59,7 +58,6 @@ final class ChecksumHashFunction extends AbstractStreamingHashFunction implement
* Hasher that updates a checksum.
*/
private final class ChecksumHasher extends AbstractByteHasher {
-
private final Checksum checksum;
private ChecksumHasher(Checksum checksum) {
diff --git a/guava/src/com/google/common/hash/Crc32cHashFunction.java b/guava/src/com/google/common/hash/Crc32cHashFunction.java
index dd9d7f3..a3530b7 100644
--- a/guava/src/com/google/common/hash/Crc32cHashFunction.java
+++ b/guava/src/com/google/common/hash/Crc32cHashFunction.java
@@ -21,7 +21,6 @@ package com.google.common.hash;
* @author Kurt Alfred Kluever
*/
final class Crc32cHashFunction extends AbstractStreamingHashFunction {
-
@Override
public int bits() {
return 32;
diff --git a/guava/src/com/google/common/hash/Funnels.java b/guava/src/com/google/common/hash/Funnels.java
index 08b814a..627683d 100644
--- a/guava/src/com/google/common/hash/Funnels.java
+++ b/guava/src/com/google/common/hash/Funnels.java
@@ -21,6 +21,7 @@ import java.io.OutputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -30,6 +31,7 @@ import javax.annotation.Nullable;
* @since 11.0
*/
@Beta
+ at CheckReturnValue
public final class Funnels {
private Funnels() {}
@@ -47,7 +49,8 @@ public final class Funnels {
into.putBytes(from);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Funnels.byteArrayFunnel()";
}
}
@@ -70,7 +73,8 @@ public final class Funnels {
into.putUnencodedChars(from);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Funnels.unencodedCharsFunnel()";
}
}
@@ -96,11 +100,13 @@ public final class Funnels {
into.putString(from, charset);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Funnels.stringFunnel(" + charset.name() + ")";
}
- @Override public boolean equals(@Nullable Object o) {
+ @Override
+ public boolean equals(@Nullable Object o) {
if (o instanceof StringCharsetFunnel) {
StringCharsetFunnel funnel = (StringCharsetFunnel) o;
return this.charset.equals(funnel.charset);
@@ -108,7 +114,8 @@ public final class Funnels {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return StringCharsetFunnel.class.hashCode() ^ charset.hashCode();
}
@@ -126,7 +133,7 @@ public final class Funnels {
private Object readResolve() {
return stringFunnel(Charset.forName(charsetCanonicalName));
}
-
+
private static final long serialVersionUID = 0;
}
}
@@ -147,7 +154,8 @@ public final class Funnels {
into.putInt(from);
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Funnels.integerFunnel()";
}
}
@@ -175,11 +183,13 @@ public final class Funnels {
}
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Funnels.sequentialFunnel(" + elementFunnel + ")";
}
- @Override public boolean equals(@Nullable Object o) {
+ @Override
+ public boolean equals(@Nullable Object o) {
if (o instanceof SequentialFunnel) {
SequentialFunnel<?> funnel = (SequentialFunnel<?>) o;
return elementFunnel.equals(funnel.elementFunnel);
@@ -187,65 +197,72 @@ public final class Funnels {
return false;
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return SequentialFunnel.class.hashCode() ^ elementFunnel.hashCode();
}
}
/**
* Returns a funnel for longs.
- *
+ *
* @since 13.0
*/
public static Funnel<Long> longFunnel() {
return LongFunnel.INSTANCE;
}
-
+
private enum LongFunnel implements Funnel<Long> {
INSTANCE;
-
+
public void funnel(Long from, PrimitiveSink into) {
into.putLong(from);
}
-
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Funnels.longFunnel()";
}
}
-
+
/**
* Wraps a {@code PrimitiveSink} as an {@link OutputStream}, so it is easy to
* {@link Funnel#funnel funnel} an object to a {@code PrimitiveSink}
- * if there is already a way to write the contents of the object to an {@code OutputStream}.
- *
+ * if there is already a way to write the contents of the object to an {@code OutputStream}.
+ *
* <p>The {@code close} and {@code flush} methods of the returned {@code OutputStream}
* do nothing, and no method throws {@code IOException}.
- *
+ *
* @since 13.0
*/
public static OutputStream asOutputStream(PrimitiveSink sink) {
return new SinkAsStream(sink);
}
-
+
private static class SinkAsStream extends OutputStream {
final PrimitiveSink sink;
+
SinkAsStream(PrimitiveSink sink) {
this.sink = Preconditions.checkNotNull(sink);
}
-
- @Override public void write(int b) {
+
+ @Override
+ public void write(int b) {
sink.putByte((byte) b);
}
- @Override public void write(byte[] bytes) {
+ @Override
+ public void write(byte[] bytes) {
sink.putBytes(bytes);
}
- @Override public void write(byte[] bytes, int off, int len) {
+ @Override
+ public void write(byte[] bytes, int off, int len) {
sink.putBytes(bytes, off, len);
}
-
- @Override public String toString() {
+
+ @Override
+ public String toString() {
return "Funnels.asOutputStream(" + sink + ")";
}
}
diff --git a/guava/src/com/google/common/hash/HashCode.java b/guava/src/com/google/common/hash/HashCode.java
index 7ee228d..7115b28 100644
--- a/guava/src/com/google/common/hash/HashCode.java
+++ b/guava/src/com/google/common/hash/HashCode.java
@@ -24,8 +24,8 @@ import com.google.common.primitives.Ints;
import com.google.common.primitives.UnsignedInts;
import java.io.Serializable;
-import java.security.MessageDigest;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -42,6 +42,7 @@ public abstract class HashCode {
/**
* Returns the number of bits in this hash code; a positive multiple of 8.
*/
+ @CheckReturnValue
public abstract int bits();
/**
@@ -50,6 +51,7 @@ public abstract class HashCode {
*
* @throws IllegalStateException if {@code bits() < 32}
*/
+ @CheckReturnValue
public abstract int asInt();
/**
@@ -58,6 +60,7 @@ public abstract class HashCode {
*
* @throws IllegalStateException if {@code bits() < 64}
*/
+ @CheckReturnValue
public abstract long asLong();
/**
@@ -67,6 +70,7 @@ public abstract class HashCode {
*
* @since 14.0 (since 11.0 as {@code Hashing.padToLong(HashCode)})
*/
+ @CheckReturnValue
public abstract long padToLong();
/**
@@ -75,6 +79,7 @@ public abstract class HashCode {
* returned by this method.
*/
// TODO(user): consider ByteString here, when that is available
+ @CheckReturnValue
public abstract byte[] asBytes();
/**
@@ -116,6 +121,7 @@ public abstract class HashCode {
*
* @since 15.0 (since 12.0 in HashCodes)
*/
+ @CheckReturnValue
public static HashCode fromInt(int hash) {
return new IntHashCode(hash);
}
@@ -135,10 +141,11 @@ public abstract class HashCode {
@Override
public byte[] asBytes() {
return new byte[] {
- (byte) hash,
- (byte) (hash >> 8),
- (byte) (hash >> 16),
- (byte) (hash >> 24)};
+ (byte) hash,
+ (byte) (hash >> 8),
+ (byte) (hash >> 16),
+ (byte) (hash >> 24)
+ };
}
@Override
@@ -163,7 +170,8 @@ public abstract class HashCode {
}
}
- @Override boolean equalsSameBits(HashCode that) {
+ @Override
+ boolean equalsSameBits(HashCode that) {
return hash == that.asInt();
}
@@ -176,6 +184,7 @@ public abstract class HashCode {
*
* @since 15.0 (since 12.0 in HashCodes)
*/
+ @CheckReturnValue
public static HashCode fromLong(long hash) {
return new LongHashCode(hash);
}
@@ -195,14 +204,15 @@ public abstract class HashCode {
@Override
public byte[] asBytes() {
return new byte[] {
- (byte) hash,
- (byte) (hash >> 8),
- (byte) (hash >> 16),
- (byte) (hash >> 24),
- (byte) (hash >> 32),
- (byte) (hash >> 40),
- (byte) (hash >> 48),
- (byte) (hash >> 56)};
+ (byte) hash,
+ (byte) (hash >> 8),
+ (byte) (hash >> 16),
+ (byte) (hash >> 24),
+ (byte) (hash >> 32),
+ (byte) (hash >> 40),
+ (byte) (hash >> 48),
+ (byte) (hash >> 56)
+ };
}
@Override
@@ -241,6 +251,7 @@ public abstract class HashCode {
*
* @since 15.0 (since 12.0 in HashCodes)
*/
+ @CheckReturnValue
public static HashCode fromBytes(byte[] bytes) {
checkArgument(bytes.length >= 1, "A HashCode must contain at least 1 byte.");
return fromBytesNoCopy(bytes.clone());
@@ -273,8 +284,10 @@ public abstract class HashCode {
@Override
public int asInt() {
- checkState(bytes.length >= 4,
- "HashCode#asInt() requires >= 4 bytes (it only has %s bytes).", bytes.length);
+ checkState(
+ bytes.length >= 4,
+ "HashCode#asInt() requires >= 4 bytes (it only has %s bytes).",
+ bytes.length);
return (bytes[0] & 0xFF)
| ((bytes[1] & 0xFF) << 8)
| ((bytes[2] & 0xFF) << 16)
@@ -283,8 +296,10 @@ public abstract class HashCode {
@Override
public long asLong() {
- checkState(bytes.length >= 8,
- "HashCode#asLong() requires >= 8 bytes (it only has %s bytes).", bytes.length);
+ checkState(
+ bytes.length >= 8,
+ "HashCode#asLong() requires >= 8 bytes (it only has %s bytes).",
+ bytes.length);
return padToLong();
}
@@ -309,7 +324,17 @@ public abstract class HashCode {
@Override
boolean equalsSameBits(HashCode that) {
- return MessageDigest.isEqual(bytes, that.getBytesInternal());
+ // We don't use MessageDigest.isEqual() here because its contract does not guarantee
+ // constant-time evaluation (no short-circuiting).
+ if (this.bytes.length != that.getBytesInternal().length) {
+ return false;
+ }
+
+ boolean areEqual = true;
+ for (int i = 0; i < this.bytes.length; i++) {
+ areEqual &= (this.bytes[i] == that.getBytesInternal()[i]);
+ }
+ return areEqual;
}
private static final long serialVersionUID = 0;
@@ -325,11 +350,14 @@ public abstract class HashCode {
*
* @since 15.0
*/
+ @CheckReturnValue
public static HashCode fromString(String string) {
- checkArgument(string.length() >= 2,
- "input string (%s) must have at least 2 characters", string);
- checkArgument(string.length() % 2 == 0,
- "input string (%s) must have an even number of characters", string);
+ checkArgument(
+ string.length() >= 2, "input string (%s) must have at least 2 characters", string);
+ checkArgument(
+ string.length() % 2 == 0,
+ "input string (%s) must have an even number of characters",
+ string);
byte[] bytes = new byte[string.length() / 2];
for (int i = 0; i < string.length(); i += 2) {
@@ -350,6 +378,13 @@ public abstract class HashCode {
throw new IllegalArgumentException("Illegal hexadecimal character: " + ch);
}
+ /**
+ * Returns {@code true} if {@code object} is a {@link HashCode} instance with the identical byte
+ * representation to this hash code.
+ *
+ * <p>Security note:</p> this method uses a constant-time (not short-circuiting) implementation
+ * to protect against <a href="http://en.wikipedia.org/wiki/Timing_attack">timing attacks</a>.
+ */
@Override
public final boolean equals(@Nullable Object object) {
if (object instanceof HashCode) {
@@ -372,7 +407,7 @@ public abstract class HashCode {
return asInt();
}
// If we have less than 4 bytes, use them all.
- byte[] bytes = asBytes();
+ byte[] bytes = getBytesInternal();
int val = (bytes[0] & 0xFF);
for (int i = 1; i < bytes.length; i++) {
val |= ((bytes[i] & 0xFF) << (i * 8));
@@ -393,7 +428,7 @@ public abstract class HashCode {
*/
@Override
public final String toString() {
- byte[] bytes = asBytes();
+ byte[] bytes = getBytesInternal();
StringBuilder sb = new StringBuilder(2 * bytes.length);
for (byte b : bytes) {
sb.append(hexDigits[(b >> 4) & 0xf]).append(hexDigits[b & 0xf]);
diff --git a/guava/src/com/google/common/hash/Hasher.java b/guava/src/com/google/common/hash/Hasher.java
index 2dd4a9a..df9c6bc 100644
--- a/guava/src/com/google/common/hash/Hasher.java
+++ b/guava/src/com/google/common/hash/Hasher.java
@@ -18,6 +18,8 @@ import com.google.common.annotations.Beta;
import java.nio.charset.Charset;
+import javax.annotation.CheckReturnValue;
+
/**
* A {@link PrimitiveSink} that can compute a hash code after reading the input. Each hasher should
* translate all multibyte values ({@link #putInt(int)}, {@link #putLong(long)}, etc) to bytes
@@ -51,28 +53,44 @@ import java.nio.charset.Charset;
*/
@Beta
public interface Hasher extends PrimitiveSink {
- @Override Hasher putByte(byte b);
- @Override Hasher putBytes(byte[] bytes);
- @Override Hasher putBytes(byte[] bytes, int off, int len);
- @Override Hasher putShort(short s);
- @Override Hasher putInt(int i);
- @Override Hasher putLong(long l);
+ @Override
+ Hasher putByte(byte b);
+
+ @Override
+ Hasher putBytes(byte[] bytes);
+
+ @Override
+ Hasher putBytes(byte[] bytes, int off, int len);
+
+ @Override
+ Hasher putShort(short s);
+
+ @Override
+ Hasher putInt(int i);
+
+ @Override
+ Hasher putLong(long l);
/**
* Equivalent to {@code putInt(Float.floatToRawIntBits(f))}.
*/
- @Override Hasher putFloat(float f);
+ @Override
+ Hasher putFloat(float f);
/**
* Equivalent to {@code putLong(Double.doubleToRawLongBits(d))}.
*/
- @Override Hasher putDouble(double d);
+ @Override
+ Hasher putDouble(double d);
/**
* Equivalent to {@code putByte(b ? (byte) 1 : (byte) 0)}.
*/
- @Override Hasher putBoolean(boolean b);
- @Override Hasher putChar(char c);
+ @Override
+ Hasher putBoolean(boolean b);
+
+ @Override
+ Hasher putChar(char c);
/**
* Equivalent to processing each {@code char} value in the {@code CharSequence}, in order.
@@ -80,12 +98,14 @@ public interface Hasher extends PrimitiveSink {
*
* @since 15.0 (since 11.0 as putString(CharSequence)).
*/
- @Override Hasher putUnencodedChars(CharSequence charSequence);
+ @Override
+ Hasher putUnencodedChars(CharSequence charSequence);
/**
* Equivalent to {@code putBytes(charSequence.toString().getBytes(charset))}.
*/
- @Override Hasher putString(CharSequence charSequence, Charset charset);
+ @Override
+ Hasher putString(CharSequence charSequence, Charset charset);
/**
* A simple convenience for {@code funnel.funnel(object, this)}.
@@ -96,5 +116,16 @@ public interface Hasher extends PrimitiveSink {
* Computes a hash code based on the data that have been provided to this hasher. The result is
* unspecified if this method is called more than once on the same instance.
*/
+ @CheckReturnValue
HashCode hash();
+
+ /**
+ * {@inheritDoc}
+ *
+ * @deprecated This returns {@link Object#hashCode()}; you almost certainly mean to call
+ * {@code hash().asInt()}.
+ */
+ @Override
+ @Deprecated
+ int hashCode();
}
diff --git a/guava/src/com/google/common/hash/Hashing.java b/guava/src/com/google/common/hash/Hashing.java
index 74ab112..3cb9cff 100644
--- a/guava/src/com/google/common/hash/Hashing.java
+++ b/guava/src/com/google/common/hash/Hashing.java
@@ -15,17 +15,21 @@
package com.google.common.hash;
import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Iterator;
+import java.util.List;
import java.util.zip.Adler32;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -41,6 +45,7 @@ import javax.annotation.Nullable;
* @since 11.0
*/
@Beta
+ at CheckReturnValue
public final class Hashing {
/**
* Returns a general-purpose, <b>temporary-use</b>, non-cryptographic hash function. The algorithm
@@ -195,8 +200,7 @@ public final class Hashing {
}
private static class Sha1Holder {
- static final HashFunction SHA_1 =
- new MessageDigestHashFunction("SHA-1", "Hashing.sha1()");
+ static final HashFunction SHA_1 = new MessageDigestHashFunction("SHA-1", "Hashing.sha1()");
}
/**
@@ -213,6 +217,21 @@ public final class Hashing {
}
/**
+ * Returns a hash function implementing the SHA-384 algorithm (384 hash bits) by delegating to
+ * the SHA-384 {@link MessageDigest}.
+ *
+ * @since 19.0
+ */
+ public static HashFunction sha384() {
+ return Sha384Holder.SHA_384;
+ }
+
+ private static class Sha384Holder {
+ static final HashFunction SHA_384 =
+ new MessageDigestHashFunction("SHA-384", "Hashing.sha384()");
+ }
+
+ /**
* Returns a hash function implementing the SHA-512 algorithm (512 hash bits) by delegating to the
* SHA-512 {@link MessageDigest}.
*/
@@ -253,8 +272,7 @@ public final class Hashing {
}
private static class Crc32Holder {
- static final HashFunction CRC_32 =
- checksumHashFunction(ChecksumType.CRC_32, "Hashing.crc32()");
+ static final HashFunction CRC_32 = checksumHashFunction(ChecksumType.CRC_32, "Hashing.crc32()");
}
/**
@@ -304,34 +322,70 @@ public final class Hashing {
}
/**
- * Assigns to {@code hashCode} a "bucket" in the range {@code [0, buckets)}, in a uniform
- * manner that minimizes the need for remapping as {@code buckets} grows. That is,
- * {@code consistentHash(h, n)} equals:
+ * Assigns to {@code hashCode} a "bucket" in the range {@code [0, buckets)}, in a uniform manner
+ * that minimizes the need for remapping as {@code buckets} grows. That is, {@code
+ * consistentHash(h, n)} equals:
*
* <ul>
* <li>{@code n - 1}, with approximate probability {@code 1/n}
* <li>{@code consistentHash(h, n - 1)}, otherwise (probability {@code 1 - 1/n})
* </ul>
*
- * <p>See the <a href="http://en.wikipedia.org/wiki/Consistent_hashing">wikipedia
- * article on consistent hashing</a> for more information.
+ * <p>This method is suitable for the common use case of dividing work among buckets that meet the
+ * following conditions:
+ *
+ * <ul>
+ * <li>You want to assign the same fraction of inputs to each bucket.
+ * <li>When you reduce the number of buckets, you can accept that the most recently added buckets
+ * will be removed first. More concretely, if you are dividing traffic among tasks, you can
+ * decrease the number of tasks from 15 and 10, killing off the final 5 tasks, and {@code
+ * consistentHash} will handle it. If, however, you are dividing traffic among servers {@code
+ * alpha}, {@code bravo}, and {@code charlie} and you occasionally need to take each of the
+ * servers offline, {@code consistentHash} will be a poor fit: It provides no way for you to
+ * specify which of the three buckets is disappearing. Thus, if your buckets change from {@code
+ * [alpha, bravo, charlie]} to {@code [bravo, charlie]}, it will assign all the old {@code alpha}
+ * traffic to {@code bravo} and all the old {@code bravo} traffic to {@code charlie}, rather than
+ * letting {@code bravo} keep its traffic.
+ * </ul>
+ *
+ *
+ * <p>See the <a href="http://en.wikipedia.org/wiki/Consistent_hashing">Wikipedia article on
+ * consistent hashing</a> for more information.
*/
public static int consistentHash(HashCode hashCode, int buckets) {
return consistentHash(hashCode.padToLong(), buckets);
}
/**
- * Assigns to {@code input} a "bucket" in the range {@code [0, buckets)}, in a uniform
- * manner that minimizes the need for remapping as {@code buckets} grows. That is,
- * {@code consistentHash(h, n)} equals:
+ * Assigns to {@code input} a "bucket" in the range {@code [0, buckets)}, in a uniform manner that
+ * minimizes the need for remapping as {@code buckets} grows. That is, {@code consistentHash(h,
+ * n)} equals:
*
* <ul>
* <li>{@code n - 1}, with approximate probability {@code 1/n}
* <li>{@code consistentHash(h, n - 1)}, otherwise (probability {@code 1 - 1/n})
* </ul>
*
- * <p>See the <a href="http://en.wikipedia.org/wiki/Consistent_hashing">wikipedia
- * article on consistent hashing</a> for more information.
+ * <p>This method is suitable for the common use case of dividing work among buckets that meet the
+ * following conditions:
+ *
+ * <ul>
+ * <li>You want to assign the same fraction of inputs to each bucket.
+ * <li>When you reduce the number of buckets, you can accept that the most recently added buckets
+ * will be removed first. More concretely, if you are dividing traffic among tasks, you can
+ * decrease the number of tasks from 15 and 10, killing off the final 5 tasks, and {@code
+ * consistentHash} will handle it. If, however, you are dividing traffic among servers {@code
+ * alpha}, {@code bravo}, and {@code charlie} and you occasionally need to take each of the
+ * servers offline, {@code consistentHash} will be a poor fit: It provides no way for you to
+ * specify which of the three buckets is disappearing. Thus, if your buckets change from {@code
+ * [alpha, bravo, charlie]} to {@code [bravo, charlie]}, it will assign all the old {@code alpha}
+ * traffic to {@code bravo} and all the old {@code bravo} traffic to {@code charlie}, rather than
+ * letting {@code bravo} keep its traffic.
+ * </ul>
+ *
+ *
+ * <p>See the <a href="http://en.wikipedia.org/wiki/Consistent_hashing">Wikipedia article on
+ * consistent hashing</a> for more information.
*/
public static int consistentHash(long input, int buckets) {
checkArgument(buckets > 0, "buckets must be positive: %s", buckets);
@@ -367,8 +421,8 @@ public final class Hashing {
byte[] resultBytes = new byte[bits / 8];
for (HashCode hashCode : hashCodes) {
byte[] nextBytes = hashCode.asBytes();
- checkArgument(nextBytes.length == resultBytes.length,
- "All hashcodes must have the same bit length.");
+ checkArgument(
+ nextBytes.length == resultBytes.length, "All hashcodes must have the same bit length.");
for (int i = 0; i < nextBytes.length; i++) {
resultBytes[i] = (byte) (resultBytes[i] * 37 ^ nextBytes[i]);
}
@@ -392,8 +446,8 @@ public final class Hashing {
byte[] resultBytes = new byte[iterator.next().bits() / 8];
for (HashCode hashCode : hashCodes) {
byte[] nextBytes = hashCode.asBytes();
- checkArgument(nextBytes.length == resultBytes.length,
- "All hashcodes must have the same bit length.");
+ checkArgument(
+ nextBytes.length == resultBytes.length, "All hashcodes must have the same bit length.");
for (int i = 0; i < nextBytes.length; i++) {
resultBytes[i] += nextBytes[i];
}
@@ -409,16 +463,62 @@ public final class Hashing {
return (bits + 31) & ~31;
}
- // TODO(kevinb): Maybe expose this class via a static Hashing method?
- @VisibleForTesting
- static final class ConcatenatedHashFunction extends AbstractCompositeHashFunction {
+ /**
+ * Returns a hash function which computes its hash code by concatenating the hash codes of the
+ * underlying hash functions together. This can be useful if you need to generate hash codes
+ * of a specific length.
+ *
+ * <p>For example, if you need 1024-bit hash codes, you could join two {@link Hashing#sha512}
+ * hash functions together: {@code Hashing.concatenating(Hashing.sha512(), Hashing.sha512())}.
+ *
+ * @since 19.0
+ */
+ public static HashFunction concatenating(
+ HashFunction first, HashFunction second, HashFunction... rest) {
+ // We can't use Lists.asList() here because there's no hash->collect dependency
+ List<HashFunction> list = new ArrayList<HashFunction>();
+ list.add(first);
+ list.add(second);
+ for (HashFunction hashFunc : rest) {
+ list.add(hashFunc);
+ }
+ return new ConcatenatedHashFunction(list.toArray(new HashFunction[0]));
+ }
+
+ /**
+ * Returns a hash function which computes its hash code by concatenating the hash codes of the
+ * underlying hash functions together. This can be useful if you need to generate hash codes
+ * of a specific length.
+ *
+ * <p>For example, if you need 1024-bit hash codes, you could join two {@link Hashing#sha512}
+ * hash functions together: {@code Hashing.concatenating(Hashing.sha512(), Hashing.sha512())}.
+ *
+ * @since 19.0
+ */
+ public static HashFunction concatenating(Iterable<HashFunction> hashFunctions) {
+ checkNotNull(hashFunctions);
+ // We can't use Iterables.toArray() here because there's no hash->collect dependency
+ List<HashFunction> list = new ArrayList<HashFunction>();
+ for (HashFunction hashFunction : hashFunctions) {
+ list.add(hashFunction);
+ }
+ checkArgument(list.size() > 0, "number of hash functions (%s) must be > 0", list.size());
+ return new ConcatenatedHashFunction(list.toArray(new HashFunction[0]));
+ }
+
+ private static final class ConcatenatedHashFunction extends AbstractCompositeHashFunction {
private final int bits;
- ConcatenatedHashFunction(HashFunction... functions) {
+ private ConcatenatedHashFunction(HashFunction... functions) {
super(functions);
int bitSum = 0;
for (HashFunction function : functions) {
bitSum += function.bits();
+ checkArgument(
+ function.bits() % 8 == 0,
+ "the number of bits (%s) in hashFunction (%s) must be divisible by 8",
+ function.bits(),
+ function);
}
this.bits = bitSum;
}
@@ -443,26 +543,14 @@ public final class Hashing {
public boolean equals(@Nullable Object object) {
if (object instanceof ConcatenatedHashFunction) {
ConcatenatedHashFunction other = (ConcatenatedHashFunction) object;
- if (bits != other.bits || functions.length != other.functions.length) {
- return false;
- }
- for (int i = 0; i < functions.length; i++) {
- if (!functions[i].equals(other.functions[i])) {
- return false;
- }
- }
- return true;
+ return Arrays.equals(functions, other.functions);
}
return false;
}
@Override
public int hashCode() {
- int hash = bits;
- for (HashFunction function : functions) {
- hash ^= function.hashCode();
- }
- return hash;
+ return Arrays.hashCode(functions) * 31 + bits;
}
}
diff --git a/guava/src/com/google/common/hash/HashingInputStream.java b/guava/src/com/google/common/hash/HashingInputStream.java
index 3fcc621..b6262e8 100644
--- a/guava/src/com/google/common/hash/HashingInputStream.java
+++ b/guava/src/com/google/common/hash/HashingInputStream.java
@@ -22,6 +22,8 @@ import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
+import javax.annotation.CheckReturnValue;
+
/**
* An {@link InputStream} that maintains a hash of the data read from it.
*
@@ -74,6 +76,7 @@ public final class HashingInputStream extends FilterInputStream {
* @return {@code false} always
*/
@Override
+ @CheckReturnValue
public boolean markSupported() {
return false;
}
@@ -97,6 +100,7 @@ public final class HashingInputStream extends FilterInputStream {
* Returns the {@link HashCode} based on the data read from this stream. The result is
* unspecified if this method is called more than once on the same instance.
*/
+ @CheckReturnValue
public HashCode hash() {
return hasher.hash();
}
diff --git a/guava/src/com/google/common/hash/HashingOutputStream.java b/guava/src/com/google/common/hash/HashingOutputStream.java
index 057b577..df57920 100644
--- a/guava/src/com/google/common/hash/HashingOutputStream.java
+++ b/guava/src/com/google/common/hash/HashingOutputStream.java
@@ -22,6 +22,8 @@ import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import javax.annotation.CheckReturnValue;
+
/**
* An {@link OutputStream} that maintains a hash of the data written to it.
*
@@ -47,12 +49,14 @@ public final class HashingOutputStream extends FilterOutputStream {
this.hasher = checkNotNull(hashFunction.newHasher());
}
- @Override public void write(int b) throws IOException {
+ @Override
+ public void write(int b) throws IOException {
hasher.putByte((byte) b);
out.write(b);
}
- @Override public void write(byte[] bytes, int off, int len) throws IOException {
+ @Override
+ public void write(byte[] bytes, int off, int len) throws IOException {
hasher.putBytes(bytes, off, len);
out.write(bytes, off, len);
}
@@ -61,6 +65,7 @@ public final class HashingOutputStream extends FilterOutputStream {
* Returns the {@link HashCode} based on the data written to this stream. The result is
* unspecified if this method is called more than once on the same instance.
*/
+ @CheckReturnValue
public HashCode hash() {
return hasher.hash();
}
@@ -68,7 +73,8 @@ public final class HashingOutputStream extends FilterOutputStream {
// Overriding close() because FilterOutputStream's close() method pre-JDK8 has bad behavior:
// it silently ignores any exception thrown by flush(). Instead, just close the delegate stream.
// It should flush itself if necessary.
- @Override public void close() throws IOException {
+ @Override
+ public void close() throws IOException {
out.close();
}
}
diff --git a/guava/src/com/google/common/hash/MessageDigestHashFunction.java b/guava/src/com/google/common/hash/MessageDigestHashFunction.java
index e160833..80fcec4 100644
--- a/guava/src/com/google/common/hash/MessageDigestHashFunction.java
+++ b/guava/src/com/google/common/hash/MessageDigestHashFunction.java
@@ -47,8 +47,8 @@ final class MessageDigestHashFunction extends AbstractStreamingHashFunction
this.toString = checkNotNull(toString);
this.prototype = getMessageDigest(algorithmName);
int maxLength = prototype.getDigestLength();
- checkArgument(bytes >= 4 && bytes <= maxLength,
- "bytes (%s) must be >= 4 and < %s", bytes, maxLength);
+ checkArgument(
+ bytes >= 4 && bytes <= maxLength, "bytes (%s) must be >= 4 and < %s", bytes, maxLength);
this.bytes = bytes;
this.supportsClone = supportsClone();
}
@@ -62,11 +62,13 @@ final class MessageDigestHashFunction extends AbstractStreamingHashFunction
}
}
- @Override public int bits() {
+ @Override
+ public int bits() {
return bytes * Byte.SIZE;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return toString;
}
@@ -78,7 +80,8 @@ final class MessageDigestHashFunction extends AbstractStreamingHashFunction
}
}
- @Override public Hasher newHasher() {
+ @Override
+ public Hasher newHasher() {
if (supportsClone) {
try {
return new MessageDigestHasher((MessageDigest) prototype.clone(), bytes);
@@ -115,7 +118,6 @@ final class MessageDigestHashFunction extends AbstractStreamingHashFunction
* Hasher that updates a message digest.
*/
private static final class MessageDigestHasher extends AbstractByteHasher {
-
private final MessageDigest digest;
private final int bytes;
private boolean done;
diff --git a/guava/src/com/google/common/hash/Murmur3_128HashFunction.java b/guava/src/com/google/common/hash/Murmur3_128HashFunction.java
index 1fde761..05aa9c1 100644
--- a/guava/src/com/google/common/hash/Murmur3_128HashFunction.java
+++ b/guava/src/com/google/common/hash/Murmur3_128HashFunction.java
@@ -48,11 +48,13 @@ final class Murmur3_128HashFunction extends AbstractStreamingHashFunction implem
this.seed = seed;
}
- @Override public int bits() {
+ @Override
+ public int bits() {
return 128;
}
- @Override public Hasher newHasher() {
+ @Override
+ public Hasher newHasher() {
return new Murmur3_128Hasher(seed);
}
@@ -90,7 +92,8 @@ final class Murmur3_128HashFunction extends AbstractStreamingHashFunction implem
this.length = 0;
}
- @Override protected void process(ByteBuffer bb) {
+ @Override
+ protected void process(ByteBuffer bb) {
long k1 = bb.getLong();
long k2 = bb.getLong();
bmix64(k1, k2);
@@ -111,7 +114,8 @@ final class Murmur3_128HashFunction extends AbstractStreamingHashFunction implem
h2 = h2 * 5 + 0x38495ab5;
}
- @Override protected void processRemaining(ByteBuffer bb) {
+ @Override
+ protected void processRemaining(ByteBuffer bb) {
long k1 = 0;
long k2 = 0;
length += bb.remaining();
@@ -155,7 +159,8 @@ final class Murmur3_128HashFunction extends AbstractStreamingHashFunction implem
h2 ^= mixK2(k2);
}
- @Override public HashCode makeHash() {
+ @Override
+ public HashCode makeHash() {
h1 ^= length;
h2 ^= length;
@@ -168,12 +173,12 @@ final class Murmur3_128HashFunction extends AbstractStreamingHashFunction implem
h1 += h2;
h2 += h1;
- return HashCode.fromBytesNoCopy(ByteBuffer
- .wrap(new byte[CHUNK_SIZE])
- .order(ByteOrder.LITTLE_ENDIAN)
- .putLong(h1)
- .putLong(h2)
- .array());
+ return HashCode.fromBytesNoCopy(
+ ByteBuffer.wrap(new byte[CHUNK_SIZE])
+ .order(ByteOrder.LITTLE_ENDIAN)
+ .putLong(h1)
+ .putLong(h2)
+ .array());
}
private static long fmix64(long k) {
diff --git a/guava/src/com/google/common/hash/Murmur3_32HashFunction.java b/guava/src/com/google/common/hash/Murmur3_32HashFunction.java
index db6e673..22f53cf 100644
--- a/guava/src/com/google/common/hash/Murmur3_32HashFunction.java
+++ b/guava/src/com/google/common/hash/Murmur3_32HashFunction.java
@@ -54,11 +54,13 @@ final class Murmur3_32HashFunction extends AbstractStreamingHashFunction impleme
this.seed = seed;
}
- @Override public int bits() {
+ @Override
+ public int bits() {
return 32;
}
- @Override public Hasher newHasher() {
+ @Override
+ public Hasher newHasher() {
return new Murmur3_32Hasher(seed);
}
@@ -81,14 +83,16 @@ final class Murmur3_32HashFunction extends AbstractStreamingHashFunction impleme
return getClass().hashCode() ^ seed;
}
- @Override public HashCode hashInt(int input) {
+ @Override
+ public HashCode hashInt(int input) {
int k1 = mixK1(input);
int h1 = mixH1(seed, k1);
return fmix(h1, Ints.BYTES);
}
- @Override public HashCode hashLong(long input) {
+ @Override
+ public HashCode hashLong(long input) {
int low = (int) input;
int high = (int) (input >>> 32);
@@ -101,8 +105,9 @@ final class Murmur3_32HashFunction extends AbstractStreamingHashFunction impleme
return fmix(h1, Longs.BYTES);
}
- // TODO(user): Maybe implement #hashBytes instead?
- @Override public HashCode hashUnencodedChars(CharSequence input) {
+ // TODO(kak): Maybe implement #hashBytes instead?
+ @Override
+ public HashCode hashUnencodedChars(CharSequence input) {
int h1 = seed;
// step through the CharSequence 2 chars at a time
@@ -158,13 +163,15 @@ final class Murmur3_32HashFunction extends AbstractStreamingHashFunction impleme
this.length = 0;
}
- @Override protected void process(ByteBuffer bb) {
+ @Override
+ protected void process(ByteBuffer bb) {
int k1 = Murmur3_32HashFunction.mixK1(bb.getInt());
h1 = Murmur3_32HashFunction.mixH1(h1, k1);
length += CHUNK_SIZE;
}
- @Override protected void processRemaining(ByteBuffer bb) {
+ @Override
+ protected void processRemaining(ByteBuffer bb) {
length += bb.remaining();
int k1 = 0;
for (int i = 0; bb.hasRemaining(); i += 8) {
@@ -173,7 +180,8 @@ final class Murmur3_32HashFunction extends AbstractStreamingHashFunction impleme
h1 ^= Murmur3_32HashFunction.mixK1(k1);
}
- @Override public HashCode makeHash() {
+ @Override
+ public HashCode makeHash() {
return Murmur3_32HashFunction.fmix(h1, length);
}
}
diff --git a/guava/src/com/google/common/hash/SipHashFunction.java b/guava/src/com/google/common/hash/SipHashFunction.java
index 0496a3c..5bac1c1 100644
--- a/guava/src/com/google/common/hash/SipHashFunction.java
+++ b/guava/src/com/google/common/hash/SipHashFunction.java
@@ -50,27 +50,30 @@ final class SipHashFunction extends AbstractStreamingHashFunction implements Ser
* @param k1 the second half of the key
*/
SipHashFunction(int c, int d, long k0, long k1) {
- checkArgument(c > 0,
- "The number of SipRound iterations (c=%s) during Compression must be positive.", c);
- checkArgument(d > 0,
- "The number of SipRound iterations (d=%s) during Finalization must be positive.", d);
+ checkArgument(
+ c > 0, "The number of SipRound iterations (c=%s) during Compression must be positive.", c);
+ checkArgument(
+ d > 0, "The number of SipRound iterations (d=%s) during Finalization must be positive.", d);
this.c = c;
this.d = d;
this.k0 = k0;
this.k1 = k1;
}
- @Override public int bits() {
+ @Override
+ public int bits() {
return 64;
}
- @Override public Hasher newHasher() {
+ @Override
+ public Hasher newHasher() {
return new SipHasher(c, d, k0, k1);
}
- // TODO(user): Implement and benchmark the hashFoo() shortcuts.
+ // TODO(kak): Implement and benchmark the hashFoo() shortcuts.
- @Override public String toString() {
+ @Override
+ public String toString() {
return "Hashing.sipHash" + c + "" + d + "(" + k0 + ", " + k1 + ")";
}
@@ -125,19 +128,22 @@ final class SipHashFunction extends AbstractStreamingHashFunction implements Ser
this.v3 ^= k1;
}
- @Override protected void process(ByteBuffer buffer) {
+ @Override
+ protected void process(ByteBuffer buffer) {
b += CHUNK_SIZE;
processM(buffer.getLong());
}
- @Override protected void processRemaining(ByteBuffer buffer) {
+ @Override
+ protected void processRemaining(ByteBuffer buffer) {
b += buffer.remaining();
for (int i = 0; buffer.hasRemaining(); i += 8) {
finalM ^= (buffer.get() & 0xFFL) << i;
}
}
- @Override public HashCode makeHash() {
+ @Override
+ public HashCode makeHash() {
// End with a byte encoding the positive integer b mod 256.
finalM ^= b << 56;
processM(finalM);
diff --git a/guava/src/com/google/common/hash/package-info.java b/guava/src/com/google/common/hash/package-info.java
index 7df4e73..a55060a 100644
--- a/guava/src/com/google/common/hash/package-info.java
+++ b/guava/src/com/google/common/hash/package-info.java
@@ -17,7 +17,7 @@
* Hash functions and related structures.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/HashingExplained">
+ * "https://github.com/google/guava/wiki/HashingExplained">
* hashing</a>.
*/
@ParametersAreNonnullByDefault
diff --git a/guava/src/com/google/common/html/HtmlEscapers.java b/guava/src/com/google/common/html/HtmlEscapers.java
index d96febf..c2009dd 100644
--- a/guava/src/com/google/common/html/HtmlEscapers.java
+++ b/guava/src/com/google/common/html/HtmlEscapers.java
@@ -26,6 +26,9 @@ import com.google.common.escape.Escapers;
* attribute values and <em>most</em> elements' text contents. When possible,
* avoid manual escaping by using templating systems and high-level APIs that
* provide autoescaping.
+ * One Google-authored templating system available for external use is <a
+ * href="https://developers.google.com/closure/templates/">Closure
+ * Templates</a>.
*
* <p>HTML escaping is particularly tricky: For example, <a
* href="http://goo.gl/5TgZb">some elements' text contents must not be HTML
diff --git a/guava/src/com/google/common/io/BaseEncoding.java b/guava/src/com/google/common/io/BaseEncoding.java
index 13c3f55..cb21d4b 100644
--- a/guava/src/com/google/common/io/BaseEncoding.java
+++ b/guava/src/com/google/common/io/BaseEncoding.java
@@ -18,11 +18,6 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.io.GwtWorkarounds.asCharInput;
-import static com.google.common.io.GwtWorkarounds.asCharOutput;
-import static com.google.common.io.GwtWorkarounds.asInputStream;
-import static com.google.common.io.GwtWorkarounds.asOutputStream;
-import static com.google.common.io.GwtWorkarounds.stringBuilderOutput;
import static com.google.common.math.IntMath.divide;
import static com.google.common.math.IntMath.log2;
import static java.math.RoundingMode.CEILING;
@@ -34,10 +29,6 @@ import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Ascii;
import com.google.common.base.CharMatcher;
-import com.google.common.io.GwtWorkarounds.ByteInput;
-import com.google.common.io.GwtWorkarounds.ByteOutput;
-import com.google.common.io.GwtWorkarounds.CharInput;
-import com.google.common.io.GwtWorkarounds.CharOutput;
import java.io.IOException;
import java.io.InputStream;
@@ -131,7 +122,7 @@ import javax.annotation.Nullable;
@Beta
@GwtCompatible(emulated = true)
public abstract class BaseEncoding {
- // TODO(user): consider adding encodeTo(Appendable, byte[], [int, int])
+ // TODO(lowasser): consider making encodeTo(Appendable, byte[], int, int) public.
BaseEncoding() {}
@@ -155,7 +146,7 @@ public abstract class BaseEncoding {
* Encodes the specified byte array, and returns the encoded {@code String}.
*/
public String encode(byte[] bytes) {
- return encode(checkNotNull(bytes), 0, bytes.length);
+ return encode(bytes, 0, bytes.length);
}
/**
@@ -163,17 +154,12 @@ public abstract class BaseEncoding {
* {@code String}.
*/
public final String encode(byte[] bytes, int off, int len) {
- checkNotNull(bytes);
checkPositionIndexes(off, off + len, bytes.length);
- CharOutput result = stringBuilderOutput(maxEncodedSize(len));
- ByteOutput byteOutput = encodingStream(result);
+ StringBuilder result = new StringBuilder(maxEncodedSize(len));
try {
- for (int i = 0; i < len; i++) {
- byteOutput.write(bytes[off + i]);
- }
- byteOutput.close();
+ encodeTo(result, bytes, off, len);
} catch (IOException impossible) {
- throw new AssertionError("impossible");
+ throw new AssertionError(impossible);
}
return result.toString();
}
@@ -184,9 +170,7 @@ public abstract class BaseEncoding {
* {@code Writer}.
*/
@GwtIncompatible("Writer,OutputStream")
- public final OutputStream encodingStream(Writer writer) {
- return asOutputStream(encodingStream(asCharOutput(writer)));
- }
+ public abstract OutputStream encodingStream(Writer writer);
/**
* Returns a {@code ByteSink} that writes base-encoded bytes to the specified {@code CharSink}.
@@ -202,7 +186,7 @@ public abstract class BaseEncoding {
};
}
- // TODO(user): document the extent of leniency, probably after adding ignore(CharMatcher)
+ // TODO(lowasser): document the extent of leniency, probably after adding ignore(CharMatcher)
private static byte[] extract(byte[] result, int length) {
if (length == result.length) {
@@ -238,19 +222,9 @@ public abstract class BaseEncoding {
*/
final byte[] decodeChecked(CharSequence chars) throws DecodingException {
chars = padding().trimTrailingFrom(chars);
- ByteInput decodedInput = decodingStream(asCharInput(chars));
byte[] tmp = new byte[maxDecodedSize(chars.length())];
- int index = 0;
- try {
- for (int i = decodedInput.read(); i != -1; i = decodedInput.read()) {
- tmp[index++] = (byte) i;
- }
- } catch (DecodingException badInput) {
- throw badInput;
- } catch (IOException impossible) {
- throw new AssertionError(impossible);
- }
- return extract(tmp, index);
+ int len = decodeTo(tmp, chars);
+ return extract(tmp, len);
}
/**
@@ -259,9 +233,7 @@ public abstract class BaseEncoding {
* errors.
*/
@GwtIncompatible("Reader,InputStream")
- public final InputStream decodingStream(Reader reader) {
- return asInputStream(decodingStream(asCharInput(reader)));
- }
+ public abstract InputStream decodingStream(Reader reader);
/**
* Returns a {@code ByteSource} that reads base-encoded bytes from the specified
@@ -282,11 +254,11 @@ public abstract class BaseEncoding {
abstract int maxEncodedSize(int bytes);
- abstract ByteOutput encodingStream(CharOutput charOutput);
+ abstract void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException;
abstract int maxDecodedSize(int chars);
- abstract ByteInput decodingStream(CharInput charInput);
+ abstract int decodeTo(byte[] target, CharSequence chars) throws DecodingException;
abstract CharMatcher padding();
@@ -342,7 +314,7 @@ public abstract class BaseEncoding {
@CheckReturnValue
public abstract BaseEncoding lowerCase();
- private static final BaseEncoding BASE64 = new StandardBaseEncoding(
+ private static final BaseEncoding BASE64 = new Base64Encoding(
"base64()", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", '=');
/**
@@ -362,7 +334,7 @@ public abstract class BaseEncoding {
return BASE64;
}
- private static final BaseEncoding BASE64_URL = new StandardBaseEncoding(
+ private static final BaseEncoding BASE64_URL = new Base64Encoding(
"base64Url()", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", '=');
/**
@@ -422,8 +394,7 @@ public abstract class BaseEncoding {
return BASE32_HEX;
}
- private static final BaseEncoding BASE16 =
- new StandardBaseEncoding("base16()", "0123456789ABCDEF", null);
+ private static final BaseEncoding BASE16 = new Base16Encoding("base16()", "0123456789ABCDEF");
/**
* The "base16" encoding specified by <a
@@ -498,9 +469,10 @@ public abstract class BaseEncoding {
return validPadding[index % charsPerChunk];
}
- int decode(char ch) throws IOException {
+ int decode(char ch) throws DecodingException {
if (ch > Ascii.MAX || decodabet[ch] == -1) {
- throw new DecodingException("Unrecognized character: " + ch);
+ throw new DecodingException("Unrecognized character: "
+ + (CharMatcher.INVISIBLE.matches(ch) ? "0x" + Integer.toHexString(ch) : ch));
}
return decodabet[ch];
}
@@ -560,12 +532,12 @@ public abstract class BaseEncoding {
}
}
- static final class StandardBaseEncoding extends BaseEncoding {
- // TODO(user): provide a useful toString
- private final Alphabet alphabet;
+ static class StandardBaseEncoding extends BaseEncoding {
+ // TODO(lowasser): provide a useful toString
+ final Alphabet alphabet;
@Nullable
- private final Character paddingChar;
+ final Character paddingChar;
StandardBaseEncoding(String name, String alphabetChars, @Nullable Character paddingChar) {
this(new Alphabet(name, alphabetChars.toCharArray()), paddingChar);
@@ -588,16 +560,17 @@ public abstract class BaseEncoding {
return alphabet.charsPerChunk * divide(bytes, alphabet.bytesPerChunk, CEILING);
}
+ @GwtIncompatible("Writer,OutputStream")
@Override
- ByteOutput encodingStream(final CharOutput out) {
+ public OutputStream encodingStream(final Writer out) {
checkNotNull(out);
- return new ByteOutput() {
+ return new OutputStream() {
int bitBuffer = 0;
int bitBufferLength = 0;
int writtenChars = 0;
@Override
- public void write(byte b) throws IOException {
+ public void write(int b) throws IOException {
bitBuffer <<= 8;
bitBuffer |= b & 0xFF;
bitBufferLength += 8;
@@ -635,14 +608,75 @@ public abstract class BaseEncoding {
}
@Override
+ void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+ checkNotNull(target);
+ checkPositionIndexes(off, off + len, bytes.length);
+ for (int i = 0; i < len; i += alphabet.bytesPerChunk) {
+ encodeChunkTo(target, bytes, off + i, Math.min(alphabet.bytesPerChunk, len - i));
+ }
+ }
+
+ void encodeChunkTo(Appendable target, byte[] bytes, int off, int len)
+ throws IOException {
+ checkNotNull(target);
+ checkPositionIndexes(off, off + len, bytes.length);
+ checkArgument(len <= alphabet.bytesPerChunk);
+ long bitBuffer = 0;
+ for (int i = 0; i < len; ++i) {
+ bitBuffer |= bytes[off + i] & 0xFF;
+ bitBuffer <<= 8; // Add additional zero byte in the end.
+ }
+ // Position of first character is length of bitBuffer minus bitsPerChar.
+ final int bitOffset = (len + 1) * 8 - alphabet.bitsPerChar;
+ int bitsProcessed = 0;
+ while (bitsProcessed < len * 8) {
+ int charIndex = (int) (bitBuffer >>> (bitOffset - bitsProcessed)) & alphabet.mask;
+ target.append(alphabet.encode(charIndex));
+ bitsProcessed += alphabet.bitsPerChar;
+ }
+ if (paddingChar != null) {
+ while (bitsProcessed < alphabet.bytesPerChunk * 8) {
+ target.append(paddingChar.charValue());
+ bitsProcessed += alphabet.bitsPerChar;
+ }
+ }
+ }
+
+ @Override
int maxDecodedSize(int chars) {
return (int) ((alphabet.bitsPerChar * (long) chars + 7L) / 8L);
}
@Override
- ByteInput decodingStream(final CharInput reader) {
+ int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+ checkNotNull(target);
+ chars = padding().trimTrailingFrom(chars);
+ if (!alphabet.isValidPaddingStartPosition(chars.length())) {
+ throw new DecodingException("Invalid input length " + chars.length());
+ }
+ int bytesWritten = 0;
+ for (int charIdx = 0; charIdx < chars.length(); charIdx += alphabet.charsPerChunk) {
+ long chunk = 0;
+ int charsProcessed = 0;
+ for (int i = 0; i < alphabet.charsPerChunk; i++) {
+ chunk <<= alphabet.bitsPerChar;
+ if (charIdx + i < chars.length()) {
+ chunk |= alphabet.decode(chars.charAt(charIdx + charsProcessed++));
+ }
+ }
+ final int minOffset = alphabet.bytesPerChunk * 8 - charsProcessed * alphabet.bitsPerChar;
+ for (int offset = (alphabet.bytesPerChunk - 1) * 8; offset >= minOffset; offset -= 8) {
+ target[bytesWritten++] = (byte) ((chunk >>> offset) & 0xFF);
+ }
+ }
+ return bytesWritten;
+ }
+
+ @GwtIncompatible("Reader,InputStream")
+ @Override
+ public InputStream decodingStream(final Reader reader) {
checkNotNull(reader);
- return new ByteInput() {
+ return new InputStream() {
int bitBuffer = 0;
int bitBufferLength = 0;
int readChars = 0;
@@ -692,7 +726,7 @@ public abstract class BaseEncoding {
@Override
public BaseEncoding omitPadding() {
- return (paddingChar == null) ? this : new StandardBaseEncoding(alphabet, null);
+ return (paddingChar == null) ? this : newInstance(alphabet, null);
}
@Override
@@ -701,15 +735,14 @@ public abstract class BaseEncoding {
(paddingChar != null && paddingChar.charValue() == padChar)) {
return this;
} else {
- return new StandardBaseEncoding(alphabet, padChar);
+ return newInstance(alphabet, padChar);
}
}
@Override
public BaseEncoding withSeparator(String separator, int afterEveryChars) {
- checkNotNull(separator);
checkArgument(padding().or(alphabet).matchesNoneOf(separator),
- "Separator cannot contain alphabet or padding characters");
+ "Separator (%s) cannot contain alphabet or padding characters", separator);
return new SeparatedBaseEncoding(this, separator, afterEveryChars);
}
@@ -722,7 +755,7 @@ public abstract class BaseEncoding {
if (result == null) {
Alphabet upper = alphabet.upperCase();
result = upperCase =
- (upper == alphabet) ? this : new StandardBaseEncoding(upper, paddingChar);
+ (upper == alphabet) ? this : newInstance(upper, paddingChar);
}
return result;
}
@@ -733,11 +766,15 @@ public abstract class BaseEncoding {
if (result == null) {
Alphabet lower = alphabet.lowerCase();
result = lowerCase =
- (lower == alphabet) ? this : new StandardBaseEncoding(lower, paddingChar);
+ (lower == alphabet) ? this : newInstance(lower, paddingChar);
}
return result;
}
+ BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
+ return new StandardBaseEncoding(alphabet, paddingChar);
+ }
+
@Override
public String toString() {
StringBuilder builder = new StringBuilder("BaseEncoding.");
@@ -753,10 +790,115 @@ public abstract class BaseEncoding {
}
}
- static CharInput ignoringInput(final CharInput delegate, final CharMatcher toIgnore) {
+ static final class Base16Encoding extends StandardBaseEncoding {
+ final char[] encoding = new char[512];
+
+ Base16Encoding(String name, String alphabetChars) {
+ this(new Alphabet(name, alphabetChars.toCharArray()));
+ }
+
+ private Base16Encoding(Alphabet alphabet) {
+ super(alphabet, null);
+ checkArgument(alphabet.chars.length == 16);
+ for (int i = 0; i < 256; ++i) {
+ encoding[i] = alphabet.encode(i >>> 4);
+ encoding[i | 0x100] = alphabet.encode(i & 0xF);
+ }
+ }
+
+ @Override
+ void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+ checkNotNull(target);
+ checkPositionIndexes(off, off + len, bytes.length);
+ for (int i = 0; i < len; ++i) {
+ int b = bytes[off + i] & 0xFF;
+ target.append(encoding[b]);
+ target.append(encoding[b | 0x100]);
+ }
+ }
+
+ @Override
+ int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+ checkNotNull(target);
+ if (chars.length() % 2 == 1) {
+ throw new DecodingException("Invalid input length " + chars.length());
+ }
+ int bytesWritten = 0;
+ for (int i = 0; i < chars.length(); i += 2) {
+ int decoded = alphabet.decode(chars.charAt(i)) << 4 | alphabet.decode(chars.charAt(i + 1));
+ target[bytesWritten++] = (byte) decoded;
+ }
+ return bytesWritten;
+ }
+
+ @Override
+ BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
+ return new Base16Encoding(alphabet);
+ }
+ }
+
+ static final class Base64Encoding extends StandardBaseEncoding {
+ Base64Encoding(String name, String alphabetChars, @Nullable Character paddingChar) {
+ this(new Alphabet(name, alphabetChars.toCharArray()), paddingChar);
+ }
+
+ private Base64Encoding(Alphabet alphabet, @Nullable Character paddingChar) {
+ super(alphabet, paddingChar);
+ checkArgument(alphabet.chars.length == 64);
+ }
+
+ @Override
+ void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+ checkNotNull(target);
+ checkPositionIndexes(off, off + len, bytes.length);
+ int i = off;
+ for (int remaining = len; remaining >= 3; remaining -= 3) {
+ int chunk = (bytes[i++] & 0xFF) << 16 | (bytes[i++] & 0xFF) << 8 | bytes[i++] & 0xFF;
+ target.append(alphabet.encode(chunk >>> 18));
+ target.append(alphabet.encode((chunk >>> 12) & 0x3F));
+ target.append(alphabet.encode((chunk >>> 6) & 0x3F));
+ target.append(alphabet.encode(chunk & 0x3F));
+ }
+ if (i < off + len) {
+ encodeChunkTo(target, bytes, i, off + len - i);
+ }
+ }
+
+ @Override
+ int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+ checkNotNull(target);
+ chars = padding().trimTrailingFrom(chars);
+ if (!alphabet.isValidPaddingStartPosition(chars.length())) {
+ throw new DecodingException("Invalid input length " + chars.length());
+ }
+ int bytesWritten = 0;
+ for (int i = 0; i < chars.length();) {
+ int chunk = alphabet.decode(chars.charAt(i++)) << 18;
+ chunk |= alphabet.decode(chars.charAt(i++)) << 12;
+ target[bytesWritten++] = (byte) (chunk >>> 16);
+ if (i < chars.length()) {
+ chunk |= alphabet.decode(chars.charAt(i++)) << 6;
+ target[bytesWritten++] = (byte) ((chunk >>> 8) & 0xFF);
+ if (i < chars.length()) {
+ chunk |= alphabet.decode(chars.charAt(i++));
+ target[bytesWritten++] = (byte) (chunk & 0xFF);
+ }
+ }
+ }
+ return bytesWritten;
+ }
+
+ @Override
+ BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
+ return new Base64Encoding(alphabet, paddingChar);
+ }
+ }
+
+ @GwtIncompatible("Reader")
+ static Reader ignoringReader(final Reader delegate, final CharMatcher toIgnore) {
checkNotNull(delegate);
checkNotNull(toIgnore);
- return new CharInput() {
+ return new Reader() {
@Override
public int read() throws IOException {
int readChar;
@@ -767,30 +909,62 @@ public abstract class BaseEncoding {
}
@Override
+ public int read(char[] cbuf, int off, int len) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public void close() throws IOException {
delegate.close();
}
};
}
- static CharOutput separatingOutput(
- final CharOutput delegate, final String separator, final int afterEveryChars) {
+ static Appendable separatingAppendable(
+ final Appendable delegate, final String separator, final int afterEveryChars) {
checkNotNull(delegate);
checkNotNull(separator);
checkArgument(afterEveryChars > 0);
- return new CharOutput() {
+ return new Appendable() {
int charsUntilSeparator = afterEveryChars;
@Override
- public void write(char c) throws IOException {
+ public Appendable append(char c) throws IOException {
if (charsUntilSeparator == 0) {
- for (int i = 0; i < separator.length(); i++) {
- delegate.write(separator.charAt(i));
- }
+ delegate.append(separator);
charsUntilSeparator = afterEveryChars;
}
- delegate.write(c);
+ delegate.append(c);
charsUntilSeparator--;
+ return this;
+ }
+
+ @Override
+ public Appendable append(CharSequence chars, int off, int len) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Appendable append(CharSequence chars) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ @GwtIncompatible("Writer")
+ static Writer separatingWriter(
+ final Writer delegate, final String separator, final int afterEveryChars) {
+ final Appendable seperatingAppendable =
+ separatingAppendable(delegate, separator, afterEveryChars);
+ return new Writer() {
+ @Override
+ public void write(int c) throws IOException {
+ seperatingAppendable.append((char) c);
+ }
+
+ @Override
+ public void write(char[] chars, int off, int len) throws IOException {
+ throw new UnsupportedOperationException();
}
@Override
@@ -832,9 +1006,15 @@ public abstract class BaseEncoding {
* divide(Math.max(0, unseparatedSize - 1), afterEveryChars, FLOOR);
}
+ @GwtIncompatible("Writer,OutputStream")
@Override
- ByteOutput encodingStream(final CharOutput output) {
- return delegate.encodingStream(separatingOutput(output, separator, afterEveryChars));
+ public OutputStream encodingStream(final Writer output) {
+ return delegate.encodingStream(separatingWriter(output, separator, afterEveryChars));
+ }
+
+ @Override
+ void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException {
+ delegate.encodeTo(separatingAppendable(target, separator, afterEveryChars), bytes, off, len);
}
@Override
@@ -843,8 +1023,14 @@ public abstract class BaseEncoding {
}
@Override
- ByteInput decodingStream(final CharInput input) {
- return delegate.decodingStream(ignoringInput(input, separatorChars));
+ int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
+ return delegate.decodeTo(target, separatorChars.removeFrom(chars));
+ }
+
+ @GwtIncompatible("Reader,InputStream")
+ @Override
+ public InputStream decodingStream(final Reader reader) {
+ return delegate.decodingStream(ignoringReader(reader, separatorChars));
}
@Override
diff --git a/guava/src/com/google/common/io/ByteArrayDataInput.java b/guava/src/com/google/common/io/ByteArrayDataInput.java
index 3f4a467..8e029ef 100644
--- a/guava/src/com/google/common/io/ByteArrayDataInput.java
+++ b/guava/src/com/google/common/io/ByteArrayDataInput.java
@@ -23,7 +23,7 @@ import java.io.IOException;
* An extension of {@code DataInput} for reading from in-memory byte arrays; its
* methods offer identical functionality but do not throw {@link IOException}.
*
- * <p><b>Warning:<b> The caller is responsible for not attempting to read past
+ * <p><b>Warning:</b> The caller is responsible for not attempting to read past
* the end of the array. If any method encounters the end of the array
* prematurely, it throws {@link IllegalStateException} to signify <i>programmer
* error</i>. This behavior is a technical violation of the supertype's
diff --git a/guava/src/com/google/common/io/ByteSource.java b/guava/src/com/google/common/io/ByteSource.java
index 4cddcdd..b829cc5 100644
--- a/guava/src/com/google/common/io/ByteSource.java
+++ b/guava/src/com/google/common/io/ByteSource.java
@@ -18,9 +18,12 @@ package com.google.common.io;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.io.ByteStreams.BUF_SIZE;
+import static com.google.common.io.ByteStreams.skipUpTo;
import com.google.common.annotations.Beta;
import com.google.common.base.Ascii;
+import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.hash.Funnels;
import com.google.common.hash.HashCode;
@@ -58,8 +61,6 @@ import java.util.Iterator;
*/
public abstract class ByteSource {
- private static final int BUF_SIZE = 0x1000; // 4K
-
/**
* Constructor for use by subclasses.
*/
@@ -104,7 +105,10 @@ public abstract class ByteSource {
/**
* Returns a view of a slice of this byte source that is at most {@code length} bytes long
- * starting at the given {@code offset}.
+ * starting at the given {@code offset}. If {@code offset} is greater than the size of this
+ * source, the returned source will be empty. If {@code offset + length} is greater than the size
+ * of this source, the returned source will contain the slice starting at {@code offset} and
+ * ending at the end of this source.
*
* @throws IllegalArgumentException if {@code offset} or {@code length} is negative
*/
@@ -113,13 +117,23 @@ public abstract class ByteSource {
}
/**
- * Returns whether the source has zero bytes. The default implementation is to open a stream and
- * check for EOF.
+ * Returns whether the source has zero bytes. The default implementation returns true if
+ * {@link #sizeIfKnown} returns zero, falling back to opening a stream and checking for
+ * EOF if the size is not known.
+ *
+ * <p>Note that, in cases where {@code sizeIfKnown} returns zero, it is <i>possible</i> that bytes
+ * are actually available for reading. (For example, some special files may return a size of 0
+ * despite actually having content when read.) This means that a source may return {@code true}
+ * from {@code isEmpty()} despite having readable content.
*
* @throws IOException if an I/O error occurs
* @since 15.0
*/
public boolean isEmpty() throws IOException {
+ Optional<Long> sizeIfKnown = sizeIfKnown();
+ if (sizeIfKnown.isPresent() && sizeIfKnown.get() == 0L) {
+ return true;
+ }
Closer closer = Closer.create();
try {
InputStream in = closer.register(openStream());
@@ -132,21 +146,49 @@ public abstract class ByteSource {
}
/**
- * Returns the size of this source in bytes. For most implementations, this is a heavyweight
- * operation that will open a stream, read (or {@link InputStream#skip(long) skip}, if possible)
- * to the end of the stream and return the total number of bytes that were read.
+ * Returns the size of this source in bytes, if the size can be easily determined without
+ * actually opening the data stream.
+ *
+ * <p>The default implementation returns {@link Optional#absent}. Some sources, such as a file,
+ * may return a non-absent value. Note that in such cases, it is <i>possible</i> that this method
+ * will return a different number of bytes than would be returned by reading all of the bytes (for
+ * example, some special files may return a size of 0 despite actually having content when read).
+ *
+ * <p>Additionally, for mutable sources such as files, a subsequent read may return a different
+ * number of bytes if the contents are changed.
+ *
+ * @since 19.0
+ */
+ @Beta
+ public Optional<Long> sizeIfKnown() {
+ return Optional.absent();
+ }
+
+ /**
+ * Returns the size of this source in bytes, even if doing so requires opening and traversing
+ * an entire stream. To avoid a potentially expensive operation, see {@link #sizeIfKnown}.
*
- * <p>For some sources, such as a file, this method may use a more efficient implementation. Note
- * that in such cases, it is <i>possible</i> that this method will return a different number of
- * bytes than would be returned by reading all of the bytes (for example, some special files may
- * return a size of 0 despite actually having content when read).
+ * <p>The default implementation calls {@link #sizeIfKnown} and returns the value if present.
+ * If absent, it will fall back to a heavyweight operation that will open a stream, read (or
+ * {@link InputStream#skip(long) skip}, if possible) to the end of the stream and return the total
+ * number of bytes that were read.
*
- * <p>In either case, if this is a mutable source such as a file, the size it returns may not be
- * the same number of bytes a subsequent read would return.
+ * <p>Note that for some sources that implement {@link #sizeIfKnown} to provide a more efficient
+ * implementation, it is <i>possible</i> that this method will return a different number of bytes
+ * than would be returned by reading all of the bytes (for example, some special files may return
+ * a size of 0 despite actually having content when read).
+ *
+ * <p>In either case, for mutable sources such as files, a subsequent read may return a different
+ * number of bytes if the contents are changed.
*
* @throws IOException if an I/O error occurs in the process of reading the size of this source
*/
public long size() throws IOException {
+ Optional<Long> sizeIfKnown = sizeIfKnown();
+ if (sizeIfKnown.isPresent()) {
+ return sizeIfKnown.get();
+ }
+
Closer closer = Closer.create();
try {
InputStream in = closer.register(openStream());
@@ -174,31 +216,17 @@ public abstract class ByteSource {
*/
private long countBySkipping(InputStream in) throws IOException {
long count = 0;
- while (true) {
- // don't try to skip more than available()
- // things may work really wrong with FileInputStream otherwise
- long skipped = in.skip(Math.min(in.available(), Integer.MAX_VALUE));
- if (skipped <= 0) {
- if (in.read() == -1) {
- return count;
- } else if (count == 0 && in.available() == 0) {
- // if available is still zero after reading a single byte, it
- // will probably always be zero, so we should countByReading
- throw new IOException();
- }
- count++;
- } else {
- count += skipped;
- }
+ long skipped;
+ while ((skipped = skipUpTo(in, Integer.MAX_VALUE)) > 0) {
+ count += skipped;
}
+ return count;
}
- private static final byte[] countBuffer = new byte[BUF_SIZE];
-
private long countByReading(InputStream in) throws IOException {
long count = 0;
long read;
- while ((read = in.read(countBuffer)) != -1) {
+ while ((read = in.read(ByteStreams.skipBuffer)) != -1) {
count += read;
}
return count;
@@ -431,10 +459,10 @@ public abstract class ByteSource {
*/
private final class SlicedByteSource extends ByteSource {
- private final long offset;
- private final long length;
+ final long offset;
+ final long length;
- private SlicedByteSource(long offset, long length) {
+ SlicedByteSource(long offset, long length) {
checkArgument(offset >= 0, "offset (%s) may not be negative", offset);
checkArgument(length >= 0, "length (%s) may not be negative", length);
this.offset = offset;
@@ -453,8 +481,9 @@ public abstract class ByteSource {
private InputStream sliceStream(InputStream in) throws IOException {
if (offset > 0) {
+ long skipped;
try {
- ByteStreams.skipFully(in, offset);
+ skipped = ByteStreams.skipUpTo(in, offset);
} catch (Throwable e) {
Closer closer = Closer.create();
closer.register(in);
@@ -464,6 +493,12 @@ public abstract class ByteSource {
closer.close();
}
}
+
+ if (skipped < offset) {
+ // offset was beyond EOF
+ in.close();
+ return new ByteArrayInputStream(new byte[0]);
+ }
}
return ByteStreams.limit(in, length);
}
@@ -482,6 +517,17 @@ public abstract class ByteSource {
}
@Override
+ public Optional<Long> sizeIfKnown() {
+ Optional<Long> optionalUnslicedSize = ByteSource.this.sizeIfKnown();
+ if (optionalUnslicedSize.isPresent()) {
+ long unslicedSize = optionalUnslicedSize.get();
+ long off = Math.min(offset, unslicedSize);
+ return Optional.of(Math.min(length, unslicedSize - off));
+ }
+ return Optional.absent();
+ }
+
+ @Override
public String toString() {
return ByteSource.this.toString() + ".slice(" + offset + ", " + length + ")";
}
@@ -489,15 +535,24 @@ public abstract class ByteSource {
private static class ByteArrayByteSource extends ByteSource {
- protected final byte[] bytes;
+ final byte[] bytes;
+ final int offset;
+ final int length;
+
+ ByteArrayByteSource(byte[] bytes) {
+ this(bytes, 0, bytes.length);
+ }
- protected ByteArrayByteSource(byte[] bytes) {
- this.bytes = checkNotNull(bytes);
+ // NOTE: Preconditions are enforced by slice, the only non-trivial caller.
+ ByteArrayByteSource(byte[] bytes, int offset, int length) {
+ this.bytes = bytes;
+ this.offset = offset;
+ this.length = length;
}
@Override
public InputStream openStream() {
- return new ByteArrayInputStream(bytes);
+ return new ByteArrayInputStream(bytes, offset, length);
}
@Override
@@ -507,50 +562,64 @@ public abstract class ByteSource {
@Override
public boolean isEmpty() {
- return bytes.length == 0;
+ return length == 0;
}
@Override
public long size() {
- return bytes.length;
+ return length;
+ }
+
+ @Override
+ public Optional<Long> sizeIfKnown() {
+ return Optional.of((long) length);
}
@Override
public byte[] read() {
- return bytes.clone();
+ return Arrays.copyOfRange(bytes, offset, offset + length);
}
@Override
public long copyTo(OutputStream output) throws IOException {
- output.write(bytes);
- return bytes.length;
+ output.write(bytes, offset, length);
+ return length;
}
@Override
public <T> T read(ByteProcessor<T> processor) throws IOException {
- processor.processBytes(bytes, 0, bytes.length);
+ processor.processBytes(bytes, offset, length);
return processor.getResult();
}
@Override
public HashCode hash(HashFunction hashFunction) throws IOException {
- return hashFunction.hashBytes(bytes);
+ return hashFunction.hashBytes(bytes, offset, length);
}
- // TODO(user): Possibly override slice()
+ @Override
+ public ByteSource slice(long offset, long length) {
+ checkArgument(offset >= 0, "offset (%s) may not be negative", offset);
+ checkArgument(length >= 0, "length (%s) may not be negative", length);
+
+ offset = Math.min(offset, this.length);
+ length = Math.min(length, this.length - offset);
+ int newOffset = this.offset + (int) offset;
+ return new ByteArrayByteSource(bytes, newOffset, (int) length);
+ }
@Override
public String toString() {
return "ByteSource.wrap("
- + Ascii.truncate(BaseEncoding.base16().encode(bytes), 30, "...") + ")";
+ + Ascii.truncate(BaseEncoding.base16().encode(bytes, offset, length), 30, "...") + ")";
}
}
private static final class EmptyByteSource extends ByteArrayByteSource {
- private static final EmptyByteSource INSTANCE = new EmptyByteSource();
+ static final EmptyByteSource INSTANCE = new EmptyByteSource();
- private EmptyByteSource() {
+ EmptyByteSource() {
super(new byte[0]);
}
@@ -573,7 +642,7 @@ public abstract class ByteSource {
private static final class ConcatenatedByteSource extends ByteSource {
- private final Iterable<? extends ByteSource> sources;
+ final Iterable<? extends ByteSource> sources;
ConcatenatedByteSource(Iterable<? extends ByteSource> sources) {
this.sources = checkNotNull(sources);
@@ -595,6 +664,19 @@ public abstract class ByteSource {
}
@Override
+ public Optional<Long> sizeIfKnown() {
+ long result = 0L;
+ for (ByteSource source : sources) {
+ Optional<Long> sizeIfKnown = source.sizeIfKnown();
+ if (!sizeIfKnown.isPresent()) {
+ return Optional.absent();
+ }
+ result += sizeIfKnown.get();
+ }
+ return Optional.of(result);
+ }
+
+ @Override
public long size() throws IOException {
long result = 0L;
for (ByteSource source : sources) {
diff --git a/guava/src/com/google/common/io/ByteStreams.java b/guava/src/com/google/common/io/ByteStreams.java
index db83a7f..4d2d36c 100644
--- a/guava/src/com/google/common/io/ByteStreams.java
+++ b/guava/src/com/google/common/io/ByteStreams.java
@@ -34,6 +34,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Arrays;
@@ -47,7 +48,46 @@ import java.util.Arrays;
*/
@Beta
public final class ByteStreams {
- private static final int BUF_SIZE = 0x1000; // 4K
+
+ /**
+ * Default size of buffers allocated for copies.
+ */
+ static final int BUF_SIZE = 8192;
+
+ /**
+ * A buffer for skipping bytes in an input stream. Only written to and never read, so actual
+ * contents don't matter.
+ */
+ static final byte[] skipBuffer = new byte[BUF_SIZE];
+
+ /**
+ * There are three methods to implement {@link FileChannel#transferTo(long, long,
+ * WritableByteChannel)}:
+ *
+ * <ol>
+ * <li> Use sendfile(2) or equivalent. Requires that both the input channel and the output channel
+ * have their own file descriptors. Generally this only happens when both channels are files or
+ * sockets. This performs zero copies - the bytes never enter userspace.</li>
+ * <li> Use mmap(2) or equivalent. Requires that either the input channel or the output channel
+ * have file descriptors. Bytes are copied from the file into a kernel buffer, then directly
+ * into the other buffer (userspace). Note that if the file is very large, a naive
+ * implementation will effectively put the whole file in memory. On many systems with paging
+ * and virtual memory, this is not a problem - because it is mapped read-only, the kernel can
+ * always page it to disk "for free". However, on systems where killing processes happens all
+ * the time in normal conditions (i.e., android) the OS must make a tradeoff between paging
+ * memory and killing other processes - so allocating a gigantic buffer and then sequentially
+ * accessing it could result in other processes dying. This is solvable via madvise(2), but
+ * that obviously doesn't exist in java.</li>
+ * <li> Ordinary copy. Kernel copies bytes into a kernel buffer, from a kernel buffer into a
+ * userspace buffer (byte[] or ByteBuffer), then copies them from that buffer into the
+ * destination channel.</li>
+ * </ol>
+ *
+ * This value is intended to be large enough to make the overhead of system calls negligible,
+ * without being so large that it causes problems for systems with atypical memory management if
+ * approaches 2 or 3 are used.
+ */
+ private static final int ZERO_COPY_CHUNK_SIZE = 512 * 1024;
private ByteStreams() {}
@@ -90,6 +130,19 @@ public final class ByteStreams {
WritableByteChannel to) throws IOException {
checkNotNull(from);
checkNotNull(to);
+ if (from instanceof FileChannel) {
+ FileChannel sourceChannel = (FileChannel) from;
+ long oldPosition = sourceChannel.position();
+ long position = oldPosition;
+ long copied;
+ do {
+ copied = sourceChannel.transferTo(position, ZERO_COPY_CHUNK_SIZE, to);
+ position += copied;
+ sourceChannel.position(position);
+ } while (copied > 0 || position < sourceChannel.size());
+ return position - oldPosition;
+ }
+
ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE);
long total = 0;
while (from.read(buf) != -1) {
@@ -346,7 +399,11 @@ public final class ByteStreams {
* @throws IllegalArgumentException if {@code size} is negative
*/
public static ByteArrayDataOutput newDataOutput(int size) {
- checkArgument(size >= 0, "Invalid size: %s", size);
+ // When called at high frequency, boxing size generates too much garbage,
+ // so avoid doing that if we can.
+ if (size < 0) {
+ throw new IllegalArgumentException(String.format("Invalid size: %s", size));
+ }
return newDataOutput(new ByteArrayOutputStream(size));
}
@@ -658,21 +715,53 @@ public final class ByteStreams {
* support skipping
*/
public static void skipFully(InputStream in, long n) throws IOException {
- long toSkip = n;
- while (n > 0) {
- long amt = in.skip(n);
- if (amt == 0) {
- // Force a blocking read to avoid infinite loop
- if (in.read() == -1) {
- long skipped = toSkip - n;
- throw new EOFException("reached end of stream after skipping "
- + skipped + " bytes; " + toSkip + " bytes expected");
+ long skipped = skipUpTo(in, n);
+ if (skipped < n) {
+ throw new EOFException("reached end of stream after skipping "
+ + skipped + " bytes; " + n + " bytes expected");
+ }
+ }
+
+ /**
+ * Discards up to {@code n} bytes of data from the input stream. This method
+ * will block until either the full amount has been skipped or until the end
+ * of the stream is reached, whichever happens first. Returns the total number
+ * of bytes skipped.
+ */
+ static long skipUpTo(InputStream in, final long n) throws IOException {
+ long totalSkipped = 0;
+
+ while (totalSkipped < n) {
+ long remaining = n - totalSkipped;
+
+ long skipped = skipSafely(in, remaining);
+
+ if (skipped == 0) {
+ // Do a buffered read since skipSafely could return 0 repeatedly, for example if
+ // in.available() always returns 0 (the default).
+ int skip = (int) Math.min(remaining, skipBuffer.length);
+ if ((skipped = in.read(skipBuffer, 0, skip)) == -1) {
+ // Reached EOF
+ break;
}
- n--;
- } else {
- n -= amt;
}
+
+ totalSkipped += skipped;
}
+
+ return totalSkipped;
+ }
+
+ /**
+ * Attempts to skip up to {@code n} bytes from the given input stream, but not more than
+ * {@code in.available()} bytes. This prevents {@code FileInputStream} from skipping more bytes
+ * than actually remain in the file, something that it
+ * {@linkplain FileInputStream#skip(long) specifies} it can do in its Javadoc despite the fact
+ * that it is violating the contract of {@code InputStream.skip()}.
+ */
+ private static long skipSafely(InputStream in, long n) throws IOException {
+ int available = in.available();
+ return available == 0 ? 0 : in.skip(Math.min(available, n));
}
/**
diff --git a/guava/src/com/google/common/io/CharSequenceReader.java b/guava/src/com/google/common/io/CharSequenceReader.java
index 34ef832..afe0c73 100644
--- a/guava/src/com/google/common/io/CharSequenceReader.java
+++ b/guava/src/com/google/common/io/CharSequenceReader.java
@@ -30,7 +30,7 @@ import java.nio.CharBuffer;
*
* @author Colin Decker
*/
-// TODO(user): make this public? as a type, or a method in CharStreams?
+// TODO(cgdecker): make this public? as a type, or a method in CharStreams?
final class CharSequenceReader extends Reader {
private CharSequence seq;
diff --git a/guava/src/com/google/common/io/CharSource.java b/guava/src/com/google/common/io/CharSource.java
index fd47bbf..32273b0 100644
--- a/guava/src/com/google/common/io/CharSource.java
+++ b/guava/src/com/google/common/io/CharSource.java
@@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.base.Ascii;
+import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.ImmutableList;
@@ -95,6 +96,71 @@ public abstract class CharSource {
}
/**
+ * Returns the size of this source in chars, if the size can be easily determined without
+ * actually opening the data stream.
+ *
+ * <p>The default implementation returns {@link Optional#absent}. Some sources, such as a
+ * {@code CharSequence}, may return a non-absent value. Note that in such cases, it is
+ * <i>possible</i> that this method will return a different number of chars than would be
+ * returned by reading all of the chars.
+ *
+ * <p>Additionally, for mutable sources such as {@code StringBuilder}s, a subsequent read
+ * may return a different number of chars if the contents are changed.
+ *
+ * @since 19.0
+ */
+ @Beta
+ public Optional<Long> lengthIfKnown() {
+ return Optional.absent();
+ }
+
+ /**
+ * Returns the length of this source in chars, even if doing so requires opening and traversing
+ * an entire stream. To avoid a potentially expensive operation, see {@link #lengthIfKnown}.
+ *
+ * <p>The default implementation calls {@link #lengthIfKnown} and returns the value if present.
+ * If absent, it will fall back to a heavyweight operation that will open a stream,
+ * {@link Reader#skip(long) skip} to the end of the stream, and return the total number of chars
+ * that were skipped.
+ *
+ * <p>Note that for sources that implement {@link #lengthIfKnown} to provide a more efficient
+ * implementation, it is <i>possible</i> that this method will return a different number of chars
+ * than would be returned by reading all of the chars.
+ *
+ * <p>In either case, for mutable sources such as files, a subsequent read may return a different
+ * number of chars if the contents are changed.
+ *
+ * @throws IOException if an I/O error occurs in the process of reading the length of this source
+ * @since 19.0
+ */
+ @Beta
+ public long length() throws IOException {
+ Optional<Long> lengthIfKnown = lengthIfKnown();
+ if (lengthIfKnown.isPresent()) {
+ return lengthIfKnown.get();
+ }
+
+ Closer closer = Closer.create();
+ try {
+ Reader reader = closer.register(openStream());
+ return countBySkipping(reader);
+ } catch (Throwable e) {
+ throw closer.rethrow(e);
+ } finally {
+ closer.close();
+ }
+ }
+
+ private long countBySkipping(Reader reader) throws IOException {
+ long count = 0;
+ long read;
+ while ((read = reader.skip(Long.MAX_VALUE)) != 0) {
+ count += read;
+ }
+ return count;
+ }
+
+ /**
* Appends the contents of this source to the given {@link Appendable} (such as a {@link Writer}).
* Does not close {@code appendable} if it is {@code Closeable}.
*
@@ -162,7 +228,7 @@ public abstract class CharSource {
*
* @throws IOException if an I/O error occurs in the process of reading from this source
*/
- public @Nullable String readFirstLine() throws IOException {
+ @Nullable public String readFirstLine() throws IOException {
Closer closer = Closer.create();
try {
BufferedReader reader = closer.register(openBufferedStream());
@@ -231,13 +297,22 @@ public abstract class CharSource {
}
/**
- * Returns whether the source has zero chars. The default implementation is to open a stream and
- * check for EOF.
+ * Returns whether the source has zero chars. The default implementation returns true if
+ * {@link #lengthIfKnown} returns zero, falling back to opening a stream and checking
+ * for EOF if the length is not known.
+ *
+ * <p>Note that, in cases where {@code lengthIfKnown} returns zero, it is <i>possible</i> that
+ * chars are actually available for reading. This means that a source may return {@code true} from
+ * {@code isEmpty()} despite having readable content.
*
* @throws IOException if an I/O error occurs
* @since 15.0
*/
public boolean isEmpty() throws IOException {
+ Optional<Long> lengthIfKnown = lengthIfKnown();
+ if (lengthIfKnown.isPresent() && lengthIfKnown.get() == 0L) {
+ return true;
+ }
Closer closer = Closer.create();
try {
Reader reader = closer.register(openStream());
@@ -348,6 +423,16 @@ public abstract class CharSource {
return seq.length() == 0;
}
+ @Override
+ public long length() {
+ return seq.length();
+ }
+
+ @Override
+ public Optional<Long> lengthIfKnown() {
+ return Optional.of((long) seq.length());
+ }
+
/**
* Returns an iterable over the lines in the string. If the string ends in
* a newline, a final empty string is not included to match the behavior of
@@ -441,6 +526,28 @@ public abstract class CharSource {
}
@Override
+ public Optional<Long> lengthIfKnown() {
+ long result = 0L;
+ for (CharSource source : sources) {
+ Optional<Long> lengthIfKnown = source.lengthIfKnown();
+ if (!lengthIfKnown.isPresent()) {
+ return Optional.absent();
+ }
+ result += lengthIfKnown.get();
+ }
+ return Optional.of(result);
+ }
+
+ @Override
+ public long length() throws IOException {
+ long result = 0L;
+ for (CharSource source : sources) {
+ result += source.length();
+ }
+ return result;
+ }
+
+ @Override
public String toString() {
return "CharSource.concat(" + sources + ")";
}
diff --git a/guava/src/com/google/common/io/CharStreams.java b/guava/src/com/google/common/io/CharStreams.java
index 8c8adce..696417d 100644
--- a/guava/src/com/google/common/io/CharStreams.java
+++ b/guava/src/com/google/common/io/CharStreams.java
@@ -164,14 +164,9 @@ public final class CharStreams {
while (n > 0) {
long amt = reader.skip(n);
if (amt == 0) {
- // force a blocking read
- if (reader.read() == -1) {
- throw new EOFException();
- }
- n--;
- } else {
- n -= amt;
+ throw new EOFException();
}
+ n -= amt;
}
}
@@ -260,7 +255,7 @@ public final class CharStreams {
return new AppendableWriter(target);
}
- // TODO(user): Remove these once Input/OutputSupplier methods are removed
+ // TODO(cgdecker): Remove these once Input/OutputSupplier methods are removed
static Reader asReader(final Readable readable) {
checkNotNull(readable);
diff --git a/guava/src/com/google/common/io/CountingInputStream.java b/guava/src/com/google/common/io/CountingInputStream.java
index 573099a..eeb4d00 100644
--- a/guava/src/com/google/common/io/CountingInputStream.java
+++ b/guava/src/com/google/common/io/CountingInputStream.java
@@ -16,14 +16,14 @@
package com.google.common.io;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import com.google.common.annotations.Beta;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
-import javax.annotation.Nullable;
-
/**
* An {@link InputStream} that counts the number of bytes read.
*
@@ -41,8 +41,8 @@ public final class CountingInputStream extends FilterInputStream {
*
* @param in the input stream to be wrapped
*/
- public CountingInputStream(@Nullable InputStream in) {
- super(in);
+ public CountingInputStream(InputStream in) {
+ super(checkNotNull(in));
}
/** Returns the number of bytes read. */
diff --git a/guava/src/com/google/common/io/CountingOutputStream.java b/guava/src/com/google/common/io/CountingOutputStream.java
index 8b6a4fe..e6ba21e 100644
--- a/guava/src/com/google/common/io/CountingOutputStream.java
+++ b/guava/src/com/google/common/io/CountingOutputStream.java
@@ -16,14 +16,14 @@
package com.google.common.io;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import com.google.common.annotations.Beta;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import javax.annotation.Nullable;
-
/**
* An OutputStream that counts the number of bytes written.
*
@@ -40,8 +40,8 @@ public final class CountingOutputStream extends FilterOutputStream {
*
* @param out the output stream to be wrapped
*/
- public CountingOutputStream(@Nullable OutputStream out) {
- super(out);
+ public CountingOutputStream(OutputStream out) {
+ super(checkNotNull(out));
}
/** Returns the number of bytes written. */
diff --git a/guava/src/com/google/common/io/Files.java b/guava/src/com/google/common/io/Files.java
index 2eef50e..c83a1b2 100644
--- a/guava/src/com/google/common/io/Files.java
+++ b/guava/src/com/google/common/io/Files.java
@@ -23,6 +23,7 @@ import static com.google.common.io.FileWriteMode.APPEND;
import com.google.common.annotations.Beta;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
@@ -126,6 +127,15 @@ public final class Files {
}
@Override
+ public Optional<Long> sizeIfKnown() {
+ if (file.isFile()) {
+ return Optional.of(file.length());
+ } else {
+ return Optional.absent();
+ }
+ }
+
+ @Override
public long size() throws IOException {
if (!file.isFile()) {
throw new FileNotFoundException(file.toString());
diff --git a/guava/src/com/google/common/io/GwtWorkarounds.java b/guava/src/com/google/common/io/GwtWorkarounds.java
deleted file mode 100644
index 285df59..0000000
--- a/guava/src/com/google/common/io/GwtWorkarounds.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (C) 2012 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.google.common.io;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkPositionIndexes;
-
-import com.google.common.annotations.GwtCompatible;
-import com.google.common.annotations.GwtIncompatible;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-
-/**
- * Provides simple GWT-compatible substitutes for {@code InputStream}, {@code OutputStream},
- * {@code Reader}, and {@code Writer} so that {@code BaseEncoding} can use streaming implementations
- * while remaining GWT-compatible.
- *
- * @author Louis Wasserman
- */
- at GwtCompatible(emulated = true)
-final class GwtWorkarounds {
- private GwtWorkarounds() {}
-
- /**
- * A GWT-compatible substitute for a {@code Reader}.
- */
- interface CharInput {
- int read() throws IOException;
- void close() throws IOException;
- }
-
- /**
- * Views a {@code Reader} as a {@code CharInput}.
- */
- @GwtIncompatible("Reader")
- static CharInput asCharInput(final Reader reader) {
- checkNotNull(reader);
- return new CharInput() {
- @Override
- public int read() throws IOException {
- return reader.read();
- }
-
- @Override
- public void close() throws IOException {
- reader.close();
- }
- };
- }
-
- /**
- * Views a {@code CharSequence} as a {@code CharInput}.
- */
- static CharInput asCharInput(final CharSequence chars) {
- checkNotNull(chars);
- return new CharInput() {
- int index = 0;
-
- @Override
- public int read() {
- if (index < chars.length()) {
- return chars.charAt(index++);
- } else {
- return -1;
- }
- }
-
- @Override
- public void close() {
- index = chars.length();
- }
- };
- }
-
- /**
- * A GWT-compatible substitute for an {@code InputStream}.
- */
- interface ByteInput {
- int read() throws IOException;
- void close() throws IOException;
- }
-
- /**
- * Views a {@code ByteInput} as an {@code InputStream}.
- */
- @GwtIncompatible("InputStream")
- static InputStream asInputStream(final ByteInput input) {
- checkNotNull(input);
- return new InputStream() {
- @Override
- public int read() throws IOException {
- return input.read();
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- checkNotNull(b);
- checkPositionIndexes(off, off + len, b.length);
- if (len == 0) {
- return 0;
- }
- int firstByte = read();
- if (firstByte == -1) {
- return -1;
- }
- b[off] = (byte) firstByte;
- for (int dst = 1; dst < len; dst++) {
- int readByte = read();
- if (readByte == -1) {
- return dst;
- }
- b[off + dst] = (byte) readByte;
- }
- return len;
- }
-
- @Override
- public void close() throws IOException {
- input.close();
- }
- };
- }
-
- /**
- * A GWT-compatible substitute for an {@code OutputStream}.
- */
- interface ByteOutput {
- void write(byte b) throws IOException;
- void flush() throws IOException;
- void close() throws IOException;
- }
-
- /**
- * Views a {@code ByteOutput} as an {@code OutputStream}.
- */
- @GwtIncompatible("OutputStream")
- static OutputStream asOutputStream(final ByteOutput output) {
- checkNotNull(output);
- return new OutputStream() {
- @Override
- public void write(int b) throws IOException {
- output.write((byte) b);
- }
-
- @Override
- public void flush() throws IOException {
- output.flush();
- }
-
- @Override
- public void close() throws IOException {
- output.close();
- }
- };
- }
-
- /**
- * A GWT-compatible substitute for a {@code Writer}.
- */
- interface CharOutput {
- void write(char c) throws IOException;
- void flush() throws IOException;
- void close() throws IOException;
- }
-
- /**
- * Views a {@code Writer} as a {@code CharOutput}.
- */
- @GwtIncompatible("Writer")
- static CharOutput asCharOutput(final Writer writer) {
- checkNotNull(writer);
- return new CharOutput() {
- @Override
- public void write(char c) throws IOException {
- writer.append(c);
- }
-
- @Override
- public void flush() throws IOException {
- writer.flush();
- }
-
- @Override
- public void close() throws IOException {
- writer.close();
- }
- };
- }
-
- /**
- * Returns a {@code CharOutput} whose {@code toString()} method can be used
- * to get the combined output.
- */
- static CharOutput stringBuilderOutput(int initialSize) {
- final StringBuilder builder = new StringBuilder(initialSize);
- return new CharOutput() {
-
- @Override
- public void write(char c) {
- builder.append(c);
- }
-
- @Override
- public void flush() {}
-
- @Override
- public void close() {}
-
- @Override
- public String toString() {
- return builder.toString();
- }
- };
- }
-}
diff --git a/guava/src/com/google/common/io/package-info.java b/guava/src/com/google/common/io/package-info.java
index b9df46e..252313a 100644
--- a/guava/src/com/google/common/io/package-info.java
+++ b/guava/src/com/google/common/io/package-info.java
@@ -28,7 +28,7 @@
* <p>This package is a part of the open-source
* <a href="http://guava-libraries.googlecode.com">Guava libraries</a>. For more information on
* Sources and Sinks as well as other features of this package, see
- * <a href="https://code.google.com/p/guava-libraries/wiki/IOExplained">I/O Explained</a> on the
+ * <a href="https://github.com/google/guava/wiki/IOExplained">I/O Explained</a> on the
* Guava wiki.
*
* @author Chris Nokleberg
diff --git a/guava/src/com/google/common/math/DoubleMath.java b/guava/src/com/google/common/math/DoubleMath.java
index 66c5e8d..ee9b693 100644
--- a/guava/src/com/google/common/math/DoubleMath.java
+++ b/guava/src/com/google/common/math/DoubleMath.java
@@ -383,91 +383,120 @@ public final class DoubleMath {
}
}
- @GwtIncompatible("com.google.common.math.DoubleUtils")
- private static final class MeanAccumulator {
-
- private long count = 0;
- private double mean = 0.0;
-
- void add(double value) {
- checkArgument(isFinite(value));
- ++count;
- // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
- mean += (value - mean) / count;
- }
-
- double mean() {
- checkArgument(count > 0, "Cannot take mean of 0 values");
- return mean;
- }
- }
-
/**
- * Returns the arithmetic mean of the values. There must be at least one value, and they must all
- * be finite.
+ * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+ * {@code values}.
+ *
+ * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+ * the arithmetic mean of the population.
+ *
+ * @param values a nonempty series of values
+ * @throws IllegalArgumentException if {@code values} is empty or contains any non-finite value
*/
- @GwtIncompatible("MeanAccumulator")
+ @GwtIncompatible("com.google.common.math.DoubleUtils")
public static double mean(double... values) {
- MeanAccumulator accumulator = new MeanAccumulator();
- for (double value : values) {
- accumulator.add(value);
+ checkArgument(values.length > 0, "Cannot take mean of 0 values");
+ long count = 1;
+ double mean = checkFinite(values[0]);
+ for (int index = 1; index < values.length; ++index) {
+ checkFinite(values[index]);
+ count++;
+ // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
+ mean += (values[index] - mean) / count;
}
- return accumulator.mean();
+ return mean;
}
/**
- * Returns the arithmetic mean of the values. There must be at least one value. The values will
- * be converted to doubles, which does not cause any loss of precision for ints.
+ * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+ * {@code values}.
+ *
+ * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+ * the arithmetic mean of the population.
+ *
+ * @param values a nonempty series of values
+ * @throws IllegalArgumentException if {@code values} is empty
*/
- @GwtIncompatible("MeanAccumulator")
public static double mean(int... values) {
- MeanAccumulator accumulator = new MeanAccumulator();
- for (int value : values) {
- accumulator.add(value);
+ checkArgument(values.length > 0, "Cannot take mean of 0 values");
+ // The upper bound on the the length of an array and the bounds on the int values mean that, in
+ // this case only, we can compute the sum as a long without risking overflow or loss of
+ // precision. So we do that, as it's slightly quicker than the Knuth algorithm.
+ long sum = 0;
+ for (int index = 0; index < values.length; ++index) {
+ sum += values[index];
}
- return accumulator.mean();
+ return (double) sum / values.length;
}
/**
- * Returns the arithmetic mean of the values. There must be at least one value. The values will
- * be converted to doubles, which causes loss of precision for longs of magnitude over 2^53
- * (slightly over 9e15).
+ * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+ * {@code values}.
+ *
+ * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+ * the arithmetic mean of the population.
+ *
+ * @param values a nonempty series of values, which will be converted to {@code double} values
+ * (this may cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15))
+ * @throws IllegalArgumentException if {@code values} is empty
*/
- @GwtIncompatible("MeanAccumulator")
public static double mean(long... values) {
- MeanAccumulator accumulator = new MeanAccumulator();
- for (long value : values) {
- accumulator.add(value);
+ checkArgument(values.length > 0, "Cannot take mean of 0 values");
+ long count = 1;
+ double mean = values[0];
+ for (int index = 1; index < values.length; ++index) {
+ count++;
+ // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
+ mean += (values[index] - mean) / count;
}
- return accumulator.mean();
+ return mean;
}
/**
- * Returns the arithmetic mean of the values. There must be at least one value, and they must all
- * be finite. The values will be converted to doubles, which may cause loss of precision for some
- * numeric types.
+ * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+ * {@code values}.
+ *
+ * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+ * the arithmetic mean of the population.
+ *
+ * @param values a nonempty series of values, which will be converted to {@code double} values
+ * (this may cause loss of precision)
+ * @throws IllegalArgumentException if {@code values} is empty or contains any non-finite value
*/
- @GwtIncompatible("MeanAccumulator")
+ @GwtIncompatible("com.google.common.math.DoubleUtils")
public static double mean(Iterable<? extends Number> values) {
- MeanAccumulator accumulator = new MeanAccumulator();
- for (Number value : values) {
- accumulator.add(value.doubleValue());
- }
- return accumulator.mean();
+ return mean(values.iterator());
}
/**
- * Returns the arithmetic mean of the values. There must be at least one value, and they must all
- * be finite. The values will be converted to doubles, which may cause loss of precision for some
- * numeric types.
+ * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of
+ * {@code values}.
+ *
+ * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
+ * the arithmetic mean of the population.
+ *
+ * @param values a nonempty series of values, which will be converted to {@code double} values
+ * (this may cause loss of precision)
+ * @throws IllegalArgumentException if {@code values} is empty or contains any non-finite value
*/
- @GwtIncompatible("MeanAccumulator")
+ @GwtIncompatible("com.google.common.math.DoubleUtils")
public static double mean(Iterator<? extends Number> values) {
- MeanAccumulator accumulator = new MeanAccumulator();
+ checkArgument(values.hasNext(), "Cannot take mean of 0 values");
+ long count = 1;
+ double mean = checkFinite(values.next().doubleValue());
while (values.hasNext()) {
- accumulator.add(values.next().doubleValue());
+ double value = checkFinite(values.next().doubleValue());
+ count++;
+ // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
+ mean += (value - mean) / count;
}
- return accumulator.mean();
+ return mean;
+ }
+
+ @GwtIncompatible("com.google.common.math.DoubleUtils")
+ private static double checkFinite(double argument) {
+ checkArgument(isFinite(argument));
+ return argument;
}
private DoubleMath() {}
diff --git a/guava/src/com/google/common/math/LongMath.java b/guava/src/com/google/common/math/LongMath.java
index 425aac6..7380ce7 100644
--- a/guava/src/com/google/common/math/LongMath.java
+++ b/guava/src/com/google/common/math/LongMath.java
@@ -30,6 +30,7 @@ import static java.math.RoundingMode.HALF_UP;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.primitives.UnsignedLongs;
import java.math.BigInteger;
import java.math.RoundingMode;
@@ -593,7 +594,7 @@ public final class LongMath {
}
k >>= 1;
if (k > 0) {
- checkNoOverflow(b <= FLOOR_SQRT_MAX_LONG);
+ checkNoOverflow(-FLOOR_SQRT_MAX_LONG <= b && b <= FLOOR_SQRT_MAX_LONG);
b *= b;
}
}
@@ -757,5 +758,188 @@ public final class LongMath {
return (x & y) + ((x ^ y) >> 1);
}
+ /*
+ * If n <= millerRabinBases[i][0], then testing n against bases millerRabinBases[i][1..]
+ * suffices to prove its primality. Values from miller-rabin.appspot.com.
+ *
+ * NOTE: We could get slightly better bases that would be treated as unsigned, but benchmarks
+ * showed negligible performance improvements.
+ */
+ private static final long[][] millerRabinBaseSets = {
+ {291830, 126401071349994536L},
+ {885594168, 725270293939359937L, 3569819667048198375L},
+ {273919523040L, 15, 7363882082L, 992620450144556L},
+ {47636622961200L, 2, 2570940, 211991001, 3749873356L},
+ {7999252175582850L,
+ 2, 4130806001517L, 149795463772692060L, 186635894390467037L, 3967304179347715805L},
+ {585226005592931976L,
+ 2, 123635709730000L, 9233062284813009L, 43835965440333360L, 761179012939631437L,
+ 1263739024124850375L},
+ {Long.MAX_VALUE,
+ 2, 325, 9375, 28178, 450775, 9780504, 1795265022}
+ };
+
+ private enum MillerRabinTester {
+ /**
+ * Works for inputs <= FLOOR_SQRT_MAX_LONG.
+ */
+ SMALL {
+ @Override
+ long mulMod(long a, long b, long m) {
+ /*
+ * NOTE(lowasser, 2015-Feb-12): Benchmarks suggest that changing this to
+ * UnsignedLongs.remainder and increasing the threshold to 2^32 doesn't pay for itself,
+ * and adding another enum constant hurts performance further -- I suspect because
+ * bimorphic implementation is a sweet spot for the JVM.
+ */
+ return (a * b) % m;
+ }
+
+ @Override
+ long squareMod(long a, long m) {
+ return (a * a) % m;
+ }
+ },
+ /**
+ * Works for all nonnegative signed longs.
+ */
+ LARGE {
+ /**
+ * Returns (a + b) mod m. Precondition: 0 <= a, b < m < 2^63.
+ */
+ private long plusMod(long a, long b, long m) {
+ return (a >= m - b) ? (a + b - m) : (a + b);
+ }
+
+ /**
+ * Returns (a * 2^32) mod m. a may be any unsigned long.
+ */
+ private long times2ToThe32Mod(long a, long m) {
+ int remainingPowersOf2 = 32;
+ do {
+ int shift = Math.min(remainingPowersOf2, Long.numberOfLeadingZeros(a));
+ // shift is either the number of powers of 2 left to multiply a by, or the biggest shift
+ // possible while keeping a in an unsigned long.
+ a = UnsignedLongs.remainder(a << shift, m);
+ remainingPowersOf2 -= shift;
+ } while (remainingPowersOf2 > 0);
+ return a;
+ }
+
+ @Override
+ long mulMod(long a, long b, long m) {
+ long aHi = a >>> 32; // < 2^31
+ long bHi = b >>> 32; // < 2^31
+ long aLo = a & 0xFFFFFFFFL; // < 2^32
+ long bLo = b & 0xFFFFFFFFL; // < 2^32
+
+ /*
+ * a * b == aHi * bHi * 2^64 + (aHi * bLo + aLo * bHi) * 2^63 + aLo * bLo.
+ * == (aHi * bHi * 2^32 + aHi * bLo + aLo * bHi) * 2^32 + aLo * bLo
+ *
+ * We carry out this computation in modular arithmetic. Since times2ToThe32Mod accepts
+ * any unsigned long, we don't have to do a mod on every operation, only when intermediate
+ * results can exceed 2^63.
+ */
+ long result = times2ToThe32Mod(aHi * bHi /* < 2^62 */, m); // < m < 2^63
+ result += aHi * bLo; // aHi * bLo < 2^63, result < 2^64
+ if (result < 0) {
+ result = UnsignedLongs.remainder(result, m);
+ }
+ // result < 2^63 again
+ result += aLo * bHi; // aLo * bHi < 2^63, result < 2^64
+ result = times2ToThe32Mod(result, m); // result < m < 2^63
+ return plusMod(
+ result,
+ UnsignedLongs.remainder(aLo * bLo /* < 2^64 */, m),
+ m);
+ }
+
+ @Override
+ long squareMod(long a, long m) {
+ long aHi = a >>> 32; // < 2^31
+ long aLo = a & 0xFFFFFFFFL; // < 2^32
+
+ /*
+ * a^2 == aHi^2 * 2^64 + aHi * aLo * 2^33 + aLo^2
+ * == (aHi^2 * 2^32 + aHi * aLo * 2) * 2^32 + aLo^2
+ * We carry out this computation in modular arithmetic. Since times2ToThe32Mod accepts
+ * any unsigned long, we don't have to do a mod on every operation, only when intermediate
+ * results can exceed 2^63.
+ */
+ long result = times2ToThe32Mod(aHi * aHi /* < 2^62 */, m); // < m < 2^63
+ long hiLo = aHi * aLo * 2;
+ if (hiLo < 0) {
+ hiLo = UnsignedLongs.remainder(hiLo, m);
+ }
+ // hiLo < 2^63
+ result += hiLo; // result < 2^64
+ result = times2ToThe32Mod(result, m); // result < m < 2^63
+ return plusMod(
+ result,
+ UnsignedLongs.remainder(aLo * aLo /* < 2^64 */, m),
+ m);
+ }
+ };
+
+ static boolean test(long base, long n) {
+ // Since base will be considered % n, it's okay if base > FLOOR_SQRT_MAX_LONG,
+ // so long as n <= FLOOR_SQRT_MAX_LONG.
+ return ((n <= FLOOR_SQRT_MAX_LONG) ? SMALL : LARGE).testWitness(base, n);
+ }
+
+ /**
+ * Returns a * b mod m.
+ */
+ abstract long mulMod(long a, long b, long m);
+
+ /**
+ * Returns a^2 mod m.
+ */
+ abstract long squareMod(long a, long m);
+
+ /**
+ * Returns a^p mod m.
+ */
+ private long powMod(long a, long p, long m) {
+ long res = 1;
+ for (; p != 0; p >>= 1) {
+ if ((p & 1) != 0) {
+ res = mulMod(res, a, m);
+ }
+ a = squareMod(a, m);
+ }
+ return res;
+ }
+
+ /**
+ * Returns true if n is a strong probable prime relative to the specified base.
+ */
+ private boolean testWitness(long base, long n) {
+ int r = Long.numberOfTrailingZeros(n - 1);
+ long d = (n - 1) >> r;
+ base %= n;
+ if (base == 0) {
+ return true;
+ }
+ // Calculate a := base^d mod n.
+ long a = powMod(base, d, n);
+ // n passes this test if
+ // base^d = 1 (mod n)
+ // or base^(2^j * d) = -1 (mod n) for some 0 <= j < r.
+ if (a == 1) {
+ return true;
+ }
+ int j = 0;
+ while (a != n - 1) {
+ if (++j == r) {
+ return false;
+ }
+ a = squareMod(a, n);
+ }
+ return true;
+ }
+ }
+
private LongMath() {}
}
diff --git a/guava/src/com/google/common/math/package-info.java b/guava/src/com/google/common/math/package-info.java
index bd17e52..f6720d1 100644
--- a/guava/src/com/google/common/math/package-info.java
+++ b/guava/src/com/google/common/math/package-info.java
@@ -21,7 +21,7 @@
* <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/MathExplained">
+ * "https://github.com/google/guava/wiki/MathExplained">
* math utilities</a>.
*/
@ParametersAreNonnullByDefault
diff --git a/guava/src/com/google/common/net/HttpHeaders.java b/guava/src/com/google/common/net/HttpHeaders.java
index 5e3dbf6..d24e69e 100644
--- a/guava/src/com/google/common/net/HttpHeaders.java
+++ b/guava/src/com/google/common/net/HttpHeaders.java
@@ -248,4 +248,18 @@ public final class HttpHeaders {
public static final String X_USER_IP = "X-User-IP";
/** The HTTP {@code X-XSS-Protection} header field name. */
public static final String X_XSS_PROTECTION = "X-XSS-Protection";
+ /**
+ * The HTTP <a href="http://html.spec.whatwg.org/multipage/semantics.html#hyperlink-auditing">
+ * {@code Ping-From}</a> header field name.
+ *
+ * @since 19.0
+ */
+ public static final String PING_FROM = "Ping-From";
+ /**
+ * The HTTP <a href="http://html.spec.whatwg.org/multipage/semantics.html#hyperlink-auditing">
+ * {@code Ping-To}</a> header field name.
+ *
+ * @since 19.0
+ */
+ public static final String PING_TO = "Ping-To";
}
diff --git a/guava/src/com/google/common/net/InetAddresses.java b/guava/src/com/google/common/net/InetAddresses.java
index 20eb18e..ed8502c 100644
--- a/guava/src/com/google/common/net/InetAddresses.java
+++ b/guava/src/com/google/common/net/InetAddresses.java
@@ -29,6 +29,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Arrays;
+import java.util.Locale;
import javax.annotation.Nullable;
@@ -150,8 +151,7 @@ public final class InetAddresses {
// The argument was malformed, i.e. not an IP string literal.
if (addr == null) {
- throw new IllegalArgumentException(
- String.format("'%s' is not an IP string literal.", ipString));
+ throw formatIllegalArgumentException("'%s' is not an IP string literal.", ipString);
}
return bytesToInetAddress(addr);
@@ -319,7 +319,7 @@ public final class InetAddresses {
* Convert a byte array into an InetAddress.
*
* {@link InetAddress#getByAddress} is documented as throwing a checked
- * exception "if IP address if of illegal length." We replace it with
+ * exception "if IP address is of illegal length." We replace it with
* an unchecked exception, for use by callers who already know that addr
* is an array of length 4 or 16.
*
@@ -498,8 +498,7 @@ public final class InetAddresses {
// Parse the address, and make sure the length/version is correct.
byte[] addr = ipStringToBytes(ipString);
if (addr == null || addr.length != expectBytes) {
- throw new IllegalArgumentException(
- String.format("Not a valid URI IP literal: '%s'", hostAddr));
+ throw formatIllegalArgumentException("Not a valid URI IP literal: '%s'", hostAddr);
}
return bytesToInetAddress(addr);
@@ -804,8 +803,7 @@ public final class InetAddresses {
return getTeredoInfo(ip).getClient();
}
- throw new IllegalArgumentException(
- String.format("'%s' has no embedded IPv4 address.", toAddrString(ip)));
+ throw formatIllegalArgumentException("'%s' has no embedded IPv4 address.", toAddrString(ip));
}
/**
@@ -1031,4 +1029,9 @@ public final class InetAddresses {
}
return true;
}
+
+ private static IllegalArgumentException formatIllegalArgumentException(
+ String format, Object... args) {
+ return new IllegalArgumentException(String.format(Locale.ROOT, format, args));
+ }
}
diff --git a/guava/src/com/google/common/net/MediaType.java b/guava/src/com/google/common/net/MediaType.java
index 1cfd741..3eff0f1 100644
--- a/guava/src/com/google/common/net/MediaType.java
+++ b/guava/src/com/google/common/net/MediaType.java
@@ -230,6 +230,21 @@ public final class MediaType {
public static final MediaType BZIP2 = createConstant(APPLICATION_TYPE, "x-bzip2");
/**
+ * Media type for <a href="https://www.dartlang.org/articles/embedding-in-html/">dart files</a>.
+ *
+ * @since 19.0
+ */
+ public static final MediaType DART_UTF_8 = createConstantUtf8(APPLICATION_TYPE, "dart");
+
+ /**
+ * Media type for <a href="https://goo.gl/dNnKKj">Apple Passbook</a>.
+ *
+ * @since 19.0
+ */
+ public static final MediaType APPLE_PASSBOOK = createConstant(APPLICATION_TYPE,
+ "vnd.apple.pkpass");
+
+ /**
* Media type for <a href="http://en.wikipedia.org/wiki/Embedded_OpenType">Embedded OpenType</a>
* fonts. This is
* <a href="http://www.iana.org/assignments/media-types/application/vnd.ms-fontobject">registered
@@ -279,6 +294,14 @@ public final class MediaType {
public static final MediaType JAVASCRIPT_UTF_8 =
createConstantUtf8(APPLICATION_TYPE, "javascript");
public static final MediaType JSON_UTF_8 = createConstantUtf8(APPLICATION_TYPE, "json");
+ /**
+ * Media type for the
+ * <a href="http://www.w3.org/TR/appmanifest/">Manifest for a web application</a>.
+ *
+ * @since 19.0
+ */
+ public static final MediaType MANIFEST_JSON_UTF_8 =
+ createConstantUtf8(APPLICATION_TYPE, "manifest+json");
public static final MediaType KML = createConstant(APPLICATION_TYPE, "vnd.google-earth.kml+xml");
public static final MediaType KMZ = createConstant(APPLICATION_TYPE, "vnd.google-earth.kmz");
public static final MediaType MBOX = createConstant(APPLICATION_TYPE, "mbox");
@@ -360,6 +383,10 @@ public final class MediaType {
private final String subtype;
private final ImmutableListMultimap<String, String> parameters;
+ private String toString;
+
+ private int hashCode;
+
private MediaType(String type, String subtype,
ImmutableListMultimap<String, String> parameters) {
this.type = type;
@@ -692,7 +719,13 @@ public final class MediaType {
}
@Override public int hashCode() {
- return Objects.hashCode(type, subtype, parametersAsMap());
+ // racy single-check idiom
+ int h = hashCode;
+ if (h == 0) {
+ h = Objects.hashCode(type, subtype, parametersAsMap());
+ hashCode = h;
+ }
+ return h;
}
private static final MapJoiner PARAMETER_JOINER = Joiner.on("; ").withKeyValueSeparator("=");
@@ -702,6 +735,16 @@ public final class MediaType {
* href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>.
*/
@Override public String toString() {
+ // racy single-check idiom, safe because String is immutable
+ String result = toString;
+ if (result == null) {
+ result = computeToString();
+ toString = result;
+ }
+ return result;
+ }
+
+ private String computeToString() {
StringBuilder builder = new StringBuilder().append(type).append('/').append(subtype);
if (!parameters.isEmpty()) {
builder.append("; ");
@@ -718,7 +761,8 @@ public final class MediaType {
private static String escapeAndQuote(String value) {
StringBuilder escaped = new StringBuilder(value.length() + 16).append('"');
- for (char ch : value.toCharArray()) {
+ for (int i = 0; i < value.length(); i++) {
+ char ch = value.charAt(i);
if (ch == '\r' || ch == '\\' || ch == '"') {
escaped.append('\\');
}
diff --git a/guava/src/com/google/common/primitives/Booleans.java b/guava/src/com/google/common/primitives/Booleans.java
index faef910..d8ced70 100644
--- a/guava/src/com/google/common/primitives/Booleans.java
+++ b/guava/src/com/google/common/primitives/Booleans.java
@@ -27,24 +27,27 @@ import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Arrays;
-import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
/**
* Static utility methods pertaining to {@code boolean} primitives, that are not
* already found in either {@link Boolean} or {@link Arrays}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible
public final class Booleans {
private Booleans() {}
@@ -82,7 +85,7 @@ public final class Booleans {
* {@code array}.
*
* <p><b>Note:</b> consider representing the array as a {@link
- * BitSet} instead, replacing {@code Booleans.contains(array, true)}
+ * java.util.BitSet} instead, replacing {@code Booleans.contains(array, true)}
* with {@code !bitSet.isEmpty()} and {@code Booleans.contains(array, false)}
* with {@code bitSet.nextClearBit(0) == sizeOfBitSet}.
*
@@ -104,9 +107,10 @@ public final class Booleans {
* Returns the index of the first appearance of the value {@code target} in
* {@code array}.
*
- * <p><b>Note:</b> consider representing the array as a {@link BitSet}
- * instead, and using {@link BitSet#nextSetBit(int)} or {@link
- * BitSet#nextClearBit(int)}.
+ * <p><b>Note:</b> consider representing the array as a {@link
+ * java.util.BitSet} instead, and using {@link
+ * java.util.BitSet#nextSetBit(int)} or {@link
+ * java.util.BitSet#nextClearBit(int)}.
*
* @param array an array of {@code boolean} values, possibly empty
* @param target a primitive {@code boolean} value
@@ -118,8 +122,7 @@ public final class Booleans {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- boolean[] array, boolean target, int start, int end) {
+ private static int indexOf(boolean[] array, boolean target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -172,8 +175,7 @@ public final class Booleans {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- boolean[] array, boolean target, int start, int end) {
+ private static int lastIndexOf(boolean[] array, boolean target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -221,8 +223,7 @@ public final class Booleans {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static boolean[] ensureCapacity(
- boolean[] array, int minLength, int padding) {
+ public static boolean[] ensureCapacity(boolean[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -306,7 +307,7 @@ public final class Booleans {
* that method.
*
* <p><b>Note:</b> consider representing the collection as a {@link
- * BitSet} instead.
+ * java.util.BitSet} instead.
*
* @param collection a collection of {@code Boolean} objects
* @return an array containing the same values as {@code collection}, in the
@@ -367,26 +368,31 @@ public final class Booleans {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Boolean get(int index) {
+ @Override
+ public Boolean get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Boolean)
&& Booleans.indexOf(array, (Boolean) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Boolean) {
int i = Booleans.indexOf(array, (Boolean) target, start, end);
@@ -397,7 +403,8 @@ public final class Booleans {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Boolean) {
int i = Booleans.lastIndexOf(array, (Boolean) target, start, end);
@@ -408,7 +415,8 @@ public final class Booleans {
return -1;
}
- @Override public Boolean set(int index, Boolean element) {
+ @Override
+ public Boolean set(int index, Boolean element) {
checkElementIndex(index, size());
boolean oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -416,7 +424,8 @@ public final class Booleans {
return oldValue;
}
- @Override public List<Boolean> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Boolean> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -425,7 +434,8 @@ public final class Booleans {
return new BooleanArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -445,7 +455,8 @@ public final class Booleans {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Booleans.hashCode(array[i]);
@@ -453,7 +464,8 @@ public final class Booleans {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 7);
builder.append(array[start] ? "[true" : "[false");
for (int i = start + 1; i < end; i++) {
diff --git a/guava/src/com/google/common/primitives/Bytes.java b/guava/src/com/google/common/primitives/Bytes.java
index d9c5e1f..fec061f 100644
--- a/guava/src/com/google/common/primitives/Bytes.java
+++ b/guava/src/com/google/common/primitives/Bytes.java
@@ -31,6 +31,9 @@ import java.util.Collections;
import java.util.List;
import java.util.RandomAccess;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
/**
* Static utility methods pertaining to {@code byte} primitives, that are not
* already found in either {@link Byte} or {@link Arrays}, <i>and interpret
@@ -39,7 +42,7 @@ import java.util.RandomAccess;
* UnsignedBytes}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
@@ -47,6 +50,7 @@ import java.util.RandomAccess;
*/
// TODO(kevinb): how to prevent warning on UnsignedBytes when building GWT
// javadoc?
+ at CheckReturnValue
@GwtCompatible
public final class Bytes {
private Bytes() {}
@@ -94,8 +98,7 @@ public final class Bytes {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- byte[] array, byte target, int start, int end) {
+ private static int indexOf(byte[] array, byte target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -148,8 +151,7 @@ public final class Bytes {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- byte[] array, byte target, int start, int end) {
+ private static int lastIndexOf(byte[] array, byte target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -197,8 +199,7 @@ public final class Bytes {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static byte[] ensureCapacity(
- byte[] array, int minLength, int padding) {
+ public static byte[] ensureCapacity(byte[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -281,26 +282,30 @@ public final class Bytes {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Byte get(int index) {
+ @Override
+ public Byte get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
- return (target instanceof Byte)
- && Bytes.indexOf(array, (Byte) target, start, end) != -1;
+ return (target instanceof Byte) && Bytes.indexOf(array, (Byte) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Byte) {
int i = Bytes.indexOf(array, (Byte) target, start, end);
@@ -311,7 +316,8 @@ public final class Bytes {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Byte) {
int i = Bytes.lastIndexOf(array, (Byte) target, start, end);
@@ -322,7 +328,8 @@ public final class Bytes {
return -1;
}
- @Override public Byte set(int index, Byte element) {
+ @Override
+ public Byte set(int index, Byte element) {
checkElementIndex(index, size());
byte oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -330,7 +337,8 @@ public final class Bytes {
return oldValue;
}
- @Override public List<Byte> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Byte> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -339,7 +347,8 @@ public final class Bytes {
return new ByteArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -359,7 +368,8 @@ public final class Bytes {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Bytes.hashCode(array[i]);
@@ -367,7 +377,8 @@ public final class Bytes {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 5);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
diff --git a/guava/src/com/google/common/primitives/Chars.java b/guava/src/com/google/common/primitives/Chars.java
index 65fe8b1..fa5f4e4 100644
--- a/guava/src/com/google/common/primitives/Chars.java
+++ b/guava/src/com/google/common/primitives/Chars.java
@@ -33,6 +33,9 @@ import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
/**
* Static utility methods pertaining to {@code char} primitives, that are not
* already found in either {@link Character} or {@link Arrays}.
@@ -41,12 +44,13 @@ import java.util.RandomAccess;
* numerically; they are neither Unicode-aware nor locale-dependent.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class Chars {
private Chars() {}
@@ -151,8 +155,7 @@ public final class Chars {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- char[] array, char target, int start, int end) {
+ private static int indexOf(char[] array, char target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -205,8 +208,7 @@ public final class Chars {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- char[] array, char target, int start, int end) {
+ private static int lastIndexOf(char[] array, char target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -289,9 +291,7 @@ public final class Chars {
*/
@GwtIncompatible("doesn't work")
public static byte[] toByteArray(char value) {
- return new byte[] {
- (byte) (value >> 8),
- (byte) value};
+ return new byte[] {(byte) (value >> 8), (byte) value};
}
/**
@@ -308,8 +308,7 @@ public final class Chars {
*/
@GwtIncompatible("doesn't work")
public static char fromByteArray(byte[] bytes) {
- checkArgument(bytes.length >= BYTES,
- "array too small: %s < %s", bytes.length, BYTES);
+ checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
return fromBytes(bytes[0], bytes[1]);
}
@@ -341,8 +340,7 @@ public final class Chars {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static char[] ensureCapacity(
- char[] array, int minLength, int padding) {
+ public static char[] ensureCapacity(char[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -373,8 +371,7 @@ public final class Chars {
return "";
}
- StringBuilder builder
- = new StringBuilder(len + separator.length() * (len - 1));
+ StringBuilder builder = new StringBuilder(len + separator.length() * (len - 1));
builder.append(array[0]);
for (int i = 1; i < len; i++) {
builder.append(separator).append(array[i]);
@@ -485,26 +482,31 @@ public final class Chars {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Character get(int index) {
+ @Override
+ public Character get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Character)
&& Chars.indexOf(array, (Character) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Character) {
int i = Chars.indexOf(array, (Character) target, start, end);
@@ -515,7 +517,8 @@ public final class Chars {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Character) {
int i = Chars.lastIndexOf(array, (Character) target, start, end);
@@ -526,7 +529,8 @@ public final class Chars {
return -1;
}
- @Override public Character set(int index, Character element) {
+ @Override
+ public Character set(int index, Character element) {
checkElementIndex(index, size());
char oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -534,7 +538,8 @@ public final class Chars {
return oldValue;
}
- @Override public List<Character> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Character> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -543,7 +548,8 @@ public final class Chars {
return new CharArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -563,7 +569,8 @@ public final class Chars {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Chars.hashCode(array[i]);
@@ -571,7 +578,8 @@ public final class Chars {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 3);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
diff --git a/guava/src/com/google/common/primitives/Doubles.java b/guava/src/com/google/common/primitives/Doubles.java
index 8e86e8f..a482cdc 100644
--- a/guava/src/com/google/common/primitives/Doubles.java
+++ b/guava/src/com/google/common/primitives/Doubles.java
@@ -38,6 +38,8 @@ import java.util.List;
import java.util.RandomAccess;
import java.util.regex.Pattern;
+import javax.annotation.CheckForNull;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -45,12 +47,13 @@ import javax.annotation.Nullable;
* already found in either {@link Double} or {@link Arrays}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class Doubles {
private Doubles() {}
@@ -141,8 +144,7 @@ public final class Doubles {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- double[] array, double target, int start, int end) {
+ private static int indexOf(double[] array, double target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -199,8 +201,7 @@ public final class Doubles {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- double[] array, double target, int start, int end) {
+ private static int lastIndexOf(double[] array, double target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -268,8 +269,8 @@ public final class Doubles {
return result;
}
- private static final class DoubleConverter
- extends Converter<String, Double> implements Serializable {
+ private static final class DoubleConverter extends Converter<String, Double>
+ implements Serializable {
static final DoubleConverter INSTANCE = new DoubleConverter();
@Override
@@ -290,6 +291,7 @@ public final class Doubles {
private Object readResolve() {
return INSTANCE;
}
+
private static final long serialVersionUID = 1;
}
@@ -320,8 +322,7 @@ public final class Doubles {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static double[] ensureCapacity(
- double[] array, int minLength, int padding) {
+ public static double[] ensureCapacity(double[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -472,26 +473,31 @@ public final class Doubles {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Double get(int index) {
+ @Override
+ public Double get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Double)
&& Doubles.indexOf(array, (Double) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Double) {
int i = Doubles.indexOf(array, (Double) target, start, end);
@@ -502,7 +508,8 @@ public final class Doubles {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Double) {
int i = Doubles.lastIndexOf(array, (Double) target, start, end);
@@ -513,7 +520,8 @@ public final class Doubles {
return -1;
}
- @Override public Double set(int index, Double element) {
+ @Override
+ public Double set(int index, Double element) {
checkElementIndex(index, size());
double oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -521,7 +529,8 @@ public final class Doubles {
return oldValue;
}
- @Override public List<Double> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Double> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -530,7 +539,8 @@ public final class Doubles {
return new DoubleArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -550,7 +560,8 @@ public final class Doubles {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Doubles.hashCode(array[i]);
@@ -558,7 +569,8 @@ public final class Doubles {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 12);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
@@ -616,12 +628,13 @@ public final class Doubles {
* parsed as a {@code double} value
* @since 14.0
*/
- @GwtIncompatible("regular expressions")
- @Nullable
@Beta
+ @Nullable
+ @CheckForNull
+ @GwtIncompatible("regular expressions")
public static Double tryParse(String string) {
if (FLOATING_POINT_PATTERN.matcher(string).matches()) {
- // TODO(user): could be potentially optimized, but only with
+ // TODO(lowasser): could be potentially optimized, but only with
// extensive testing
try {
return Double.parseDouble(string);
diff --git a/guava/src/com/google/common/primitives/Floats.java b/guava/src/com/google/common/primitives/Floats.java
index 167089e..4776386 100644
--- a/guava/src/com/google/common/primitives/Floats.java
+++ b/guava/src/com/google/common/primitives/Floats.java
@@ -37,6 +37,8 @@ import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
+import javax.annotation.CheckForNull;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -44,12 +46,13 @@ import javax.annotation.Nullable;
* already found in either {@link Float} or {@link Arrays}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class Floats {
private Floats() {}
@@ -137,8 +140,7 @@ public final class Floats {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- float[] array, float target, int start, int end) {
+ private static int indexOf(float[] array, float target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -195,8 +197,7 @@ public final class Floats {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- float[] array, float target, int start, int end) {
+ private static int lastIndexOf(float[] array, float target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -225,7 +226,7 @@ public final class Floats {
/**
* Returns the greatest value present in {@code array}, using the same rules
- * of comparison as {@link Math#min(float, float)}.
+ * of comparison as {@link Math#max(float, float)}.
*
* @param array a <i>nonempty</i> array of {@code float} values
* @return the value present in {@code array} that is greater than or equal to
@@ -264,8 +265,8 @@ public final class Floats {
return result;
}
- private static final class FloatConverter
- extends Converter<String, Float> implements Serializable {
+ private static final class FloatConverter extends Converter<String, Float>
+ implements Serializable {
static final FloatConverter INSTANCE = new FloatConverter();
@Override
@@ -286,6 +287,7 @@ public final class Floats {
private Object readResolve() {
return INSTANCE;
}
+
private static final long serialVersionUID = 1;
}
@@ -316,8 +318,7 @@ public final class Floats {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static float[] ensureCapacity(
- float[] array, int minLength, int padding) {
+ public static float[] ensureCapacity(float[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -468,26 +469,30 @@ public final class Floats {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Float get(int index) {
+ @Override
+ public Float get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
- return (target instanceof Float)
- && Floats.indexOf(array, (Float) target, start, end) != -1;
+ return (target instanceof Float) && Floats.indexOf(array, (Float) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Float) {
int i = Floats.indexOf(array, (Float) target, start, end);
@@ -498,7 +503,8 @@ public final class Floats {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Float) {
int i = Floats.lastIndexOf(array, (Float) target, start, end);
@@ -509,7 +515,8 @@ public final class Floats {
return -1;
}
- @Override public Float set(int index, Float element) {
+ @Override
+ public Float set(int index, Float element) {
checkElementIndex(index, size());
float oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -517,7 +524,8 @@ public final class Floats {
return oldValue;
}
- @Override public List<Float> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Float> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -526,7 +534,8 @@ public final class Floats {
return new FloatArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -546,7 +555,8 @@ public final class Floats {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Floats.hashCode(array[i]);
@@ -554,7 +564,8 @@ public final class Floats {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 12);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
@@ -593,12 +604,13 @@ public final class Floats {
* parsed as a {@code float} value
* @since 14.0
*/
- @GwtIncompatible("regular expressions")
- @Nullable
@Beta
+ @Nullable
+ @CheckForNull
+ @GwtIncompatible("regular expressions")
public static Float tryParse(String string) {
if (Doubles.FLOATING_POINT_PATTERN.matcher(string).matches()) {
- // TODO(user): could be potentially optimized, but only with
+ // TODO(lowasser): could be potentially optimized, but only with
// extensive testing
try {
return Float.parseFloat(string);
diff --git a/guava/src/com/google/common/primitives/Ints.java b/guava/src/com/google/common/primitives/Ints.java
index c0d0126..6249f99 100644
--- a/guava/src/com/google/common/primitives/Ints.java
+++ b/guava/src/com/google/common/primitives/Ints.java
@@ -36,18 +36,21 @@ import java.util.List;
import java.util.RandomAccess;
import javax.annotation.CheckForNull;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
/**
* Static utility methods pertaining to {@code int} primitives, that are not
* already found in either {@link Integer} or {@link Arrays}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class Ints {
private Ints() {}
@@ -159,8 +162,7 @@ public final class Ints {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- int[] array, int target, int start, int end) {
+ private static int indexOf(int[] array, int target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -213,8 +215,7 @@ public final class Ints {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- int[] array, int target, int start, int end) {
+ private static int lastIndexOf(int[] array, int target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -298,10 +299,11 @@ public final class Ints {
@GwtIncompatible("doesn't work")
public static byte[] toByteArray(int value) {
return new byte[] {
- (byte) (value >> 24),
- (byte) (value >> 16),
- (byte) (value >> 8),
- (byte) value};
+ (byte) (value >> 24),
+ (byte) (value >> 16),
+ (byte) (value >> 8),
+ (byte) value
+ };
}
/**
@@ -318,8 +320,7 @@ public final class Ints {
*/
@GwtIncompatible("doesn't work")
public static int fromByteArray(byte[] bytes) {
- checkArgument(bytes.length >= BYTES,
- "array too small: %s < %s", bytes.length, BYTES);
+ checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
return fromBytes(bytes[0], bytes[1], bytes[2], bytes[3]);
}
@@ -335,8 +336,8 @@ public final class Ints {
return b1 << 24 | (b2 & 0xFF) << 16 | (b3 & 0xFF) << 8 | (b4 & 0xFF);
}
- private static final class IntConverter
- extends Converter<String, Integer> implements Serializable {
+ private static final class IntConverter extends Converter<String, Integer>
+ implements Serializable {
static final IntConverter INSTANCE = new IntConverter();
@Override
@@ -357,6 +358,7 @@ public final class Ints {
private Object readResolve() {
return INSTANCE;
}
+
private static final long serialVersionUID = 1;
}
@@ -387,8 +389,7 @@ public final class Ints {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static int[] ensureCapacity(
- int[] array, int minLength, int padding) {
+ public static int[] ensureCapacity(int[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -530,26 +531,30 @@ public final class Ints {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Integer get(int index) {
+ @Override
+ public Integer get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
- return (target instanceof Integer)
- && Ints.indexOf(array, (Integer) target, start, end) != -1;
+ return (target instanceof Integer) && Ints.indexOf(array, (Integer) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Integer) {
int i = Ints.indexOf(array, (Integer) target, start, end);
@@ -560,7 +565,8 @@ public final class Ints {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Integer) {
int i = Ints.lastIndexOf(array, (Integer) target, start, end);
@@ -571,7 +577,8 @@ public final class Ints {
return -1;
}
- @Override public Integer set(int index, Integer element) {
+ @Override
+ public Integer set(int index, Integer element) {
checkElementIndex(index, size());
int oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -579,7 +586,8 @@ public final class Ints {
return oldValue;
}
- @Override public List<Integer> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Integer> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -588,7 +596,8 @@ public final class Ints {
return new IntArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -608,7 +617,8 @@ public final class Ints {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Ints.hashCode(array[i]);
@@ -616,7 +626,8 @@ public final class Ints {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 5);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
@@ -636,23 +647,6 @@ public final class Ints {
private static final long serialVersionUID = 0;
}
- private static final byte[] asciiDigits = new byte[128];
-
- static {
- Arrays.fill(asciiDigits, (byte) -1);
- for (int i = 0; i <= 9; i++) {
- asciiDigits['0' + i] = (byte) i;
- }
- for (int i = 0; i <= 26; i++) {
- asciiDigits['A' + i] = (byte) (10 + i);
- asciiDigits['a' + i] = (byte) (10 + i);
- }
- }
-
- private static int digit(char c) {
- return (c < 128) ? asciiDigits[c] : -1;
- }
-
/**
* Parses the specified string as a signed decimal integer value. The ASCII
* character {@code '-'} (<code>'\u002D'</code>) is recognized as the
@@ -674,6 +668,7 @@ public final class Ints {
* @since 11.0
*/
@Beta
+ @Nullable
@CheckForNull
public static Integer tryParse(String string) {
return tryParse(string, 10);
@@ -700,47 +695,18 @@ public final class Ints {
* or cannot be parsed as an integer value
* @throws IllegalArgumentException if {@code radix < Character.MIN_RADIX} or
* {@code radix > Character.MAX_RADIX}
+ * @since 19.0
*/
- @CheckForNull static Integer tryParse(
+ @Beta
+ @Nullable
+ @CheckForNull
+ public static Integer tryParse(
String string, int radix) {
- if (checkNotNull(string).isEmpty()) {
- return null;
- }
- if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
- throw new IllegalArgumentException(
- "radix must be between MIN_RADIX and MAX_RADIX but was " + radix);
- }
- boolean negative = string.charAt(0) == '-';
- int index = negative ? 1 : 0;
- if (index == string.length()) {
- return null;
- }
- int digit = digit(string.charAt(index++));
- if (digit < 0 || digit >= radix) {
- return null;
- }
- int accum = -digit;
-
- int cap = Integer.MIN_VALUE / radix;
-
- while (index < string.length()) {
- digit = digit(string.charAt(index++));
- if (digit < 0 || digit >= radix || accum < cap) {
- return null;
- }
- accum *= radix;
- if (accum < Integer.MIN_VALUE + digit) {
- return null;
- }
- accum -= digit;
- }
-
- if (negative) {
- return accum;
- } else if (accum == Integer.MIN_VALUE) {
+ Long result = Longs.tryParse(string, radix);
+ if (result == null || result.longValue() != result.intValue()) {
return null;
} else {
- return -accum;
+ return result.intValue();
}
}
}
diff --git a/guava/src/com/google/common/primitives/Longs.java b/guava/src/com/google/common/primitives/Longs.java
index 1078850..2e36fcb 100644
--- a/guava/src/com/google/common/primitives/Longs.java
+++ b/guava/src/com/google/common/primitives/Longs.java
@@ -34,17 +34,22 @@ import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
+import javax.annotation.CheckForNull;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
+
/**
* Static utility methods pertaining to {@code long} primitives, that are not
* already found in either {@link Long} or {@link Arrays}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible
public final class Longs {
private Longs() {}
@@ -126,8 +131,7 @@ public final class Longs {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- long[] array, long target, int start, int end) {
+ private static int indexOf(long[] array, long target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -180,8 +184,7 @@ public final class Longs {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- long[] array, long target, int start, int end) {
+ private static int lastIndexOf(long[] array, long target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -287,10 +290,9 @@ public final class Longs {
* elements
*/
public static long fromByteArray(byte[] bytes) {
- checkArgument(bytes.length >= BYTES,
- "array too small: %s < %s", bytes.length, BYTES);
- return fromBytes(bytes[0], bytes[1], bytes[2], bytes[3],
- bytes[4], bytes[5], bytes[6], bytes[7]) ;
+ checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
+ return fromBytes(
+ bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]);
}
/**
@@ -300,8 +302,8 @@ public final class Longs {
*
* @since 7.0
*/
- public static long fromBytes(byte b1, byte b2, byte b3, byte b4,
- byte b5, byte b6, byte b7, byte b8) {
+ public static long fromBytes(
+ byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7, byte b8) {
return (b1 & 0xFFL) << 56
| (b2 & 0xFFL) << 48
| (b3 & 0xFFL) << 40
@@ -312,6 +314,25 @@ public final class Longs {
| (b8 & 0xFFL);
}
+ private static final byte[] asciiDigits = createAsciiDigits();
+
+ private static byte[] createAsciiDigits() {
+ byte[] result = new byte[128];
+ Arrays.fill(result, (byte) -1);
+ for (int i = 0; i <= 9; i++) {
+ result['0' + i] = (byte) i;
+ }
+ for (int i = 0; i <= 26; i++) {
+ result['A' + i] = (byte) (10 + i);
+ result['a' + i] = (byte) (10 + i);
+ }
+ return result;
+ }
+
+ private static int digit(char c) {
+ return (c < 128) ? asciiDigits[c] : -1;
+ }
+
/**
* Parses the specified string as a signed decimal long value. The ASCII
* character {@code '-'} (<code>'\u002D'</code>) is recognized as the
@@ -333,26 +354,65 @@ public final class Longs {
* @since 14.0
*/
@Beta
+ @Nullable
+ @CheckForNull
public static Long tryParse(String string) {
+ return tryParse(string, 10);
+ }
+
+ /**
+ * Parses the specified string as a signed long value using the specified
+ * radix. The ASCII character {@code '-'} (<code>'\u002D'</code>) is
+ * recognized as the minus sign.
+ *
+ * <p>Unlike {@link Long#parseLong(String, int)}, this method returns
+ * {@code null} instead of throwing an exception if parsing fails.
+ * Additionally, this method only accepts ASCII digits, and returns
+ * {@code null} if non-ASCII digits are present in the string.
+ *
+ * <p>Note that strings prefixed with ASCII {@code '+'} are rejected, even
+ * under JDK 7, despite the change to {@link Long#parseLong(String, int)}
+ * for that version.
+ *
+ * @param string the string representation of an long value
+ * @param radix the radix to use when parsing
+ * @return the long value represented by {@code string} using
+ * {@code radix}, or {@code null} if {@code string} has a length of zero
+ * or cannot be parsed as a long value
+ * @throws IllegalArgumentException if {@code radix < Character.MIN_RADIX} or
+ * {@code radix > Character.MAX_RADIX}
+ * @since 19.0
+ */
+ @Beta
+ @Nullable
+ @CheckForNull
+ public static Long tryParse(String string, int radix) {
if (checkNotNull(string).isEmpty()) {
return null;
}
+ if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
+ throw new IllegalArgumentException(
+ "radix must be between MIN_RADIX and MAX_RADIX but was " + radix);
+ }
boolean negative = string.charAt(0) == '-';
int index = negative ? 1 : 0;
if (index == string.length()) {
return null;
}
- int digit = string.charAt(index++) - '0';
- if (digit < 0 || digit > 9) {
+ int digit = digit(string.charAt(index++));
+ if (digit < 0 || digit >= radix) {
return null;
}
long accum = -digit;
+
+ long cap = Long.MIN_VALUE / radix;
+
while (index < string.length()) {
- digit = string.charAt(index++) - '0';
- if (digit < 0 || digit > 9 || accum < Long.MIN_VALUE / 10) {
+ digit = digit(string.charAt(index++));
+ if (digit < 0 || digit >= radix || accum < cap) {
return null;
}
- accum *= 10;
+ accum *= radix;
if (accum < Long.MIN_VALUE + digit) {
return null;
}
@@ -389,6 +449,7 @@ public final class Longs {
private Object readResolve() {
return INSTANCE;
}
+
private static final long serialVersionUID = 1;
}
@@ -419,8 +480,7 @@ public final class Longs {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static long[] ensureCapacity(
- long[] array, int minLength, int padding) {
+ public static long[] ensureCapacity(long[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -563,26 +623,30 @@ public final class Longs {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Long get(int index) {
+ @Override
+ public Long get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
- return (target instanceof Long)
- && Longs.indexOf(array, (Long) target, start, end) != -1;
+ return (target instanceof Long) && Longs.indexOf(array, (Long) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Long) {
int i = Longs.indexOf(array, (Long) target, start, end);
@@ -593,7 +657,8 @@ public final class Longs {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Long) {
int i = Longs.lastIndexOf(array, (Long) target, start, end);
@@ -604,7 +669,8 @@ public final class Longs {
return -1;
}
- @Override public Long set(int index, Long element) {
+ @Override
+ public Long set(int index, Long element) {
checkElementIndex(index, size());
long oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -612,7 +678,8 @@ public final class Longs {
return oldValue;
}
- @Override public List<Long> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Long> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -621,7 +688,8 @@ public final class Longs {
return new LongArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
@@ -641,7 +709,8 @@ public final class Longs {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Longs.hashCode(array[i]);
@@ -649,7 +718,8 @@ public final class Longs {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 10);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
diff --git a/guava/src/com/google/common/primitives/ParseRequest.java b/guava/src/com/google/common/primitives/ParseRequest.java
index 98f29b4..dd5d5e3 100644
--- a/guava/src/com/google/common/primitives/ParseRequest.java
+++ b/guava/src/com/google/common/primitives/ParseRequest.java
@@ -16,9 +16,12 @@ package com.google.common.primitives;
import com.google.common.annotations.GwtCompatible;
+import javax.annotation.CheckReturnValue;
+
/**
* A string to be parsed as a number and the radix to interpret it in.
*/
+ at CheckReturnValue
@GwtCompatible
final class ParseRequest {
final String rawValue;
diff --git a/guava/src/com/google/common/primitives/Primitives.java b/guava/src/com/google/common/primitives/Primitives.java
index 08c6f31..81588ab 100644
--- a/guava/src/com/google/common/primitives/Primitives.java
+++ b/guava/src/com/google/common/primitives/Primitives.java
@@ -23,6 +23,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
+import javax.annotation.CheckReturnValue;
+
/**
* Contains static utility methods pertaining to primitive types and their
* corresponding wrapper types.
@@ -30,6 +32,7 @@ import java.util.Set;
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
public final class Primitives {
private Primitives() {}
@@ -40,7 +43,7 @@ public final class Primitives {
private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPE;
// Sad that we can't use a BiMap. :(
-
+
static {
Map<Class<?>, Class<?>> primToWrap = new HashMap<Class<?>, Class<?>>(16);
Map<Class<?>, Class<?>> wrapToPrim = new HashMap<Class<?>, Class<?>>(16);
@@ -59,8 +62,11 @@ public final class Primitives {
WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim);
}
- private static void add(Map<Class<?>, Class<?>> forward,
- Map<Class<?>, Class<?>> backward, Class<?> key, Class<?> value) {
+ private static void add(
+ Map<Class<?>, Class<?>> forward,
+ Map<Class<?>, Class<?>> backward,
+ Class<?> key,
+ Class<?> value) {
forward.put(key, value);
backward.put(value, key);
}
diff --git a/guava/src/com/google/common/primitives/Shorts.java b/guava/src/com/google/common/primitives/Shorts.java
index 1a4ba4c..a2ad0e8 100644
--- a/guava/src/com/google/common/primitives/Shorts.java
+++ b/guava/src/com/google/common/primitives/Shorts.java
@@ -35,17 +35,20 @@ import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
+import javax.annotation.CheckReturnValue;
+
/**
* Static utility methods pertaining to {@code short} primitives, that are not
* already found in either {@link Short} or {@link Arrays}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class Shorts {
private Shorts() {}
@@ -158,8 +161,7 @@ public final class Shorts {
}
// TODO(kevinb): consider making this public
- private static int indexOf(
- short[] array, short target, int start, int end) {
+ private static int indexOf(short[] array, short target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
@@ -212,8 +214,7 @@ public final class Shorts {
}
// TODO(kevinb): consider making this public
- private static int lastIndexOf(
- short[] array, short target, int start, int end) {
+ private static int lastIndexOf(short[] array, short target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
@@ -298,8 +299,9 @@ public final class Shorts {
@GwtIncompatible("doesn't work")
public static byte[] toByteArray(short value) {
return new byte[] {
- (byte) (value >> 8),
- (byte) value};
+ (byte) (value >> 8),
+ (byte) value
+ };
}
/**
@@ -316,8 +318,7 @@ public final class Shorts {
*/
@GwtIncompatible("doesn't work")
public static short fromByteArray(byte[] bytes) {
- checkArgument(bytes.length >= BYTES,
- "array too small: %s < %s", bytes.length, BYTES);
+ checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
return fromBytes(bytes[0], bytes[1]);
}
@@ -333,8 +334,8 @@ public final class Shorts {
return (short) ((b1 << 8) | (b2 & 0xFF));
}
- private static final class ShortConverter
- extends Converter<String, Short> implements Serializable {
+ private static final class ShortConverter extends Converter<String, Short>
+ implements Serializable {
static final ShortConverter INSTANCE = new ShortConverter();
@Override
@@ -355,6 +356,7 @@ public final class Shorts {
private Object readResolve() {
return INSTANCE;
}
+
private static final long serialVersionUID = 1;
}
@@ -385,8 +387,7 @@ public final class Shorts {
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
- public static short[] ensureCapacity(
- short[] array, int minLength, int padding) {
+ public static short[] ensureCapacity(short[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength)
@@ -529,26 +530,30 @@ public final class Shorts {
this.end = end;
}
- @Override public int size() {
+ @Override
+ public int size() {
return end - start;
}
- @Override public boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return false;
}
- @Override public Short get(int index) {
+ @Override
+ public Short get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
- @Override public boolean contains(Object target) {
+ @Override
+ public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
- return (target instanceof Short)
- && Shorts.indexOf(array, (Short) target, start, end) != -1;
+ return (target instanceof Short) && Shorts.indexOf(array, (Short) target, start, end) != -1;
}
- @Override public int indexOf(Object target) {
+ @Override
+ public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Short) {
int i = Shorts.indexOf(array, (Short) target, start, end);
@@ -559,7 +564,8 @@ public final class Shorts {
return -1;
}
- @Override public int lastIndexOf(Object target) {
+ @Override
+ public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Short) {
int i = Shorts.lastIndexOf(array, (Short) target, start, end);
@@ -570,7 +576,8 @@ public final class Shorts {
return -1;
}
- @Override public Short set(int index, Short element) {
+ @Override
+ public Short set(int index, Short element) {
checkElementIndex(index, size());
short oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
@@ -578,7 +585,8 @@ public final class Shorts {
return oldValue;
}
- @Override public List<Short> subList(int fromIndex, int toIndex) {
+ @Override
+ public List<Short> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
@@ -587,7 +595,8 @@ public final class Shorts {
return new ShortArrayAsList(array, start + fromIndex, start + toIndex);
}
- @Override public boolean equals(Object object) {
+ @Override
+ public boolean equals(Object object) {
if (object == this) {
return true;
}
@@ -607,7 +616,8 @@ public final class Shorts {
return super.equals(object);
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Shorts.hashCode(array[i]);
@@ -615,7 +625,8 @@ public final class Shorts {
return result;
}
- @Override public String toString() {
+ @Override
+ public String toString() {
StringBuilder builder = new StringBuilder(size() * 6);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
diff --git a/guava/src/com/google/common/primitives/SignedBytes.java b/guava/src/com/google/common/primitives/SignedBytes.java
index 77a0ff5..4a8f131 100644
--- a/guava/src/com/google/common/primitives/SignedBytes.java
+++ b/guava/src/com/google/common/primitives/SignedBytes.java
@@ -23,14 +23,16 @@ import com.google.common.annotations.GwtCompatible;
import java.util.Comparator;
+import javax.annotation.CheckReturnValue;
+
/**
* Static utility methods pertaining to {@code byte} primitives that
* interpret values as signed. The corresponding methods that treat the values
* as unsigned are found in {@link UnsignedBytes}, and the methods for which
* signedness is not an issue are in {@link Bytes}.
- *
+ *
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
@@ -38,17 +40,18 @@ import java.util.Comparator;
*/
// TODO(kevinb): how to prevent warning on UnsignedBytes when building GWT
// javadoc?
+ at CheckReturnValue
@GwtCompatible
public final class SignedBytes {
private SignedBytes() {}
/**
- * The largest power of two that can be represented as a signed {@code byte}.
+ * The largest power of two that can be represented as a signed {@code byte}.
*
* @since 10.0
*/
public static final byte MAX_POWER_OF_TWO = 1 << 6;
-
+
/**
* Returns the {@code byte} value that is equal to {@code value}, if possible.
*
diff --git a/guava/src/com/google/common/primitives/UnsignedBytes.java b/guava/src/com/google/common/primitives/UnsignedBytes.java
index cc16b0c..6ec6338 100644
--- a/guava/src/com/google/common/primitives/UnsignedBytes.java
+++ b/guava/src/com/google/common/primitives/UnsignedBytes.java
@@ -27,6 +27,8 @@ import sun.misc.Unsafe;
import java.nio.ByteOrder;
import java.util.Comparator;
+import javax.annotation.CheckReturnValue;
+
/**
* Static utility methods pertaining to {@code byte} primitives that interpret
* values as <i>unsigned</i> (that is, any negative value {@code b} is treated
@@ -35,7 +37,7 @@ import java.util.Comparator;
* which signedness is not an issue are in {@link Bytes}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
@@ -71,6 +73,7 @@ public final class UnsignedBytes {
*
* @since 6.0
*/
+ @CheckReturnValue
public static int toInt(byte value) {
return value & UNSIGNED_MASK;
}
@@ -122,6 +125,7 @@ public final class UnsignedBytes {
* @return a negative value if {@code a} is less than {@code b}; a positive
* value if {@code a} is greater than {@code b}; or zero if they are equal
*/
+ @CheckReturnValue
public static int compare(byte a, byte b) {
return toInt(a) - toInt(b);
}
@@ -134,6 +138,7 @@ public final class UnsignedBytes {
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
+ @CheckReturnValue
public static byte min(byte... array) {
checkArgument(array.length > 0);
int min = toInt(array[0]);
@@ -154,6 +159,7 @@ public final class UnsignedBytes {
* to every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
+ @CheckReturnValue
public static byte max(byte... array) {
checkArgument(array.length > 0);
int max = toInt(array[0]);
@@ -172,6 +178,7 @@ public final class UnsignedBytes {
* @since 13.0
*/
@Beta
+ @CheckReturnValue
public static String toString(byte x) {
return toString(x, 10);
}
@@ -187,9 +194,12 @@ public final class UnsignedBytes {
* @since 13.0
*/
@Beta
+ @CheckReturnValue
public static String toString(byte x, int radix) {
- checkArgument(radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX,
- "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX", radix);
+ checkArgument(
+ radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX,
+ "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX",
+ radix);
// Benchmarks indicate this is probably not worth optimizing.
return Integer.toString(toInt(x), radix);
}
@@ -199,7 +209,7 @@ public final class UnsignedBytes {
*
* @throws NumberFormatException if the string does not contain a valid unsigned {@code byte}
* value
- * @throws NullPointerException if {@code s} is null
+ * @throws NullPointerException if {@code s} is null
* (in contrast to {@link Byte#parseByte(String)})
* @since 13.0
*/
@@ -216,7 +226,7 @@ public final class UnsignedBytes {
* @throws NumberFormatException if the string does not contain a valid unsigned {@code byte}
* with the given radix, or if {@code radix} is not between {@link Character#MIN_RADIX}
* and {@link Character#MAX_RADIX}.
- * @throws NullPointerException if {@code s} is null
+ * @throws NullPointerException if {@code s} is null
* (in contrast to {@link Byte#parseByte(String)})
* @since 13.0
*/
@@ -240,6 +250,7 @@ public final class UnsignedBytes {
* the resulting string (but not at the start or end)
* @param array an array of {@code byte} values, possibly empty
*/
+ @CheckReturnValue
public static String join(String separator, byte... array) {
checkNotNull(separator);
if (array.length == 0) {
@@ -271,6 +282,7 @@ public final class UnsignedBytes {
* Lexicographical order article at Wikipedia</a>
* @since 2.0
*/
+ @CheckReturnValue
public static Comparator<byte[]> lexicographicalComparator() {
return LexicographicalComparatorHolder.BEST_COMPARATOR;
}
@@ -298,8 +310,7 @@ public final class UnsignedBytes {
enum UnsafeComparator implements Comparator<byte[]> {
INSTANCE;
- static final boolean BIG_ENDIAN =
- ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN);
+ static final boolean BIG_ENDIAN = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN);
/*
* The following static final fields exist for performance reasons.
@@ -335,7 +346,7 @@ public final class UnsignedBytes {
throw new AssertionError();
}
}
-
+
/**
* Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
* Replace with a simple call to Unsafe.getUnsafe when integrating
@@ -344,29 +355,33 @@ public final class UnsignedBytes {
* @return a sun.misc.Unsafe
*/
private static sun.misc.Unsafe getUnsafe() {
- try {
- return sun.misc.Unsafe.getUnsafe();
- } catch (SecurityException tryReflectionInstead) {}
- try {
- return java.security.AccessController.doPrivileged
- (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
- public sun.misc.Unsafe run() throws Exception {
- Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
- for (java.lang.reflect.Field f : k.getDeclaredFields()) {
- f.setAccessible(true);
- Object x = f.get(null);
- if (k.isInstance(x))
- return k.cast(x);
- }
- throw new NoSuchFieldError("the Unsafe");
- }});
- } catch (java.security.PrivilegedActionException e) {
- throw new RuntimeException("Could not initialize intrinsics",
- e.getCause());
- }
+ try {
+ return sun.misc.Unsafe.getUnsafe();
+ } catch (SecurityException e) {
+ // that's okay; try reflection instead
+ }
+ try {
+ return java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
+ public sun.misc.Unsafe run() throws Exception {
+ Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+ for (java.lang.reflect.Field f : k.getDeclaredFields()) {
+ f.setAccessible(true);
+ Object x = f.get(null);
+ if (k.isInstance(x)) {
+ return k.cast(x);
+ }
+ }
+ throw new NoSuchFieldError("the Unsafe");
+ }
+ });
+ } catch (java.security.PrivilegedActionException e) {
+ throw new RuntimeException("Could not initialize intrinsics", e.getCause());
+ }
}
- @Override public int compare(byte[] left, byte[] right) {
+ @Override
+ public int compare(byte[] left, byte[] right) {
int minLength = Math.min(left.length, right.length);
int minWords = minLength / Longs.BYTES;
@@ -386,8 +401,8 @@ public final class UnsignedBytes {
/*
* We want to compare only the first index where left[index] != right[index].
* This corresponds to the least significant nonzero byte in lw ^ rw, since lw
- * and rw are little-endian. Long.numberOfTrailingZeros(diff) tells us the least
- * significant nonzero bit, and zeroing out the first three bits of L.nTZ gives us the
+ * and rw are little-endian. Long.numberOfTrailingZeros(diff) tells us the least
+ * significant nonzero bit, and zeroing out the first three bits of L.nTZ gives us the
* shift to get that least significant nonzero byte.
*/
int n = Long.numberOfTrailingZeros(lw ^ rw) & ~0x7;
@@ -409,7 +424,8 @@ public final class UnsignedBytes {
enum PureJavaComparator implements Comparator<byte[]> {
INSTANCE;
- @Override public int compare(byte[] left, byte[] right) {
+ @Override
+ public int compare(byte[] left, byte[] right) {
int minLength = Math.min(left.length, right.length);
for (int i = 0; i < minLength; i++) {
int result = UnsignedBytes.compare(left[i], right[i]);
@@ -431,8 +447,7 @@ public final class UnsignedBytes {
// yes, UnsafeComparator does implement Comparator<byte[]>
@SuppressWarnings("unchecked")
- Comparator<byte[]> comparator =
- (Comparator<byte[]>) theClass.getEnumConstants()[0];
+ Comparator<byte[]> comparator = (Comparator<byte[]>) theClass.getEnumConstants()[0];
return comparator;
} catch (Throwable t) { // ensure we really catch *everything*
return lexicographicalComparatorJavaImpl();
diff --git a/guava/src/com/google/common/primitives/UnsignedInteger.java b/guava/src/com/google/common/primitives/UnsignedInteger.java
index 1b87e2d..0ba7a4a 100644
--- a/guava/src/com/google/common/primitives/UnsignedInteger.java
+++ b/guava/src/com/google/common/primitives/UnsignedInteger.java
@@ -35,12 +35,13 @@ import javax.annotation.Nullable;
* treat primitive {@code int} values as unsigned, using the methods from {@link UnsignedInts}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">
* unsigned primitive utilities</a>.
*
* @author Louis Wasserman
* @since 11.0
*/
+ at CheckReturnValue
@GwtCompatible(emulated = true)
public final class UnsignedInteger extends Number implements Comparable<UnsignedInteger> {
public static final UnsignedInteger ZERO = fromIntBits(0);
@@ -75,8 +76,10 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
* if possible. The inverse operation of {@link #longValue()}.
*/
public static UnsignedInteger valueOf(long value) {
- checkArgument((value & INT_MASK) == value,
- "value (%s) is outside the range for an unsigned integer value", value);
+ checkArgument(
+ (value & INT_MASK) == value,
+ "value (%s) is outside the range for an unsigned integer value",
+ value);
return fromIntBits((int) value);
}
@@ -88,8 +91,10 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
*/
public static UnsignedInteger valueOf(BigInteger value) {
checkNotNull(value);
- checkArgument(value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
- "value (%s) is outside the range for an unsigned integer value", value);
+ checkArgument(
+ value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
+ "value (%s) is outside the range for an unsigned integer value",
+ value);
return fromIntBits(value.intValue());
}
@@ -121,7 +126,6 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
*
* @since 14.0
*/
- @CheckReturnValue
public UnsignedInteger plus(UnsignedInteger val) {
return fromIntBits(this.value + checkNotNull(val).value);
}
@@ -132,7 +136,6 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
*
* @since 14.0
*/
- @CheckReturnValue
public UnsignedInteger minus(UnsignedInteger val) {
return fromIntBits(value - checkNotNull(val).value);
}
@@ -143,10 +146,9 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
*
* @since 14.0
*/
- @CheckReturnValue
@GwtIncompatible("Does not truncate correctly")
public UnsignedInteger times(UnsignedInteger val) {
- // TODO(user): make this GWT-compatible
+ // TODO(lowasser): make this GWT-compatible
return fromIntBits(value * checkNotNull(val).value);
}
@@ -156,7 +158,6 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
* @throws ArithmeticException if {@code val} is zero
* @since 14.0
*/
- @CheckReturnValue
public UnsignedInteger dividedBy(UnsignedInteger val) {
return fromIntBits(UnsignedInts.divide(value, checkNotNull(val).value));
}
@@ -167,7 +168,6 @@ public final class UnsignedInteger extends Number implements Comparable<Unsigned
* @throws ArithmeticException if {@code val} is zero
* @since 14.0
*/
- @CheckReturnValue
public UnsignedInteger mod(UnsignedInteger val) {
return fromIntBits(UnsignedInts.remainder(value, checkNotNull(val).value));
}
diff --git a/guava/src/com/google/common/primitives/UnsignedInts.java b/guava/src/com/google/common/primitives/UnsignedInts.java
index 762b841..e6841c0 100644
--- a/guava/src/com/google/common/primitives/UnsignedInts.java
+++ b/guava/src/com/google/common/primitives/UnsignedInts.java
@@ -23,6 +23,8 @@ import com.google.common.annotations.GwtCompatible;
import java.util.Arrays;
import java.util.Comparator;
+import javax.annotation.CheckReturnValue;
+
/**
* Static utility methods pertaining to {@code int} primitives that interpret values as
* <i>unsigned</i> (that is, any negative value {@code x} is treated as the positive value
@@ -38,7 +40,7 @@ import java.util.Comparator;
* class be used, at a small efficiency penalty, to enforce the distinction in the type system.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">
* unsigned primitive utilities</a>.
*
* @author Louis Wasserman
@@ -64,6 +66,7 @@ public final class UnsignedInts {
* @return a negative value if {@code a} is less than {@code b}; a positive value if {@code a} is
* greater than {@code b}; or zero if they are equal
*/
+ @CheckReturnValue
public static int compare(int a, int b) {
return Ints.compare(flip(a), flip(b));
}
@@ -71,6 +74,7 @@ public final class UnsignedInts {
/**
* Returns the value of the given {@code int} as a {@code long}, when treated as unsigned.
*/
+ @CheckReturnValue
public static long toLong(int value) {
return value & INT_MASK;
}
@@ -83,6 +87,7 @@ public final class UnsignedInts {
* the array according to {@link #compare}
* @throws IllegalArgumentException if {@code array} is empty
*/
+ @CheckReturnValue
public static int min(int... array) {
checkArgument(array.length > 0);
int min = flip(array[0]);
@@ -103,6 +108,7 @@ public final class UnsignedInts {
* in the array according to {@link #compare}
* @throws IllegalArgumentException if {@code array} is empty
*/
+ @CheckReturnValue
public static int max(int... array) {
checkArgument(array.length > 0);
int max = flip(array[0]);
@@ -123,6 +129,7 @@ public final class UnsignedInts {
* string (but not at the start or end)
* @param array an array of unsigned {@code int} values, possibly empty
*/
+ @CheckReturnValue
public static String join(String separator, int... array) {
checkNotNull(separator);
if (array.length == 0) {
@@ -150,6 +157,7 @@ public final class UnsignedInts {
* @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order"> Lexicographical order
* article at Wikipedia</a>
*/
+ @CheckReturnValue
public static Comparator<int[]> lexicographicalComparator() {
return LexicographicalComparator.INSTANCE;
}
@@ -177,6 +185,7 @@ public final class UnsignedInts {
* @param divisor the divisor (denominator)
* @throws ArithmeticException if divisor is 0
*/
+ @CheckReturnValue
public static int divide(int dividend, int divisor) {
return (int) (toLong(dividend) / toLong(divisor));
}
@@ -189,6 +198,7 @@ public final class UnsignedInts {
* @param divisor the divisor (denominator)
* @throws ArithmeticException if divisor is 0
*/
+ @CheckReturnValue
public static int remainder(int dividend, int divisor) {
return (int) (toLong(dividend) % toLong(divisor));
}
@@ -225,7 +235,7 @@ public final class UnsignedInts {
* Returns the unsigned {@code int} value represented by the given decimal string.
*
* @throws NumberFormatException if the string does not contain a valid unsigned {@code int} value
- * @throws NullPointerException if {@code s} is null
+ * @throws NullPointerException if {@code s} is null
* (in contrast to {@link Integer#parseInt(String)})
*/
public static int parseUnsignedInt(String s) {
@@ -240,15 +250,15 @@ public final class UnsignedInts {
* {@link Character#MIN_RADIX} and {@link Character#MAX_RADIX}.
* @throws NumberFormatException if the string does not contain a valid unsigned {@code int}, or
* if supplied radix is invalid.
- * @throws NullPointerException if {@code s} is null
+ * @throws NullPointerException if {@code s} is null
* (in contrast to {@link Integer#parseInt(String)})
*/
public static int parseUnsignedInt(String string, int radix) {
checkNotNull(string);
long result = Long.parseLong(string, radix);
if ((result & INT_MASK) != result) {
- throw new NumberFormatException("Input " + string + " in base " + radix
- + " is not in the range of an unsigned integer");
+ throw new NumberFormatException(
+ "Input " + string + " in base " + radix + " is not in the range of an unsigned integer");
}
return (int) result;
}
@@ -256,6 +266,7 @@ public final class UnsignedInts {
/**
* Returns a string representation of x, where x is treated as unsigned.
*/
+ @CheckReturnValue
public static String toString(int x) {
return toString(x, 10);
}
@@ -269,6 +280,7 @@ public final class UnsignedInts {
* @throws IllegalArgumentException if {@code radix} is not between {@link Character#MIN_RADIX}
* and {@link Character#MAX_RADIX}.
*/
+ @CheckReturnValue
public static String toString(int x, int radix) {
long asLong = x & INT_MASK;
return Long.toString(asLong, radix);
diff --git a/guava/src/com/google/common/primitives/UnsignedLong.java b/guava/src/com/google/common/primitives/UnsignedLong.java
index 314818f..4bf00c4 100644
--- a/guava/src/com/google/common/primitives/UnsignedLong.java
+++ b/guava/src/com/google/common/primitives/UnsignedLong.java
@@ -32,7 +32,7 @@ import javax.annotation.Nullable;
* treat primitive {@code long} values as unsigned, using the methods from {@link UnsignedLongs}.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">
* unsigned primitive utilities</a>.
*
* @author Louis Wasserman
@@ -68,7 +68,7 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
* @since 14.0
*/
public static UnsignedLong fromLongBits(long bits) {
- // TODO(user): consider caching small values, like Long.valueOf
+ // TODO(lowasser): consider caching small values, like Long.valueOf
return new UnsignedLong(bits);
}
@@ -79,8 +79,7 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
* @since 14.0
*/
public static UnsignedLong valueOf(long value) {
- checkArgument(value >= 0,
- "value (%s) is outside the range for an unsigned long value", value);
+ checkArgument(value >= 0, "value (%s) is outside the range for an unsigned long value", value);
return fromLongBits(value);
}
@@ -92,8 +91,10 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
*/
public static UnsignedLong valueOf(BigInteger value) {
checkNotNull(value);
- checkArgument(value.signum() >= 0 && value.bitLength() <= Long.SIZE,
- "value (%s) is outside the range for an unsigned long value", value);
+ checkArgument(
+ value.signum() >= 0 && value.bitLength() <= Long.SIZE,
+ "value (%s) is outside the range for an unsigned long value",
+ value);
return fromLongBits(value.longValue());
}
@@ -102,7 +103,7 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
* an unsigned {@code long} value.
*
* @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
- * value
+ * value
*/
public static UnsignedLong valueOf(String string) {
return valueOf(string, 10);
@@ -113,8 +114,8 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
* an unsigned {@code long} value in the specified radix.
*
* @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
- * value, or {@code radix} is not between {@link Character#MIN_RADIX} and
- * {@link Character#MAX_RADIX}
+ * value, or {@code radix} is not between {@link Character#MIN_RADIX} and
+ * {@link Character#MAX_RADIX}
*/
public static UnsignedLong valueOf(String string, int radix) {
return fromLongBits(UnsignedLongs.parseUnsignedLong(string, radix));
@@ -126,6 +127,7 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
*
* @since 14.0
*/
+ @CheckReturnValue
public UnsignedLong plus(UnsignedLong val) {
return fromLongBits(this.value + checkNotNull(val).value);
}
@@ -136,6 +138,7 @@ public final class UnsignedLong extends Number implements Comparable<UnsignedLon
*
* @since 14.0
*/
+ @CheckReturnValue
public UnsignedLong minus(UnsignedLong val) {
return fromLongBits(this.value - checkNotNull(val).value);
}
diff --git a/guava/src/com/google/common/primitives/UnsignedLongs.java b/guava/src/com/google/common/primitives/UnsignedLongs.java
index cb9923f..a4e6f10 100644
--- a/guava/src/com/google/common/primitives/UnsignedLongs.java
+++ b/guava/src/com/google/common/primitives/UnsignedLongs.java
@@ -24,6 +24,8 @@ import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
+import javax.annotation.CheckReturnValue;
+
/**
* Static utility methods pertaining to {@code long} primitives that interpret values as
* <i>unsigned</i> (that is, any negative value {@code x} is treated as the positive value
@@ -39,7 +41,7 @@ import java.util.Comparator;
* class be used, at a small efficiency penalty, to enforce the distinction in the type system.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">
* unsigned primitive utilities</a>.
*
* @author Louis Wasserman
@@ -72,6 +74,7 @@ public final class UnsignedLongs {
* @return a negative value if {@code a} is less than {@code b}; a positive value if {@code a} is
* greater than {@code b}; or zero if they are equal
*/
+ @CheckReturnValue
public static int compare(long a, long b) {
return Longs.compare(flip(a), flip(b));
}
@@ -84,6 +87,7 @@ public final class UnsignedLongs {
* the array according to {@link #compare}
* @throws IllegalArgumentException if {@code array} is empty
*/
+ @CheckReturnValue
public static long min(long... array) {
checkArgument(array.length > 0);
long min = flip(array[0]);
@@ -104,6 +108,7 @@ public final class UnsignedLongs {
* in the array according to {@link #compare}
* @throws IllegalArgumentException if {@code array} is empty
*/
+ @CheckReturnValue
public static long max(long... array) {
checkArgument(array.length > 0);
long max = flip(array[0]);
@@ -124,6 +129,7 @@ public final class UnsignedLongs {
* string (but not at the start or end)
* @param array an array of unsigned {@code long} values, possibly empty
*/
+ @CheckReturnValue
public static String join(String separator, long... array) {
checkNotNull(separator);
if (array.length == 0) {
@@ -152,6 +158,7 @@ public final class UnsignedLongs {
* @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">Lexicographical order
* article at Wikipedia</a>
*/
+ @CheckReturnValue
public static Comparator<long[]> lexicographicalComparator() {
return LexicographicalComparator.INSTANCE;
}
@@ -179,6 +186,7 @@ public final class UnsignedLongs {
* @param divisor the divisor (denominator)
* @throws ArithmeticException if divisor is 0
*/
+ @CheckReturnValue
public static long divide(long dividend, long divisor) {
if (divisor < 0) { // i.e., divisor >= 2^63:
if (compare(dividend, divisor) < 0) {
@@ -213,6 +221,7 @@ public final class UnsignedLongs {
* @throws ArithmeticException if divisor is 0
* @since 11.0
*/
+ @CheckReturnValue
public static long remainder(long dividend, long divisor) {
if (divisor < 0) { // i.e., divisor >= 2^63:
if (compare(dividend, divisor) < 0) {
@@ -243,7 +252,7 @@ public final class UnsignedLongs {
*
* @throws NumberFormatException if the string does not contain a valid unsigned {@code long}
* value
- * @throws NullPointerException if {@code s} is null
+ * @throws NullPointerException if {@code s} is null
* (in contrast to {@link Long#parseLong(String)})
*/
public static long parseUnsignedLong(String s) {
@@ -287,7 +296,7 @@ public final class UnsignedLongs {
* @throws NumberFormatException if the string does not contain a valid unsigned {@code long}
* with the given radix, or if {@code radix} is not between {@link Character#MIN_RADIX}
* and {@link Character#MAX_RADIX}.
- * @throws NullPointerException if {@code s} is null
+ * @throws NullPointerException if {@code s} is null
* (in contrast to {@link Long#parseLong(String)})
*/
public static long parseUnsignedLong(String s, int radix) {
@@ -340,6 +349,7 @@ public final class UnsignedLongs {
/**
* Returns a string representation of x, where x is treated as unsigned.
*/
+ @CheckReturnValue
public static String toString(long x) {
return toString(x, 10);
}
@@ -353,9 +363,12 @@ public final class UnsignedLongs {
* @throws IllegalArgumentException if {@code radix} is not between {@link Character#MIN_RADIX}
* and {@link Character#MAX_RADIX}.
*/
+ @CheckReturnValue
public static String toString(long x, int radix) {
- checkArgument(radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX,
- "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX", radix);
+ checkArgument(
+ radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX,
+ "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX",
+ radix);
if (x == 0) {
// Simply return "0"
return "0";
@@ -384,6 +397,7 @@ public final class UnsignedLongs {
private static final long[] maxValueDivs = new long[Character.MAX_RADIX + 1];
private static final int[] maxValueMods = new int[Character.MAX_RADIX + 1];
private static final int[] maxSafeDigits = new int[Character.MAX_RADIX + 1];
+
static {
BigInteger overflow = new BigInteger("10000000000000000", 16);
for (int i = Character.MIN_RADIX; i <= Character.MAX_RADIX; i++) {
diff --git a/guava/src/com/google/common/primitives/package-info.java b/guava/src/com/google/common/primitives/package-info.java
index 205183f..52a4fe5 100644
--- a/guava/src/com/google/common/primitives/package-info.java
+++ b/guava/src/com/google/common/primitives/package-info.java
@@ -22,7 +22,7 @@
* <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
+ * "https://github.com/google/guava/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* <h2>Contents</h2>
diff --git a/guava/src/com/google/common/reflect/ClassPath.java b/guava/src/com/google/common/reflect/ClassPath.java
index cadb825..59763d2 100644
--- a/guava/src/com/google/common/reflect/ClassPath.java
+++ b/guava/src/com/google/common/reflect/ClassPath.java
@@ -26,20 +26,20 @@ import com.google.common.base.Splitter;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Maps;
-import com.google.common.collect.Ordering;
+import com.google.common.collect.MultimapBuilder;
+import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import java.io.File;
import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
+import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
@@ -87,10 +87,8 @@ public final class ClassPath {
* failed.
*/
public static ClassPath from(ClassLoader classloader) throws IOException {
- Scanner scanner = new Scanner();
- for (Map.Entry<URI, ClassLoader> entry : getClassPathEntries(classloader).entrySet()) {
- scanner.scan(entry.getKey(), entry.getValue());
- }
+ DefaultScanner scanner = new DefaultScanner();
+ scanner.scan(classloader);
return new ClassPath(scanner.getResources());
}
@@ -153,6 +151,7 @@ public final class ClassPath {
@Beta
public static class ResourceInfo {
private final String resourceName;
+
final ClassLoader loader;
static ResourceInfo of(String resourceName, ClassLoader loader) {
@@ -162,16 +161,25 @@ public final class ClassPath {
return new ResourceInfo(resourceName, loader);
}
}
-
- ResourceInfo(String resourceName, ClassLoader loader) {
+
+ ResourceInfo(String resourceName, ClassLoader loader) {
this.resourceName = checkNotNull(resourceName);
this.loader = checkNotNull(loader);
}
- /** Returns the url identifying the resource. */
- public final URL url() {
- return checkNotNull(loader.getResource(resourceName),
- "Failed to load resource: %s", resourceName);
+ /**
+ * Returns the url identifying the resource.
+ *
+ * <p>See {@link ClassLoader#getResource}
+ * @throws NoSuchElementException if the resource cannot be loaded through the class loader,
+ * despite physically existing in the class path.
+ */
+ public final URL url() throws NoSuchElementException {
+ URL url = loader.getResource(resourceName);
+ if (url == null) {
+ throw new NoSuchElementException(resourceName);
+ }
+ return url;
}
/** Returns the fully qualified name of the resource. Such as "com/mycomp/foo/bar.txt". */
@@ -212,19 +220,19 @@ public final class ClassPath {
this.className = getClassName(resourceName);
}
- /**
+ /**
* Returns the package name of the class, without attempting to load the class.
- *
- * <p>Behaves identically to {@link Package#getName()} but does not require the class (or
+ *
+ * <p>Behaves identically to {@link Package#getName()} but does not require the class (or
* package) to be loaded.
*/
public String getPackageName() {
return Reflection.getPackageName(className);
}
- /**
+ /**
* Returns the simple name of the underlying class as given in the source code.
- *
+ *
* <p>Behaves identically to {@link Class#getSimpleName()} but does not require the class to be
* loaded.
*/
@@ -232,7 +240,7 @@ public final class ClassPath {
int lastDollarSign = className.lastIndexOf('$');
if (lastDollarSign != -1) {
String innerClassName = className.substring(lastDollarSign + 1);
- // local and anonymous classes are prefixed with number (1,2,3...), anonymous classes are
+ // local and anonymous classes are prefixed with number (1,2,3...), anonymous classes are
// entirely numeric whereas local classes have the user supplied name as a suffix
return CharMatcher.DIGIT.trimLeadingFrom(innerClassName);
}
@@ -245,9 +253,9 @@ public final class ClassPath {
return className.substring(packageName.length() + 1);
}
- /**
- * Returns the fully qualified name of the class.
- *
+ /**
+ * Returns the fully qualified name of the class.
+ *
* <p>Behaves identically to {@link Class#getName()} but does not require the class to be
* loaded.
*/
@@ -275,94 +283,47 @@ public final class ClassPath {
}
}
- @VisibleForTesting static ImmutableMap<URI, ClassLoader> getClassPathEntries(
- ClassLoader classloader) {
- LinkedHashMap<URI, ClassLoader> entries = Maps.newLinkedHashMap();
- // Search parent first, since it's the order ClassLoader#loadClass() uses.
- ClassLoader parent = classloader.getParent();
- if (parent != null) {
- entries.putAll(getClassPathEntries(parent));
- }
- if (classloader instanceof URLClassLoader) {
- URLClassLoader urlClassLoader = (URLClassLoader) classloader;
- for (URL entry : urlClassLoader.getURLs()) {
- URI uri;
- try {
- uri = entry.toURI();
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
- if (!entries.containsKey(uri)) {
- entries.put(uri, classloader);
- }
+ /**
+ * Abstract class that scans through the class path represented by a {@link ClassLoader} and calls
+ * {@link #scanDirectory} and {@link #scanJarFile} for directories and jar files on the class path
+ * respectively.
+ */
+ abstract static class Scanner {
+
+ // We only scan each file once independent of the classloader that resource might be associated
+ // with.
+ private final Set<File> scannedUris = Sets.newHashSet();
+
+ public final void scan(ClassLoader classloader) throws IOException {
+ for (Map.Entry<File, ClassLoader> entry : getClassPathEntries(classloader).entrySet()) {
+ scan(entry.getKey(), entry.getValue());
}
}
- return ImmutableMap.copyOf(entries);
- }
- @VisibleForTesting static final class Scanner {
+ /** Called when a directory is scanned for resource files. */
+ protected abstract void scanDirectory(ClassLoader loader, File directory)
+ throws IOException;
- private final ImmutableSortedSet.Builder<ResourceInfo> resources =
- new ImmutableSortedSet.Builder<ResourceInfo>(Ordering.usingToString());
- private final Set<URI> scannedUris = Sets.newHashSet();
+ /** Called when a jar file is scanned for resource entries. */
+ protected abstract void scanJarFile(ClassLoader loader, JarFile file) throws IOException;
- ImmutableSortedSet<ResourceInfo> getResources() {
- return resources.build();
- }
-
- void scan(URI uri, ClassLoader classloader) throws IOException {
- if (uri.getScheme().equals("file") && scannedUris.add(uri)) {
- scanFrom(new File(uri), classloader);
+ @VisibleForTesting final void scan(File file, ClassLoader classloader) throws IOException {
+ if (scannedUris.add(file.getCanonicalFile())) {
+ scanFrom(file, classloader);
}
}
-
- @VisibleForTesting void scanFrom(File file, ClassLoader classloader)
- throws IOException {
+
+ private void scanFrom(File file, ClassLoader classloader) throws IOException {
if (!file.exists()) {
return;
}
if (file.isDirectory()) {
- scanDirectory(file, classloader);
+ scanDirectory(classloader, file);
} else {
scanJar(file, classloader);
}
}
-
- private void scanDirectory(File directory, ClassLoader classloader) throws IOException {
- scanDirectory(directory, classloader, "", ImmutableSet.<File>of());
- }
-
- private void scanDirectory(
- File directory, ClassLoader classloader, String packagePrefix,
- ImmutableSet<File> ancestors) throws IOException {
- File canonical = directory.getCanonicalFile();
- if (ancestors.contains(canonical)) {
- // A cycle in the filesystem, for example due to a symbolic link.
- return;
- }
- File[] files = directory.listFiles();
- if (files == null) {
- logger.warning("Cannot read directory " + directory);
- // IO error, just skip the directory
- return;
- }
- ImmutableSet<File> newAncestors = ImmutableSet.<File>builder()
- .addAll(ancestors)
- .add(canonical)
- .build();
- for (File f : files) {
- String name = f.getName();
- if (f.isDirectory()) {
- scanDirectory(f, classloader, packagePrefix + name + "/", newAncestors);
- } else {
- String resourceName = packagePrefix + name;
- if (!resourceName.equals(JarFile.MANIFEST_NAME)) {
- resources.add(ResourceInfo.of(resourceName, classloader));
- }
- }
- }
- }
-
+
private void scanJar(File file, ClassLoader classloader) throws IOException {
JarFile jarFile;
try {
@@ -372,67 +333,130 @@ public final class ClassPath {
return;
}
try {
- for (URI uri : getClassPathFromManifest(file, jarFile.getManifest())) {
- scan(uri, classloader);
- }
- Enumeration<JarEntry> entries = jarFile.entries();
- while (entries.hasMoreElements()) {
- JarEntry entry = entries.nextElement();
- if (entry.isDirectory() || entry.getName().equals(JarFile.MANIFEST_NAME)) {
- continue;
- }
- resources.add(ResourceInfo.of(entry.getName(), classloader));
+ for (File path : getClassPathFromManifest(file, jarFile.getManifest())) {
+ scan(path, classloader);
}
+ scanJarFile(classloader, jarFile);
} finally {
try {
jarFile.close();
} catch (IOException ignored) {}
}
}
-
+
/**
* Returns the class path URIs specified by the {@code Class-Path} manifest attribute, according
- * to <a href="http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Main%20Attributes">
+ * to
+ * <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Main_Attributes">
* JAR File Specification</a>. If {@code manifest} is null, it means the jar file has no
* manifest, and an empty set will be returned.
*/
- @VisibleForTesting static ImmutableSet<URI> getClassPathFromManifest(
+ @VisibleForTesting static ImmutableSet<File> getClassPathFromManifest(
File jarFile, @Nullable Manifest manifest) {
if (manifest == null) {
return ImmutableSet.of();
}
- ImmutableSet.Builder<URI> builder = ImmutableSet.builder();
+ ImmutableSet.Builder<File> builder = ImmutableSet.builder();
String classpathAttribute = manifest.getMainAttributes()
.getValue(Attributes.Name.CLASS_PATH.toString());
if (classpathAttribute != null) {
for (String path : CLASS_PATH_ATTRIBUTE_SEPARATOR.split(classpathAttribute)) {
- URI uri;
+ URL url;
try {
- uri = getClassPathEntry(jarFile, path);
- } catch (URISyntaxException e) {
+ url = getClassPathEntry(jarFile, path);
+ } catch (MalformedURLException e) {
// Ignore bad entry
logger.warning("Invalid Class-Path entry: " + path);
continue;
}
- builder.add(uri);
+ if (url.getProtocol().equals("file")) {
+ builder.add(new File(url.getFile()));
+ }
}
}
return builder.build();
}
-
+
+ @VisibleForTesting static ImmutableMap<File, ClassLoader> getClassPathEntries(
+ ClassLoader classloader) {
+ LinkedHashMap<File, ClassLoader> entries = Maps.newLinkedHashMap();
+ // Search parent first, since it's the order ClassLoader#loadClass() uses.
+ ClassLoader parent = classloader.getParent();
+ if (parent != null) {
+ entries.putAll(getClassPathEntries(parent));
+ }
+ if (classloader instanceof URLClassLoader) {
+ URLClassLoader urlClassLoader = (URLClassLoader) classloader;
+ for (URL entry : urlClassLoader.getURLs()) {
+ if (entry.getProtocol().equals("file")) {
+ File file = new File(entry.getFile());
+ if (!entries.containsKey(file)) {
+ entries.put(file, classloader);
+ }
+ }
+ }
+ }
+ return ImmutableMap.copyOf(entries);
+ }
+
/**
* Returns the absolute uri of the Class-Path entry value as specified in
- * <a href="http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Main%20Attributes">
+ * <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Main_Attributes">
* JAR File Specification</a>. Even though the specification only talks about relative urls,
* absolute urls are actually supported too (for example, in Maven surefire plugin).
*/
- @VisibleForTesting static URI getClassPathEntry(File jarFile, String path)
- throws URISyntaxException {
- URI uri = new URI(path);
- if (uri.isAbsolute()) {
- return uri;
- } else {
- return new File(jarFile.getParentFile(), path.replace('/', File.separatorChar)).toURI();
+ @VisibleForTesting static URL getClassPathEntry(File jarFile, String path)
+ throws MalformedURLException {
+ return new URL(jarFile.toURI().toURL(), path);
+ }
+ }
+
+ @VisibleForTesting static final class DefaultScanner extends Scanner {
+ private final SetMultimap<ClassLoader, String> resources =
+ MultimapBuilder.hashKeys().linkedHashSetValues().build();
+
+ ImmutableSet<ResourceInfo> getResources() {
+ ImmutableSet.Builder<ResourceInfo> builder = ImmutableSet.builder();
+ for (Map.Entry<ClassLoader, String> entry : resources.entries()) {
+ builder.add(ResourceInfo.of(entry.getValue(), entry.getKey()));
+ }
+ return builder.build();
+ }
+
+ @Override protected void scanJarFile(ClassLoader classloader, JarFile file) {
+ Enumeration<JarEntry> entries = file.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry entry = entries.nextElement();
+ if (entry.isDirectory() || entry.getName().equals(JarFile.MANIFEST_NAME)) {
+ continue;
+ }
+ resources.get(classloader).add(entry.getName());
+ }
+ }
+
+ @Override protected void scanDirectory(ClassLoader classloader, File directory)
+ throws IOException {
+ scanDirectory(directory, classloader, "");
+ }
+
+ private void scanDirectory(
+ File directory, ClassLoader classloader, String packagePrefix) throws IOException {
+ File[] files = directory.listFiles();
+ if (files == null) {
+ logger.warning("Cannot read directory " + directory);
+ // IO error, just skip the directory
+ return;
+ }
+ for (File f : files) {
+ String name = f.getName();
+ if (f.isDirectory()) {
+ scanDirectory(f, classloader, packagePrefix + name + "/");
+ } else {
+ String resourceName = packagePrefix + name;
+ if (!resourceName.equals(JarFile.MANIFEST_NAME)) {
+ resources.get(classloader).add(resourceName);
+ }
+ }
}
}
}
diff --git a/guava/src/com/google/common/reflect/Invokable.java b/guava/src/com/google/common/reflect/Invokable.java
index b281faf..73fb009 100644
--- a/guava/src/com/google/common/reflect/Invokable.java
+++ b/guava/src/com/google/common/reflect/Invokable.java
@@ -150,7 +150,7 @@ public abstract class Invokable<T, R> extends Element implements GenericDeclarat
/** Explicitly specifies the return type of this {@code Invokable}. */
public final <R1 extends R> Invokable<T, R1> returning(TypeToken<R1> returnType) {
- if (!returnType.isAssignableFrom(getReturnType())) {
+ if (!returnType.isSupertypeOf(getReturnType())) {
throw new IllegalArgumentException(
"Invokable is known to return " + getReturnType() + ", not " + returnType);
}
diff --git a/guava/src/com/google/common/reflect/TypeResolver.java b/guava/src/com/google/common/reflect/TypeResolver.java
index 2eec8ea..452cf01 100644
--- a/guava/src/com/google/common/reflect/TypeResolver.java
+++ b/guava/src/com/google/common/reflect/TypeResolver.java
@@ -103,6 +103,11 @@ public final class TypeResolver {
if (from.equals(to)) {
return;
}
+ if (to instanceof WildcardType != from instanceof WildcardType) {
+ // When we are saying "assuming <?> is T, there really isn't any useful type mapping.
+ // Similarly, saying "assuming T is <?>" is meaningless. Of course it is.
+ return;
+ }
new TypeVisitor() {
@Override void visitTypeVariable(TypeVariable<?> typeVariable) {
mappings.put(new TypeVariableKey(typeVariable), to);
diff --git a/guava/src/com/google/common/reflect/TypeToken.java b/guava/src/com/google/common/reflect/TypeToken.java
index bc33e8f..093f152 100644
--- a/guava/src/com/google/common/reflect/TypeToken.java
+++ b/guava/src/com/google/common/reflect/TypeToken.java
@@ -45,6 +45,7 @@ import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;
@@ -52,9 +53,8 @@ import javax.annotation.Nullable;
* A {@link Type} with generics.
*
* <p>Operations that are otherwise only available in {@link Class} are implemented to support
- * {@code Type}, for example {@link #isAssignableFrom}, {@link #isArray} and {@link
- * #getComponentType}. It also provides additional utilities such as {@link #getTypes} and {@link
- * #resolveType} etc.
+ * {@code Type}, for example {@link #isSubtypeOf}, {@link #isArray} and {@link #getComponentType}.
+ * It also provides additional utilities such as {@link #getTypes}, {@link #resolveType}, etc.
*
* <p>There are three ways to get a {@code TypeToken} instance: <ul>
* <li>Wrap a {@code Type} obtained via reflection. For example: {@code
@@ -112,11 +112,11 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
protected TypeToken() {
this.runtimeType = capture();
checkState(!(runtimeType instanceof TypeVariable),
- "Cannot construct a TypeToken for a type variable.\n" +
- "You probably meant to call new TypeToken<%s>(getClass()) " +
- "that can resolve the type variable for you.\n" +
- "If you do need to create a TypeToken of a type variable, " +
- "please use TypeToken.of() instead.", runtimeType);
+ "Cannot construct a TypeToken for a type variable.\n"
+ + "You probably meant to call new TypeToken<%s>(getClass()) "
+ + "that can resolve the type variable for you.\n"
+ + "If you do need to create a TypeToken of a type variable, "
+ + "please use TypeToken.of() instead.", runtimeType);
}
/**
@@ -174,23 +174,13 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
* </ul>
*/
public final Class<? super T> getRawType() {
- Class<?> rawType = getRawType(runtimeType);
+ // For wildcard or type variable, the first bound determines the runtime type.
+ Class<?> rawType = getRawTypes().iterator().next();
@SuppressWarnings("unchecked") // raw type is |T|
Class<? super T> result = (Class<? super T>) rawType;
return result;
}
- /**
- * Returns the raw type of the class or parameterized type; if {@code T} is type variable or
- * wildcard type, the raw types of all its upper bounds are returned.
- */
- private ImmutableSet<Class<? super T>> getImmediateRawTypes() {
- // Cast from ImmutableSet<Class<?>> to ImmutableSet<Class<? super T>>
- @SuppressWarnings({"unchecked", "rawtypes"})
- ImmutableSet<Class<? super T>> result = (ImmutableSet) getRawTypes(runtimeType);
- return result;
- }
-
/** Returns the represented type. */
public final Type getType() {
return runtimeType;
@@ -373,7 +363,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
* input {@code Iterable.class}.
*/
public final TypeToken<? super T> getSupertype(Class<? super T> superclass) {
- checkArgument(superclass.isAssignableFrom(getRawType()),
+ checkArgument(this.someRawTypeIsSubclassOf(superclass),
"%s is not a super class of %s", superclass, this);
if (runtimeType instanceof TypeVariable) {
return getSupertypeFromUpperBounds(superclass, ((TypeVariable<?>) runtimeType).getBounds());
@@ -401,26 +391,156 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
if (runtimeType instanceof WildcardType) {
return getSubtypeFromLowerBounds(subclass, ((WildcardType) runtimeType).getLowerBounds());
}
- checkArgument(getRawType().isAssignableFrom(subclass),
- "%s isn't a subclass of %s", subclass, this);
// unwrap array type if necessary
if (isArray()) {
return getArraySubtype(subclass);
}
+ // At this point, it's either a raw class or parameterized type.
+ checkArgument(getRawType().isAssignableFrom(subclass),
+ "%s isn't a subclass of %s", subclass, this);
+ Type resolvedTypeArgs = resolveTypeArgsForSubclass(subclass);
@SuppressWarnings("unchecked") // guarded by the isAssignableFrom() statement above
TypeToken<? extends T> subtype = (TypeToken<? extends T>)
- of(resolveTypeArgsForSubclass(subclass));
+ of(replaceTypeVariablesWithWildcard(resolvedTypeArgs, subclass));
return subtype;
}
- /** Returns true if this type is assignable from the given {@code type}. */
+ private static final Type replaceTypeVariablesWithWildcard(
+ Type type, final Class<?> declaringClass) {
+ checkNotNull(declaringClass);
+ final AtomicReference<Type> result = new AtomicReference<Type>();
+ result.set(type);
+ new TypeVisitor() {
+ @Override void visitTypeVariable(TypeVariable<?> var) {
+ if (var.getGenericDeclaration() == declaringClass) {
+ result.set(Types.subtypeOf(Object.class));
+ }
+ }
+ @Override void visitParameterizedType(ParameterizedType pt) {
+ result.set(Types.newParameterizedTypeWithOwner(
+ // Replaces type vars on the owner type if it's owner type of declaringClass.
+ declaringClass.getEnclosingClass() == null
+ ? pt.getOwnerType()
+ : replaceTypeVariablesWithWildcard(
+ pt.getOwnerType(), declaringClass.getEnclosingClass()),
+ (Class<?>) pt.getRawType(),
+ replaceTypeVariablesWithWildcard(pt.getActualTypeArguments(), declaringClass)));
+ }
+ @Override void visitWildcardType(WildcardType t) {}
+ @Override void visitGenericArrayType(GenericArrayType t) {}
+ @Override void visitClass(Class<?> t) {}
+ }.visit(type);
+ return result.get();
+ }
+
+ private static final Type[] replaceTypeVariablesWithWildcard(
+ Type[] types, Class<?> declaringClass) {
+ Type[] result = new Type[types.length];
+ for (int i = 0; i < types.length; i++) {
+ result[i] = replaceTypeVariablesWithWildcard(types[i], declaringClass);
+ }
+ return result;
+ }
+
+ /**
+ * Returns true if this type is a supertype of the given {@code type}. "Supertype" is defined
+ * according to <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1"
+ * >the rules for type arguments</a> introduced with Java generics.
+ *
+ * @deprecated Use the method under its new name, {@link #isSupertypeOf(TypeToken)}. This method
+ * will be removed in Guava release 20.0.
+ */
+ @Deprecated
public final boolean isAssignableFrom(TypeToken<?> type) {
- return isAssignableFrom(type.runtimeType);
+ return isSupertypeOf(type);
}
- /** Check if this type is assignable from the given {@code type}. */
+ /**
+ * Returns true if this type is a supertype of the given {@code type}. "Supertype" is defined
+ * according to <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1"
+ * >the rules for type arguments</a> introduced with Java generics.
+ *
+ * @deprecated Use the method under its new name, {@link #isSupertypeOf(Type)}. This method will
+ * be removed in Guava release 20.0.
+ */
+ @Deprecated
public final boolean isAssignableFrom(Type type) {
- return isAssignable(checkNotNull(type), runtimeType);
+ return isSupertypeOf(type);
+ }
+
+ /**
+ * Returns true if this type is a supertype of the given {@code type}. "Supertype" is defined
+ * according to <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1"
+ * >the rules for type arguments</a> introduced with Java generics.
+ *
+ * @since 19.0
+ */
+ public final boolean isSupertypeOf(TypeToken<?> type) {
+ return type.isSubtypeOf(getType());
+ }
+
+ /**
+ * Returns true if this type is a supertype of the given {@code type}. "Supertype" is defined
+ * according to <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1"
+ * >the rules for type arguments</a> introduced with Java generics.
+ *
+ * @since 19.0
+ */
+ public final boolean isSupertypeOf(Type type) {
+ return of(type).isSubtypeOf(getType());
+ }
+
+ /**
+ * Returns true if this type is a subtype of the given {@code type}. "Subtype" is defined
+ * according to <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1"
+ * >the rules for type arguments</a> introduced with Java generics.
+ *
+ * @since 19.0
+ */
+ public final boolean isSubtypeOf(TypeToken<?> type) {
+ return isSubtypeOf(type.getType());
+ }
+
+ /**
+ * Returns true if this type is a subtype of the given {@code type}. "Subtype" is defined
+ * according to <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1"
+ * >the rules for type arguments</a> introduced with Java generics.
+ *
+ * @since 19.0
+ */
+ public final boolean isSubtypeOf(Type supertype) {
+ checkNotNull(supertype);
+ if (supertype instanceof WildcardType) {
+ // if 'supertype' is <? super Foo>, 'this' can be:
+ // Foo, SubFoo, <? extends Foo>.
+ // if 'supertype' is <? extends Foo>, nothing is a subtype.
+ return any(((WildcardType) supertype).getLowerBounds()).isSupertypeOf(runtimeType);
+ }
+ // if 'this' is wildcard, it's a suptype of to 'supertype' if any of its "extends"
+ // bounds is a subtype of 'supertype'.
+ if (runtimeType instanceof WildcardType) {
+ // <? super Base> is of no use in checking 'from' being a subtype of 'to'.
+ return any(((WildcardType) runtimeType).getUpperBounds()).isSubtypeOf(supertype);
+ }
+ // if 'this' is type variable, it's a subtype if any of its "extends"
+ // bounds is a subtype of 'supertype'.
+ if (runtimeType instanceof TypeVariable) {
+ return runtimeType.equals(supertype)
+ || any(((TypeVariable<?>) runtimeType).getBounds()).isSubtypeOf(supertype);
+ }
+ if (runtimeType instanceof GenericArrayType) {
+ return of(supertype).isSuperTypeOfArray((GenericArrayType) runtimeType);
+ }
+ // Proceed to regular Type subtype check
+ if (supertype instanceof Class) {
+ return this.someRawTypeIsSubclassOf((Class<?>) supertype);
+ } else if (supertype instanceof ParameterizedType) {
+ return this.isSubtypeOfParameterizedType((ParameterizedType) supertype);
+ } else if (supertype instanceof GenericArrayType) {
+ return this.isSubTypeOfArrayType((GenericArrayType) supertype);
+ } else { // to instanceof TypeVariable
+ return false;
+ }
}
/**
@@ -450,7 +570,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
if (isPrimitive()) {
@SuppressWarnings("unchecked") // this is a primitive class
Class<T> type = (Class<T>) runtimeType;
- return TypeToken.of(Primitives.wrap(type));
+ return of(Primitives.wrap(type));
}
return this;
}
@@ -469,7 +589,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
if (isWrapper()) {
@SuppressWarnings("unchecked") // this is a wrapper class
Class<T> type = (Class<T>) runtimeType;
- return TypeToken.of(Primitives.unwrap(type));
+ return of(Primitives.unwrap(type));
}
return this;
}
@@ -492,7 +612,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
* @since 14.0
*/
public final Invokable<T, Object> method(Method method) {
- checkArgument(of(method.getDeclaringClass()).isAssignableFrom(this),
+ checkArgument(this.someRawTypeIsSubclassOf(method.getDeclaringClass()),
"%s not declared by %s", method, this);
return new Invokable.MethodInvokable<T>(method) {
@Override Type getGenericReturnType() {
@@ -580,7 +700,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
// Java has no way to express ? super T when we parameterize TypeToken vs. Class.
@SuppressWarnings({"unchecked", "rawtypes"})
ImmutableList<Class<? super T>> collectedTypes = (ImmutableList)
- TypeCollector.FOR_RAW_TYPE.collectTypes(getImmediateRawTypes());
+ TypeCollector.FOR_RAW_TYPE.collectTypes(getRawTypes());
return ImmutableSet.copyOf(collectedTypes);
}
@@ -589,7 +709,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
private final class InterfaceSet extends TypeSet {
- private transient final TypeSet allTypes;
+ private final transient TypeSet allTypes;
private transient ImmutableSet<TypeToken<? super T>> interfaces;
InterfaceSet(TypeSet allTypes) {
@@ -615,7 +735,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
// Java has no way to express ? super T when we parameterize TypeToken vs. Class.
@SuppressWarnings({"unchecked", "rawtypes"})
ImmutableList<Class<? super T>> collectedTypes = (ImmutableList)
- TypeCollector.FOR_RAW_TYPE.collectTypes(getImmediateRawTypes());
+ TypeCollector.FOR_RAW_TYPE.collectTypes(getRawTypes());
return FluentIterable.from(collectedTypes)
.filter(new Predicate<Class<?>>() {
@Override public boolean apply(Class<?> type) {
@@ -662,7 +782,7 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
// Java has no way to express ? super T when we parameterize TypeToken vs. Class.
@SuppressWarnings({"unchecked", "rawtypes"})
ImmutableList<Class<? super T>> collectedTypes = (ImmutableList)
- TypeCollector.FOR_RAW_TYPE.classesOnly().collectTypes(getImmediateRawTypes());
+ TypeCollector.FOR_RAW_TYPE.classesOnly().collectTypes(getRawTypes());
return ImmutableSet.copyOf(collectedTypes);
}
@@ -743,183 +863,131 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
return this;
}
- private static boolean isAssignable(Type from, Type to) {
- if (to.equals(from)) {
- return true;
- }
- if (to instanceof WildcardType) {
- return isAssignableToWildcardType(from, (WildcardType) to);
- }
- // if "from" is type variable, it's assignable if any of its "extends"
- // bounds is assignable to "to".
- if (from instanceof TypeVariable) {
- return isAssignableFromAny(((TypeVariable<?>) from).getBounds(), to);
- }
- // if "from" is wildcard, it'a assignable to "to" if any of its "extends"
- // bounds is assignable to "to".
- if (from instanceof WildcardType) {
- return isAssignableFromAny(((WildcardType) from).getUpperBounds(), to);
- }
- if (from instanceof GenericArrayType) {
- return isAssignableFromGenericArrayType((GenericArrayType) from, to);
- }
- // Proceed to regular Type assignability check
- if (to instanceof Class) {
- return isAssignableToClass(from, (Class<?>) to);
- } else if (to instanceof ParameterizedType) {
- return isAssignableToParameterizedType(from, (ParameterizedType) to);
- } else if (to instanceof GenericArrayType) {
- return isAssignableToGenericArrayType(from, (GenericArrayType) to);
- } else { // to instanceof TypeVariable
- return false;
- }
- }
-
- private static boolean isAssignableFromAny(Type[] fromTypes, Type to) {
- for (Type from : fromTypes) {
- if (isAssignable(from, to)) {
+ private boolean someRawTypeIsSubclassOf(Class<?> superclass) {
+ for (Class<?> rawType : getRawTypes()) {
+ if (superclass.isAssignableFrom(rawType)) {
return true;
}
}
return false;
}
- private static boolean isAssignableToClass(Type from, Class<?> to) {
- return to.isAssignableFrom(getRawType(from));
- }
-
- private static boolean isAssignableToWildcardType(
- Type from, WildcardType to) {
- // if "to" is <? extends Foo>, "from" can be:
- // Foo, SubFoo, <? extends Foo>, <? extends SubFoo>, <T extends Foo> or
- // <T extends SubFoo>.
- // if "to" is <? super Foo>, "from" can be:
- // Foo, SuperFoo, <? super Foo> or <? super SuperFoo>.
- return isAssignable(from, supertypeBound(to)) && isAssignableBySubtypeBound(from, to);
- }
-
- private static boolean isAssignableBySubtypeBound(Type from, WildcardType to) {
- Type toSubtypeBound = subtypeBound(to);
- if (toSubtypeBound == null) {
- return true;
- }
- Type fromSubtypeBound = subtypeBound(from);
- if (fromSubtypeBound == null) {
- return false;
- }
- return isAssignable(toSubtypeBound, fromSubtypeBound);
- }
-
- private static boolean isAssignableToParameterizedType(Type from, ParameterizedType to) {
- Class<?> matchedClass = getRawType(to);
- if (!matchedClass.isAssignableFrom(getRawType(from))) {
+ private boolean isSubtypeOfParameterizedType(ParameterizedType supertype) {
+ Class<?> matchedClass = of(supertype).getRawType();
+ if (!this.someRawTypeIsSubclassOf(matchedClass)) {
return false;
}
Type[] typeParams = matchedClass.getTypeParameters();
- Type[] toTypeArgs = to.getActualTypeArguments();
- TypeToken<?> fromTypeToken = of(from);
+ Type[] toTypeArgs = supertype.getActualTypeArguments();
for (int i = 0; i < typeParams.length; i++) {
- // If "to" is "List<? extends CharSequence>"
- // and "from" is StringArrayList,
+ // If 'supertype' is "List<? extends CharSequence>"
+ // and 'this' is StringArrayList,
// First step is to figure out StringArrayList "is-a" List<E> and <E> is
// String.
// typeParams[0] is E and fromTypeToken.get(typeParams[0]) will resolve to
// String.
// String is then matched against <? extends CharSequence>.
- Type fromTypeArg = fromTypeToken.resolveType(typeParams[i]).runtimeType;
- if (!matchTypeArgument(fromTypeArg, toTypeArgs[i])) {
+ if (!resolveType(typeParams[i]).is(toTypeArgs[i])) {
return false;
}
}
return true;
}
- private static boolean isAssignableToGenericArrayType(Type from, GenericArrayType to) {
- if (from instanceof Class) {
- Class<?> fromClass = (Class<?>) from;
+ private boolean isSubTypeOfArrayType(GenericArrayType supertype) {
+ if (runtimeType instanceof Class) {
+ Class<?> fromClass = (Class<?>) runtimeType;
if (!fromClass.isArray()) {
return false;
}
- return isAssignable(fromClass.getComponentType(), to.getGenericComponentType());
- } else if (from instanceof GenericArrayType) {
- GenericArrayType fromArrayType = (GenericArrayType) from;
- return isAssignable(fromArrayType.getGenericComponentType(), to.getGenericComponentType());
+ return of(fromClass.getComponentType()).isSubtypeOf(supertype.getGenericComponentType());
+ } else if (runtimeType instanceof GenericArrayType) {
+ GenericArrayType fromArrayType = (GenericArrayType) runtimeType;
+ return of(fromArrayType.getGenericComponentType())
+ .isSubtypeOf(supertype.getGenericComponentType());
} else {
return false;
}
}
- private static boolean isAssignableFromGenericArrayType(GenericArrayType from, Type to) {
- if (to instanceof Class) {
- Class<?> toClass = (Class<?>) to;
- if (!toClass.isArray()) {
- return toClass == Object.class; // any T[] is assignable to Object
+ private boolean isSuperTypeOfArray(GenericArrayType subtype) {
+ if (runtimeType instanceof Class) {
+ Class<?> thisClass = (Class<?>) runtimeType;
+ if (!thisClass.isArray()) {
+ return thisClass.isAssignableFrom(Object[].class);
}
- return isAssignable(from.getGenericComponentType(), toClass.getComponentType());
- } else if (to instanceof GenericArrayType) {
- GenericArrayType toArrayType = (GenericArrayType) to;
- return isAssignable(from.getGenericComponentType(), toArrayType.getGenericComponentType());
+ return of(subtype.getGenericComponentType()).isSubtypeOf(thisClass.getComponentType());
+ } else if (runtimeType instanceof GenericArrayType) {
+ return of(subtype.getGenericComponentType())
+ .isSubtypeOf(((GenericArrayType) runtimeType).getGenericComponentType());
} else {
return false;
}
}
- private static boolean matchTypeArgument(Type from, Type to) {
- if (from.equals(to)) {
+ /**
+ * Return true if any of the following conditions is met: <ul>
+ * <li>'this' and {@code formalType} are equal
+ * <li>{@code formalType} is {@code <? extends Foo>} and 'this' is a subtype of {@code Foo}
+ * <li>{@code formalType} is {@code <? super Foo>} and 'this' is a supertype of {@code Foo}
+ * </ul>
+ */
+ private boolean is(Type formalType) {
+ if (runtimeType.equals(formalType)) {
return true;
}
- if (to instanceof WildcardType) {
- return isAssignableToWildcardType(from, (WildcardType) to);
+ if (formalType instanceof WildcardType) {
+ // if "formalType" is <? extends Foo>, "this" can be:
+ // Foo, SubFoo, <? extends Foo>, <? extends SubFoo>, <T extends Foo> or
+ // <T extends SubFoo>.
+ // if "formalType" is <? super Foo>, "this" can be:
+ // Foo, SuperFoo, <? super Foo> or <? super SuperFoo>.
+ return every(((WildcardType) formalType).getUpperBounds()).isSupertypeOf(runtimeType)
+ && every(((WildcardType) formalType).getLowerBounds()).isSubtypeOf(runtimeType);
}
return false;
}
- private static Type supertypeBound(Type type) {
- if (type instanceof WildcardType) {
- return supertypeBound((WildcardType) type);
- }
- return type;
+ private static Bounds every(Type[] bounds) {
+ // Every bound must match. On any false, result is false.
+ return new Bounds(bounds, false);
}
- private static Type supertypeBound(WildcardType type) {
- Type[] upperBounds = type.getUpperBounds();
- if (upperBounds.length == 1) {
- return supertypeBound(upperBounds[0]);
- } else if (upperBounds.length == 0) {
- return Object.class;
- } else {
- throw new AssertionError(
- "There should be at most one upper bound for wildcard type: " + type);
- }
+ private static Bounds any(Type[] bounds) {
+ // Any bound matches. On any true, result is true.
+ return new Bounds(bounds, true);
}
- @Nullable private static Type subtypeBound(Type type) {
- if (type instanceof WildcardType) {
- return subtypeBound((WildcardType) type);
- } else {
- return type;
+ private static class Bounds {
+ private final Type[] bounds;
+ private final boolean target;
+
+ Bounds(Type[] bounds, boolean target) {
+ this.bounds = bounds;
+ this.target = target;
}
- }
- @Nullable private static Type subtypeBound(WildcardType type) {
- Type[] lowerBounds = type.getLowerBounds();
- if (lowerBounds.length == 1) {
- return subtypeBound(lowerBounds[0]);
- } else if (lowerBounds.length == 0) {
- return null;
- } else {
- throw new AssertionError(
- "Wildcard should have at most one lower bound: " + type);
+ boolean isSubtypeOf(Type supertype) {
+ for (Type bound : bounds) {
+ if (of(bound).isSubtypeOf(supertype) == target) {
+ return target;
+ }
+ }
+ return !target;
}
- }
- @VisibleForTesting static Class<?> getRawType(Type type) {
- // For wildcard or type variable, the first bound determines the runtime type.
- return getRawTypes(type).iterator().next();
+ boolean isSupertypeOf(Type subtype) {
+ TypeToken<?> type = of(subtype);
+ for (Type bound : bounds) {
+ if (type.isSubtypeOf(bound) == target) {
+ return target;
+ }
+ }
+ return !target;
+ }
}
- @VisibleForTesting static ImmutableSet<Class<?>> getRawTypes(Type type) {
- checkNotNull(type);
+ private ImmutableSet<Class<? super T>> getRawTypes() {
final ImmutableSet.Builder<Class<?>> builder = ImmutableSet.builder();
new TypeVisitor() {
@Override void visitTypeVariable(TypeVariable<?> t) {
@@ -935,11 +1003,15 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
builder.add(t);
}
@Override void visitGenericArrayType(GenericArrayType t) {
- builder.add(Types.getArrayClass(getRawType(t.getGenericComponentType())));
+ builder.add(Types.getArrayClass(
+ of(t.getGenericComponentType()).getRawType()));
}
- }.visit(type);
- return builder.build();
+ }.visit(runtimeType);
+ // Cast from ImmutableSet<Class<?>> to ImmutableSet<Class<? super T>>
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ ImmutableSet<Class<? super T>> result = (ImmutableSet) builder.build();
+ return result;
}
/**
@@ -959,10 +1031,13 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
return result;
}
TypeVariable<Class<T>>[] typeParams = cls.getTypeParameters();
- if (typeParams.length > 0) {
+ Type ownerType = cls.isMemberClass()
+ ? toGenericType(cls.getEnclosingClass()).runtimeType : null;
+
+ if ((typeParams.length > 0) || (ownerType != cls.getEnclosingClass())) {
@SuppressWarnings("unchecked") // Like, it's Iterable<T> for Iterable.class
TypeToken<? extends T> type = (TypeToken<? extends T>)
- of(Types.newParameterizedType(cls, typeParams));
+ of(Types.newParameterizedTypeWithOwner(ownerType, cls, typeParams));
return type;
} else {
return of(cls);
@@ -974,8 +1049,8 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl
for (Type upperBound : upperBounds) {
@SuppressWarnings("unchecked") // T's upperbound is <? super T>.
TypeToken<? super T> bound = (TypeToken<? super T>) of(upperBound);
- if (of(supertype).isAssignableFrom(bound)) {
- @SuppressWarnings({"rawtypes", "unchecked"}) // guarded by the isAssignableFrom check.
+ if (bound.isSubtypeOf(supertype)) {
+ @SuppressWarnings({"rawtypes", "unchecked"}) // guarded by the isSubtypeOf check.
TypeToken<? super T> result = bound.getSupertype((Class) supertype);
return result;
}
diff --git a/guava/src/com/google/common/reflect/Types.java b/guava/src/com/google/common/reflect/Types.java
index d6c56e8..a86e5a2 100644
--- a/guava/src/com/google/common/reflect/Types.java
+++ b/guava/src/com/google/common/reflect/Types.java
@@ -26,6 +26,7 @@ import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import java.io.Serializable;
@@ -33,12 +34,15 @@ import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
+import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
+import java.security.AccessControlException;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicReference;
@@ -149,7 +153,7 @@ final class Types {
*/
static <D extends GenericDeclaration> TypeVariable<D> newArtificialTypeVariable(
D declaration, String name, Type... bounds) {
- return new TypeVariableImpl<D>(
+ return newTypeVariableImpl(
declaration,
name,
(bounds.length == 0)
@@ -317,8 +321,76 @@ final class Types {
private static final long serialVersionUID = 0;
}
- private static final class TypeVariableImpl<D extends GenericDeclaration>
- implements TypeVariable<D> {
+ private static <D extends GenericDeclaration> TypeVariable<D> newTypeVariableImpl(
+ D genericDeclaration, String name, Type[] bounds) {
+ TypeVariableImpl<D> typeVariableImpl =
+ new TypeVariableImpl<D>(genericDeclaration, name, bounds);
+ @SuppressWarnings("unchecked")
+ TypeVariable<D> typeVariable = Reflection.newProxy(
+ TypeVariable.class, new TypeVariableInvocationHandler(typeVariableImpl));
+ return typeVariable;
+ }
+
+ /**
+ * Invocation handler to work around a compatibility problem between Java 7 and Java 8.
+ *
+ * <p>Java 8 introduced a new method {@code getAnnotatedBounds()} in the {@link TypeVariable}
+ * interface, whose return type {@code AnnotatedType[]} is also new in Java 8. That means that we
+ * cannot implement that interface in source code in a way that will compile on both Java 7 and
+ * Java 8. If we include the {@code getAnnotatedBounds()} method then its return type means
+ * it won't compile on Java 7, while if we don't include the method then the compiler will
+ * complain that an abstract method is unimplemented. So instead we use a dynamic proxy to
+ * get an implementation. If the method being called on the {@code TypeVariable} instance has
+ * the same name as one of the public methods of {@link TypeVariableImpl}, the proxy calls
+ * the same method on its instance of {@code TypeVariableImpl}. Otherwise it throws {@link
+ * UnsupportedOperationException}; this should only apply to {@code getAnnotatedBounds()}. This
+ * does mean that users on Java 8 who obtain an instance of {@code TypeVariable} from {@link
+ * TypeResolver#resolveType} will not be able to call {@code getAnnotatedBounds()} on it, but that
+ * should hopefully be rare.
+ *
+ * <p>This workaround should be removed at a distant future time when we no longer support Java
+ * versions earlier than 8.
+ */
+ private static final class TypeVariableInvocationHandler implements InvocationHandler {
+ private static final ImmutableMap<String, Method> typeVariableMethods;
+ static {
+ ImmutableMap.Builder<String, Method> builder = ImmutableMap.builder();
+ for (Method method : TypeVariableImpl.class.getMethods()) {
+ if (method.getDeclaringClass().equals(TypeVariableImpl.class)) {
+ try {
+ method.setAccessible(true);
+ } catch (AccessControlException e) {
+ // OK: the method is accessible to us anyway. The setAccessible call is only for
+ // unusual execution environments where that might not be true.
+ }
+ builder.put(method.getName(), method);
+ }
+ }
+ typeVariableMethods = builder.build();
+ }
+
+ private final TypeVariableImpl<?> typeVariableImpl;
+
+ TypeVariableInvocationHandler(TypeVariableImpl<?> typeVariableImpl) {
+ this.typeVariableImpl = typeVariableImpl;
+ }
+
+ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ String methodName = method.getName();
+ Method typeVariableMethod = typeVariableMethods.get(methodName);
+ if (typeVariableMethod == null) {
+ throw new UnsupportedOperationException(methodName);
+ } else {
+ try {
+ return typeVariableMethod.invoke(typeVariableImpl, args);
+ } catch (InvocationTargetException e) {
+ throw e.getCause();
+ }
+ }
+ }
+ }
+
+ private static final class TypeVariableImpl<D extends GenericDeclaration> {
private final D genericDeclaration;
private final String name;
@@ -331,15 +403,19 @@ final class Types {
this.bounds = ImmutableList.copyOf(bounds);
}
- @Override public Type[] getBounds() {
+ public Type[] getBounds() {
return toArray(bounds);
}
- @Override public D getGenericDeclaration() {
+ public D getGenericDeclaration() {
return genericDeclaration;
}
- @Override public String getName() {
+ public String getName() {
+ return name;
+ }
+
+ public String getTypeName() {
return name;
}
@@ -354,8 +430,12 @@ final class Types {
@Override public boolean equals(Object obj) {
if (NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY) {
// equal only to our TypeVariable implementation with identical bounds
- if (obj instanceof TypeVariableImpl) {
- TypeVariableImpl<?> that = (TypeVariableImpl<?>) obj;
+ if (obj != null
+ && Proxy.isProxyClass(obj.getClass())
+ && Proxy.getInvocationHandler(obj) instanceof TypeVariableInvocationHandler) {
+ TypeVariableInvocationHandler typeVariableInvocationHandler =
+ (TypeVariableInvocationHandler) Proxy.getInvocationHandler(obj);
+ TypeVariableImpl<?> that = typeVariableInvocationHandler.typeVariableImpl;
return name.equals(that.getName())
&& genericDeclaration.equals(that.getGenericDeclaration())
&& bounds.equals(that.bounds);
diff --git a/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java b/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java
index aefe27f..68a36ca 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java
@@ -18,7 +18,6 @@ package com.google.common.util.concurrent;
import com.google.common.annotations.Beta;
import com.google.common.base.Supplier;
-import com.google.common.base.Throwables;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -54,7 +53,8 @@ public abstract class AbstractExecutionThreadService implements Service {
try {
startUp();
notifyStarted();
-
+ // If stopAsync() is called while starting we may be in the STOPPING state in which
+ // case we should skip right down to shutdown.
if (isRunning()) {
try {
AbstractExecutionThreadService.this.run();
@@ -62,11 +62,14 @@ public abstract class AbstractExecutionThreadService implements Service {
try {
shutDown();
} catch (Exception ignored) {
+ // TODO(lukes): if guava ever moves to java7, this would be a good candidate for
+ // a suppressed exception, or maybe we could generalize Closer.Suppressor
logger.log(Level.WARNING,
"Error while attempting to shut down the service"
+ " after failure.", ignored);
}
- throw t;
+ notifyFailed(t);
+ return;
}
}
@@ -74,7 +77,6 @@ public abstract class AbstractExecutionThreadService implements Service {
notifyStopped();
} catch (Throwable t) {
notifyFailed(t);
- throw Throwables.propagate(t);
}
}
});
@@ -83,6 +85,10 @@ public abstract class AbstractExecutionThreadService implements Service {
@Override protected void doStop() {
triggerShutdown();
}
+
+ @Override public String toString() {
+ return AbstractExecutionThreadService.this.toString();
+ }
};
/**
diff --git a/guava/src/com/google/common/util/concurrent/AbstractFuture.java b/guava/src/com/google/common/util/concurrent/AbstractFuture.java
index 8f6bb0f..bd891e0 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractFuture.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractFuture.java
@@ -17,58 +17,286 @@
package com.google.common.util.concurrent;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater;
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Throwables;
+
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import java.util.concurrent.locks.LockSupport;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.annotation.Nullable;
/**
- * An abstract implementation of the {@link ListenableFuture} interface. This
- * class is preferable to {@link java.util.concurrent.FutureTask} for two
- * reasons: It implements {@code ListenableFuture}, and it does not implement
- * {@code Runnable}. (If you want a {@code Runnable} implementation of {@code
- * ListenableFuture}, create a {@link ListenableFutureTask}, or submit your
- * tasks to a {@link ListeningExecutorService}.)
- *
- * <p>This class implements all methods in {@code ListenableFuture}.
- * Subclasses should provide a way to set the result of the computation through
- * the protected methods {@link #set(Object)} and
- * {@link #setException(Throwable)}. Subclasses may also override {@link
- * #interruptTask()}, which will be invoked automatically if a call to {@link
- * #cancel(boolean) cancel(true)} succeeds in canceling the future.
- *
- * <p>{@code AbstractFuture} uses an {@link AbstractQueuedSynchronizer} to deal
- * with concurrency issues and guarantee thread safety.
- *
- * <p>The state changing methods all return a boolean indicating success or
- * failure in changing the future's state. Valid states are running,
- * completed, failed, or cancelled.
+ * An abstract implementation of {@link ListenableFuture}, intended for advanced users only. More
+ * common ways to create a {@code ListenableFuture} include instantiating a {@link SettableFuture},
+ * submitting a task to a {@link ListeningExecutorService}, and deriving a {@code Future} from an
+ * existing one, typically using methods like {@link Futures#transform(ListenableFuture, Function)
+ * Futures.transform} and {@link Futures#catching(ListenableFuture, Class, Function)
+ * Futures.catching}.
*
- * <p>This class uses an {@link ExecutionList} to guarantee that all registered
- * listeners will be executed, either when the future finishes or, for listeners
- * that are added after the future completes, immediately.
- * {@code Runnable}-{@code Executor} pairs are stored in the execution list but
- * are not necessarily executed in the order in which they were added. (If a
- * listener is added after the Future is complete, it will be executed
- * immediately, even if earlier listeners have not been executed. Additionally,
- * executors need not guarantee FIFO execution, or different listeners may run
- * in different executors.)
+ * <p>This class implements all methods in {@code ListenableFuture}. Subclasses should provide a way
+ * to set the result of the computation through the protected methods {@link #set(Object)}, {@link
+ * #setFuture(ListenableFuture)} and {@link #setException(Throwable)}. Subclasses may also override
+ * {@link #interruptTask()}, which will be invoked automatically if a call to {@link
+ * #cancel(boolean) cancel(true)} succeeds in canceling the future. Subclasses should rarely
+ * override other methods.
*
* @author Sven Mawson
+ * @author Luke Sandberg
* @since 1.0
*/
+ at GwtCompatible(emulated = true)
public abstract class AbstractFuture<V> implements ListenableFuture<V> {
+ private static final boolean GENERATE_CANCELLATION_CAUSES =
+ Boolean.parseBoolean(
+ System.getProperty("guava.concurrent.generate_cancellation_cause", "false"));
+
+ /**
+ * A less abstract subclass of AbstractFuture. This can be used to optimize setFuture by ensuring
+ * that {@link #get} calls exactly the implementation of {@link AbstractFuture#get}.
+ */
+ abstract static class TrustedFuture<V> extends AbstractFuture<V> {
+ // N.B. cancel is not overridden to be final, because many future utilities need to override
+ // cancel in order to propagate cancellation to other futures.
+ // TODO(lukes): with maybePropagateCancellation this is no longer really true. Track down the
+ // final few cases and eliminate their overrides of cancel()
+
+ @Override public final V get() throws InterruptedException, ExecutionException {
+ return super.get();
+ }
+
+ @Override public final V get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return super.get(timeout, unit);
+ }
+
+ @Override public final boolean isDone() {
+ return super.isDone();
+ }
+
+ @Override public final boolean isCancelled() {
+ return super.isCancelled();
+ }
+
+ @Override public final void addListener(Runnable listener, Executor executor) {
+ super.addListener(listener, executor);
+ }
+ }
+
+ // Logger to log exceptions caught when running listeners.
+ private static final Logger log = Logger.getLogger(AbstractFuture.class.getName());
+
+ // A heuristic for timed gets. If the remaining timeout is less than this, spin instead of
+ // blocking. This value is what AbstractQueuedSynchronizer uses.
+ private static final long SPIN_THRESHOLD_NANOS = 1000L;
+
+ private static final AtomicHelper ATOMIC_HELPER;
+
+ static {
+ AtomicHelper helper;
+
+ try {
+ helper = new UnsafeAtomicHelper();
+ } catch (Throwable unsafeFailure) {
+ // catch absolutely everything and fall through to our 'SafeAtomicHelper'
+ // The access control checks that ARFU does means the caller class has to be AbstractFuture
+ // instead of SafeAtomicHelper, so we annoyingly define these here
+ try {
+ helper = new SafeAtomicHelper(
+ newUpdater(Waiter.class, Thread.class, "thread"),
+ newUpdater(Waiter.class, Waiter.class, "next"),
+ newUpdater(AbstractFuture.class, Waiter.class, "waiters"),
+ newUpdater(AbstractFuture.class, Listener.class, "listeners"),
+ newUpdater(AbstractFuture.class, Object.class, "value"));
+ } catch (Throwable atomicReferenceFieldUpdaterFailure) {
+ // Some Android 5.0.x Samsung devices have bugs in JDK reflection APIs that cause
+ // getDeclaredField to throw a NoSuchFieldException when the field is definitely there.
+ // For these users fallback to a suboptimal implementation, based on synchronized. This
+ // will be a definite performance hit to those users.
+ log.log(Level.SEVERE, "UnsafeAtomicHelper is broken!", unsafeFailure);
+ log.log(Level.SEVERE, "SafeAtomicHelper is broken!", atomicReferenceFieldUpdaterFailure);
+ helper = new SynchronizedHelper();
+ }
+ }
+ ATOMIC_HELPER = helper;
+
+ // Prevent rare disastrous classloading in first call to LockSupport.park.
+ // See: https://bugs.openjdk.java.net/browse/JDK-8074773
+ @SuppressWarnings("unused")
+ Class<?> ensureLoaded = LockSupport.class;
+ }
+
+ /**
+ * Waiter links form a Treiber stack, in the {@link #waiters} field.
+ */
+ private static final class Waiter {
+ static final Waiter TOMBSTONE = new Waiter(false /* ignored param */);
+
+ @Nullable volatile Thread thread;
+ @Nullable volatile Waiter next;
+
+ // Constructor for the TOMBSTONE, avoids use of ATOMIC_HELPER in case this class is loaded
+ // before the ATOMIC_HELPER. Apparently this is possible on some android platforms.
+ Waiter(boolean unused) {}
+
+ Waiter() {
+ // avoid volatile write, write is made visible by subsequent CAS on waiters field
+ ATOMIC_HELPER.putThread(this, Thread.currentThread());
+ }
+
+ // non-volatile write to the next field. Should be made visible by subsequent CAS on waiters
+ // field.
+ void setNext(Waiter next) {
+ ATOMIC_HELPER.putNext(this, next);
+ }
+
+ void unpark() {
+ // This is racy with removeWaiter. The consequence of the race is that we may spuriously
+ // call unpark even though the thread has already removed itself from the list. But even if
+ // we did use a CAS, that race would still exist (it would just be ever so slightly smaller).
+ Thread w = thread;
+ if (w != null) {
+ thread = null;
+ LockSupport.unpark(w);
+ }
+ }
+ }
+
+ /**
+ * Marks the given node as 'deleted' (null waiter) and then scans the list to unlink all deleted
+ * nodes. This is an O(n) operation in the common case (and O(n^2) in the worst), but we are
+ * saved by two things.
+ * <ul>
+ * <li>This is only called when a waiting thread times out or is interrupted. Both of which
+ * should be rare.
+ * <li>The waiters list should be very short.
+ * </ul>
+ */
+ private void removeWaiter(Waiter node) {
+ node.thread = null; // mark as 'deleted'
+ restart: while (true) {
+ Waiter pred = null;
+ Waiter curr = waiters;
+ if (curr == Waiter.TOMBSTONE) {
+ return; // give up if someone is calling complete
+ }
+ Waiter succ;
+ while (curr != null) {
+ succ = curr.next;
+ if (curr.thread != null) { // we aren't unlinking this node, update pred.
+ pred = curr;
+ } else if (pred != null) { // We are unlinking this node and it has a predecessor.
+ pred.next = succ;
+ if (pred.thread == null) { // We raced with another node that unlinked pred. Restart.
+ continue restart;
+ }
+ } else if (!ATOMIC_HELPER.casWaiters(this, curr, succ)) { // We are unlinking head
+ continue restart; // We raced with an add or complete
+ }
+ curr = succ;
+ }
+ break;
+ }
+ }
+
+ /** Listeners also form a stack through the {@link #listeners} field. */
+ private static final class Listener {
+ static final Listener TOMBSTONE = new Listener(null, null);
+ final Runnable task;
+ final Executor executor;
+
+ // writes to next are made visible by subsequent CAS's on the listeners field
+ @Nullable Listener next;
+
+ Listener(Runnable task, Executor executor) {
+ this.task = task;
+ this.executor = executor;
+ }
+ }
+
+ /** A special value to represent {@code null}. */
+ private static final Object NULL = new Object();
+
+ /** A special value to represent failure, when {@link #setException} is called successfully. */
+ private static final class Failure {
+ static final Failure FALLBACK_INSTANCE = new Failure(
+ new Throwable("Failure occurred while trying to finish a future.") {
+ @Override public synchronized Throwable fillInStackTrace() {
+ return this; // no stack trace
+ }
+ });
+ final Throwable exception;
- /** Synchronization control for AbstractFutures. */
- private final Sync<V> sync = new Sync<V>();
+ Failure(Throwable exception) {
+ this.exception = checkNotNull(exception);
+ }
+ }
+
+ /** A special value to represent cancellation and the 'wasInterrupted' bit. */
+ private static final class Cancellation {
+ final boolean wasInterrupted;
+ @Nullable final Throwable cause;
+
+ Cancellation(boolean wasInterrupted, @Nullable Throwable cause) {
+ this.wasInterrupted = wasInterrupted;
+ this.cause = cause;
+ }
+ }
+
+ /** A special value that encodes the 'setFuture' state. */
+ private final class SetFuture implements Runnable {
+ final ListenableFuture<? extends V> future;
+
+ SetFuture(ListenableFuture<? extends V> future) {
+ this.future = future;
+ }
+
+ @Override public void run() {
+ if (value != this) {
+ // nothing to do, we must have been cancelled
+ return;
+ }
+ completeWithFuture(future, this);
+ }
+ }
+
+ // TODO(lukes): investigate using the @Contended annotation on these fields when jdk8 is
+ // available.
+ /**
+ * This field encodes the current state of the future.
+ *
+ * <p>The valid values are:
+ * <ul>
+ * <li>{@code null} initial state, nothing has happened.
+ * <li>{@link Cancellation} terminal state, {@code cancel} was called.
+ * <li>{@link Failure} terminal state, {@code setException} was called.
+ * <li>{@link SetFuture} intermediate state, {@code setFuture} was called.
+ * <li>{@link #NULL} terminal state, {@code set(null)} was called.
+ * <li>Any other non-null value, terminal state, {@code set} was called with a non-null
+ * argument.
+ * </ul>
+ */
+ private volatile Object value;
+
+ /** All listeners. */
+ private volatile Listener listeners;
- // The execution list to hold our executors.
- private final ExecutionList executionList = new ExecutionList();
+ /** All waiting threads. */
+ private volatile Waiter waiters;
/**
* Constructor for use by subclasses.
@@ -79,6 +307,31 @@ public abstract class AbstractFuture<V> implements ListenableFuture<V> {
* Improve the documentation of when InterruptedException is thrown. Our
* behavior matches the JDK's, but the JDK's documentation is misleading.
*/
+
+ // Gets and Timed Gets
+ //
+ // * Be responsive to interruption
+ // * Don't create Waiter nodes if you aren't going to park, this helps reduce contention on the
+ // waiters field.
+ // * Future completion is defined by when #value becomes non-null/non SetFuture
+ // * Future completion can be observed if the waiters field contains a TOMBSTONE
+
+ // Timed Get
+ // There are a few design constraints to consider
+ // * We want to be responsive to small timeouts, unpark() has non trivial latency overheads (I
+ // have observed 12 micros on 64 bit linux systems to wake up a parked thread). So if the
+ // timeout is small we shouldn't park(). This needs to be traded off with the cpu overhead of
+ // spinning, so we use SPIN_THRESHOLD_NANOS which is what AbstractQueuedSynchronizer uses for
+ // similar purposes.
+ // * We want to behave reasonably for timeouts of 0
+ // * We are more responsive to completion than timeouts. This is because parkNanos depends on
+ // system scheduling and as such we could either miss our deadline, or unpark() could be delayed
+ // so that it looks like we timed out even though we didn't. For comparison FutureTask respects
+ // completion preferably and AQS is non-deterministic (depends on where in the queue the waiter
+ // is). If we wanted to be strict about it, we could store the unpark() time in the Waiter
+ // node and we could use that to make a decision about whether or not we timed out prior to
+ // being unparked.
+
/**
* {@inheritDoc}
*
@@ -91,9 +344,71 @@ public abstract class AbstractFuture<V> implements ListenableFuture<V> {
* @throws CancellationException {@inheritDoc}
*/
@Override
- public V get(long timeout, TimeUnit unit) throws InterruptedException,
- TimeoutException, ExecutionException {
- return sync.get(unit.toNanos(timeout));
+ public V get(long timeout, TimeUnit unit)
+ throws InterruptedException, TimeoutException, ExecutionException {
+ // NOTE: if timeout < 0, remainingNanos will be < 0 and we will fall into the while(true) loop
+ // at the bottom and throw a timeoutexception.
+ long remainingNanos = unit.toNanos(timeout); // we rely on the implicit null check on unit.
+ if (Thread.interrupted()) {
+ throw new InterruptedException();
+ }
+ Object localValue = value;
+ if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
+ return getDoneValue(localValue);
+ }
+ // we delay calling nanoTime until we know we will need to either park or spin
+ final long endNanos = remainingNanos > 0 ? System.nanoTime() + remainingNanos : 0;
+ long_wait_loop: if (remainingNanos >= SPIN_THRESHOLD_NANOS) {
+ Waiter oldHead = waiters;
+ if (oldHead != Waiter.TOMBSTONE) {
+ Waiter node = new Waiter();
+ do {
+ node.setNext(oldHead);
+ if (ATOMIC_HELPER.casWaiters(this, oldHead, node)) {
+ while (true) {
+ LockSupport.parkNanos(this, remainingNanos);
+ // Check interruption first, if we woke up due to interruption we need to honor that.
+ if (Thread.interrupted()) {
+ removeWaiter(node);
+ throw new InterruptedException();
+ }
+
+ // Otherwise re-read and check doneness. If we loop then it must have been a spurious
+ // wakeup
+ localValue = value;
+ if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
+ return getDoneValue(localValue);
+ }
+
+ // timed out?
+ remainingNanos = endNanos - System.nanoTime();
+ if (remainingNanos < SPIN_THRESHOLD_NANOS) {
+ // Remove the waiter, one way or another we are done parking this thread.
+ removeWaiter(node);
+ break long_wait_loop; // jump down to the busy wait loop
+ }
+ }
+ }
+ oldHead = waiters; // re-read and loop.
+ } while (oldHead != Waiter.TOMBSTONE);
+ }
+ // re-read value, if we get here then we must have observed a TOMBSTONE while trying to add a
+ // waiter.
+ return getDoneValue(value);
+ }
+ // If we get here then we have remainingNanos < SPIN_THRESHOLD_NANOS and there is no node on the
+ // waiters list
+ while (remainingNanos > 0) {
+ localValue = value;
+ if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
+ return getDoneValue(localValue);
+ }
+ if (Thread.interrupted()) {
+ throw new InterruptedException();
+ }
+ remainingNanos = endNanos - System.nanoTime();
+ }
+ throw new TimeoutException();
}
/*
@@ -111,31 +426,125 @@ public abstract class AbstractFuture<V> implements ListenableFuture<V> {
* or during the call (optional but recommended).
* @throws CancellationException {@inheritDoc}
*/
- @Override
- public V get() throws InterruptedException, ExecutionException {
- return sync.get();
+ @Override public V get() throws InterruptedException, ExecutionException {
+ if (Thread.interrupted()) {
+ throw new InterruptedException();
+ }
+ Object localValue = value;
+ if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
+ return getDoneValue(localValue);
+ }
+ Waiter oldHead = waiters;
+ if (oldHead != Waiter.TOMBSTONE) {
+ Waiter node = new Waiter();
+ do {
+ node.setNext(oldHead);
+ if (ATOMIC_HELPER.casWaiters(this, oldHead, node)) {
+ // we are on the stack, now wait for completion.
+ while (true) {
+ LockSupport.park(this);
+ // Check interruption first, if we woke up due to interruption we need to honor that.
+ if (Thread.interrupted()) {
+ removeWaiter(node);
+ throw new InterruptedException();
+ }
+ // Otherwise re-read and check doneness. If we loop then it must have been a spurious
+ // wakeup
+ localValue = value;
+ if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
+ return getDoneValue(localValue);
+ }
+ }
+ }
+ oldHead = waiters; // re-read and loop.
+ } while (oldHead != Waiter.TOMBSTONE);
+ }
+ // re-read value, if we get here then we must have observed a TOMBSTONE while trying to add a
+ // waiter.
+ return getDoneValue(value);
+ }
+
+ /**
+ * Unboxes {@code obj}. Assumes that obj is not {@code null} or a {@link SetFuture}.
+ */
+ private V getDoneValue(Object obj) throws ExecutionException {
+ // While this seems like it might be too branch-y, simple benchmarking proves it to be
+ // unmeasurable (comparing done AbstractFutures with immediateFuture)
+ if (obj instanceof Cancellation) {
+ throw cancellationExceptionWithCause("Task was cancelled.", ((Cancellation) obj).cause);
+ } else if (obj instanceof Failure) {
+ throw new ExecutionException(((Failure) obj).exception);
+ } else if (obj == NULL) {
+ return null;
+ } else {
+ @SuppressWarnings("unchecked") // this is the only other option
+ V asV = (V) obj;
+ return asV;
+ }
}
@Override
public boolean isDone() {
- return sync.isDone();
+ final Object localValue = value;
+ return localValue != null & !(localValue instanceof AbstractFuture.SetFuture);
}
@Override
public boolean isCancelled() {
- return sync.isCancelled();
+ final Object localValue = value;
+ return localValue instanceof Cancellation;
}
+ /**
+ * {@inheritDoc}
+ *
+ * <p>If a cancellation attempt succeeds on a {@code Future} that had previously been {@linkplain
+ * #setFuture set asynchronously}, then the cancellation will also be propagated to the delegate
+ * {@code Future} that was supplied in the {@code setFuture} call.
+ */
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
- if (!sync.cancel(mayInterruptIfRunning)) {
- return false;
- }
- executionList.execute();
- if (mayInterruptIfRunning) {
- interruptTask();
+ Object localValue = value;
+ if (localValue == null | localValue instanceof AbstractFuture.SetFuture) {
+ // Try to delay allocating the exception. At this point we may still lose the CAS, but it is
+ // certainly less likely.
+ // TODO(lukes): this exception actually makes cancellation significantly more expensive :(
+ // I wonder if we should consider removing it or providing a mechanism to not do it.
+ Throwable cause = GENERATE_CANCELLATION_CAUSES ? newCancellationCause() : null;
+ Object valueToSet = new Cancellation(mayInterruptIfRunning, cause);
+ do {
+ if (ATOMIC_HELPER.casValue(this, localValue, valueToSet)) {
+ // We call interuptTask before calling complete(), first which is consistent with
+ // FutureTask
+ if (mayInterruptIfRunning) {
+ interruptTask();
+ }
+ complete();
+ if (localValue instanceof AbstractFuture.SetFuture) {
+ // propagate cancellation to the future set in setfuture, this is racy, and we don't
+ // care if we are successful or not.
+ ((AbstractFuture<?>.SetFuture) localValue).future.cancel(mayInterruptIfRunning);
+ }
+ return true;
+ }
+ // obj changed, reread
+ localValue = value;
+ // obj cannot be null at this point, because value can only change from null to non-null. So
+ // if value changed (and it did since we lost the CAS), then it cannot be null.
+ } while (localValue instanceof AbstractFuture.SetFuture);
}
- return true;
+ return false;
+ }
+
+ /**
+ * Returns an exception to be used as the cause of the CancellationException thrown by
+ * {@link #get}.
+ *
+ * <p>Note: this method may be called speculatively. There is no guarantee that the future will
+ * be cancelled if this method is called.
+ */
+ private Throwable newCancellationCause() {
+ return new CancellationException("Future.cancel() was called.");
}
/**
@@ -157,7 +566,8 @@ public abstract class AbstractFuture<V> implements ListenableFuture<V> {
* @since 14.0
*/
protected final boolean wasInterrupted() {
- return sync.wasInterrupted();
+ final Object localValue = value;
+ return (localValue instanceof Cancellation) && ((Cancellation) localValue).wasInterrupted;
}
/**
@@ -166,231 +576,453 @@ public abstract class AbstractFuture<V> implements ListenableFuture<V> {
* @since 10.0
*/
@Override
- public void addListener(Runnable listener, Executor exec) {
- executionList.add(listener, exec);
+ public void addListener(Runnable listener, Executor executor) {
+ checkNotNull(listener, "Runnable was null.");
+ checkNotNull(executor, "Executor was null.");
+ Listener oldHead = listeners;
+ if (oldHead != Listener.TOMBSTONE) {
+ Listener newNode = new Listener(listener, executor);
+ do {
+ newNode.next = oldHead;
+ if (ATOMIC_HELPER.casListeners(this, oldHead, newNode)) {
+ return;
+ }
+ oldHead = listeners; // re-read
+ } while (oldHead != Listener.TOMBSTONE);
+ }
+ // If we get here then the Listener TOMBSTONE was set, which means the future is done, call
+ // the listener.
+ executeListener(listener, executor);
}
/**
- * Subclasses should invoke this method to set the result of the computation
- * to {@code value}. This will set the state of the future to
- * {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the
- * state was successfully changed.
+ * Sets the result of this {@code Future} unless this {@code Future} has already been cancelled or
+ * set (including {@linkplain #setFuture set asynchronously}). When a call to this method returns,
+ * the {@code Future} is guaranteed to be {@linkplain #isDone done} <b>only if</b> the call was
+ * accepted (in which case it returns {@code true}). If it returns {@code false}, the {@code
+ * Future} may have previously been set asynchronously, in which case its result may not be known
+ * yet. That result, though not yet known, cannot by overridden by a call to a {@code set*}
+ * method, only by a call to {@link #cancel}.
*
- * @param value the value that was the result of the task.
- * @return true if the state was successfully changed.
+ * @param value the value to be used as the result
+ * @return true if the attempt was accepted, completing the {@code Future}
*/
protected boolean set(@Nullable V value) {
- boolean result = sync.set(value);
- if (result) {
- executionList.execute();
+ Object valueToSet = value == null ? NULL : value;
+ if (ATOMIC_HELPER.casValue(this, null, valueToSet)) {
+ complete();
+ return true;
}
- return result;
+ return false;
}
/**
- * Subclasses should invoke this method to set the result of the computation
- * to an error, {@code throwable}. This will set the state of the future to
- * {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the
- * state was successfully changed.
+ * Sets the failed result of this {@code Future} unless this {@code Future} has already been
+ * cancelled or set (including {@linkplain #setFuture set asynchronously}). When a call to this
+ * method returns, the {@code Future} is guaranteed to be {@linkplain #isDone done} <b>only if</b>
+ * the call was accepted (in which case it returns {@code true}). If it returns {@code false}, the
+ * {@code Future} may have previously been set asynchronously, in which case its result may not be
+ * known yet. That result, though not yet known, cannot by overridden by a call to a {@code set*}
+ * method, only by a call to {@link #cancel}.
*
- * @param throwable the exception that the task failed with.
- * @return true if the state was successfully changed.
+ * @param throwable the exception to be used as the failed result
+ * @return true if the attempt was accepted, completing the {@code Future}
*/
protected boolean setException(Throwable throwable) {
- boolean result = sync.setException(checkNotNull(throwable));
- if (result) {
- executionList.execute();
+ Object valueToSet = new Failure(checkNotNull(throwable));
+ if (ATOMIC_HELPER.casValue(this, null, valueToSet)) {
+ complete();
+ return true;
}
- return result;
+ return false;
}
/**
- * <p>Following the contract of {@link AbstractQueuedSynchronizer} we create a
- * private subclass to hold the synchronizer. This synchronizer is used to
- * implement the blocking and waiting calls as well as to handle state changes
- * in a thread-safe manner. The current state of the future is held in the
- * Sync state, and the lock is released whenever the state changes to
- * {@link #COMPLETED}, {@link #CANCELLED}, or {@link #INTERRUPTED}
+ * Sets the result of this {@code Future} to match the supplied input {@code Future} once the
+ * supplied {@code Future} is done, unless this {@code Future} has already been cancelled or set
+ * (including "set asynchronously," defined below).
*
- * <p>To avoid races between threads doing release and acquire, we transition
- * to the final state in two steps. One thread will successfully CAS from
- * RUNNING to COMPLETING, that thread will then set the result of the
- * computation, and only then transition to COMPLETED, CANCELLED, or
- * INTERRUPTED.
+ * <p>If the supplied future is {@linkplain #isDone done} when this method is called and the call
+ * is accepted, then this future is guaranteed to have been completed with the supplied future by
+ * the time this method returns. If the supplied future is not done and the call is accepted, then
+ * the future will be <i>set asynchronously</i>. Note that such a result, though not yet known,
+ * cannot by overridden by a call to a {@code set*} method, only by a call to {@link #cancel}.
*
- * <p>We don't use the integer argument passed between acquire methods so we
- * pass around a -1 everywhere.
+ * <p>If the call {@code setFuture(delegate)} is accepted and this {@code Future} is later
+ * cancelled, cancellation will be propagated to {@code delegate}. Additionally, any call to
+ * {@code setFuture} after any cancellation will propagate cancellation to the supplied {@code
+ * Future}.
+ *
+ * @param future the future to delegate to
+ * @return true if the attempt was accepted, indicating that the {@code Future} was not previously
+ * cancelled or set.
+ * @since 19.0
+ */
+ @Beta protected boolean setFuture(ListenableFuture<? extends V> future) {
+ checkNotNull(future);
+ Object localValue = value;
+ if (localValue == null) {
+ if (future.isDone()) {
+ return completeWithFuture(future, null);
+ }
+ SetFuture valueToSet = new SetFuture(future);
+ if (ATOMIC_HELPER.casValue(this, null, valueToSet)) {
+ // the listener is responsible for calling completeWithFuture, directExecutor is appropriate
+ // since all we are doing is unpacking a completed future which should be fast.
+ try {
+ future.addListener(valueToSet, directExecutor());
+ } catch (Throwable t) {
+ // addListener has thrown an exception! SetFuture.run can't throw any exceptions so this
+ // must have been caused by addListener itself. The most likely explanation is a
+ // misconfigured mock. Try to switch to Failure.
+ Failure failure;
+ try {
+ failure = new Failure(t);
+ } catch (Throwable oomMostLikely) {
+ failure = Failure.FALLBACK_INSTANCE;
+ }
+ // Note: The only way this CAS could fail is if cancel() has raced with us. That is ok.
+ ATOMIC_HELPER.casValue(this, valueToSet, failure);
+ }
+ return true;
+ }
+ localValue = value; // we lost the cas, fall through and maybe cancel
+ }
+ // The future has already been set to something. If it is cancellation we should cancel the
+ // incoming future.
+ if (localValue instanceof Cancellation) {
+ // we don't care if it fails, this is best-effort.
+ future.cancel(((Cancellation) localValue).wasInterrupted);
+ }
+ return false;
+ }
+
+ /**
+ * Called when a future passed via setFuture has completed.
+ *
+ * @param future the done future to complete this future with.
+ * @param expected the expected value of the {@link #value} field.
*/
- static final class Sync<V> extends AbstractQueuedSynchronizer {
+ private boolean completeWithFuture(ListenableFuture<? extends V> future, Object expected) {
+ Object valueToSet;
+ if (future instanceof TrustedFuture) {
+ // Break encapsulation for TrustedFuture instances since we know that subclasses cannot
+ // override .get() (since it is final) and therefore this is equivalent to calling .get()
+ // and unpacking the exceptions like we do below (just much faster because it is a single
+ // field read instead of a read, several branches and possibly creating exceptions).
+ valueToSet = ((AbstractFuture<?>) future).value;
+ } else {
+ // Otherwise calculate valueToSet by calling .get()
+ try {
+ V v = Uninterruptibles.getUninterruptibly(future);
+ valueToSet = v == null ? NULL : v;
+ } catch (ExecutionException exception) {
+ valueToSet = new Failure(exception.getCause());
+ } catch (CancellationException cancellation) {
+ valueToSet = new Cancellation(false, cancellation);
+ } catch (Throwable t) {
+ valueToSet = new Failure(t);
+ }
+ }
+ // The only way this can fail is if we raced with another thread calling cancel(). If we lost
+ // that race then there is nothing to do.
+ if (ATOMIC_HELPER.casValue(AbstractFuture.this, expected, valueToSet)) {
+ complete();
+ return true;
+ }
+ return false;
+ }
- private static final long serialVersionUID = 0L;
+ /** Unblocks all threads and runs all listeners. */
+ private void complete() {
+ for (Waiter currentWaiter = clearWaiters();
+ currentWaiter != null;
+ currentWaiter = currentWaiter.next) {
+ currentWaiter.unpark();
+ }
+ // We need to reverse the list to handle buggy listeners that depend on ordering.
+ Listener currentListener = clearListeners();
+ Listener reversedList = null;
+ while (currentListener != null) {
+ Listener tmp = currentListener;
+ currentListener = currentListener.next;
+ tmp.next = reversedList;
+ reversedList = tmp;
+ }
+ for (; reversedList != null; reversedList = reversedList.next) {
+ executeListener(reversedList.task, reversedList.executor);
+ }
+ // We call this after the listeners on the theory that done() will only be used for 'cleanup'
+ // oriented tasks (e.g. clearing fields) and so can wait behind listeners which may be executing
+ // more important work. A counter argument would be that done() is trusted code and therefore
+ // it would be safe to run before potentially slow or poorly behaved listeners. Reevaluate this
+ // once we have more examples of done() implementations.
+ done();
+ }
- /* Valid states. */
- static final int RUNNING = 0;
- static final int COMPLETING = 1;
- static final int COMPLETED = 2;
- static final int CANCELLED = 4;
- static final int INTERRUPTED = 8;
+ /**
+ * Callback method that is called immediately after the future is completed.
+ *
+ * <p>This is called exactly once, after all listeners have executed. By default it does nothing.
+ */
+ void done() {}
- private V value;
- private Throwable exception;
+ /**
+ * Returns the exception that this {@code Future} completed with. This includes completion through
+ * a call to {@link setException} or {@link setFuture}{@code (failedFuture)} but not cancellation.
+ *
+ * @throws RuntimeException if the {@code Future} has not failed
+ */
+ final Throwable trustedGetException() {
+ return ((Failure) value).exception;
+ }
- /*
- * Acquisition succeeds if the future is done, otherwise it fails.
- */
- @Override
- protected int tryAcquireShared(int ignored) {
- if (isDone()) {
- return 1;
+ /**
+ * If this future has been cancelled (and possibly interrupted), cancels (and possibly interrupts)
+ * the given future (if available).
+ *
+ * <p>This method should be used only when this future is completed. It is designed to be called
+ * from {@code done}.
+ */
+ final void maybePropagateCancellation(@Nullable Future<?> related) {
+ if (related != null & isCancelled()) {
+ related.cancel(wasInterrupted());
+ }
+ }
+
+ /** Clears the {@link #waiters} list and returns the most recently added value. */
+ private Waiter clearWaiters() {
+ Waiter head;
+ do {
+ head = waiters;
+ } while (!ATOMIC_HELPER.casWaiters(this, head, Waiter.TOMBSTONE));
+ return head;
+ }
+
+ /** Clears the {@link #listeners} list and returns the most recently added value. */
+ private Listener clearListeners() {
+ Listener head;
+ do {
+ head = listeners;
+ } while (!ATOMIC_HELPER.casListeners(this, head, Listener.TOMBSTONE));
+ return head;
+ }
+
+ /**
+ * Submits the given runnable to the given {@link Executor} catching and logging all
+ * {@linkplain RuntimeException runtime exceptions} thrown by the executor.
+ */
+ private static void executeListener(Runnable runnable, Executor executor) {
+ try {
+ executor.execute(runnable);
+ } catch (RuntimeException e) {
+ // Log it and keep going, bad runnable and/or executor. Don't
+ // punish the other runnables if we're given a bad one. We only
+ // catch RuntimeException because we want Errors to propagate up.
+ log.log(Level.SEVERE, "RuntimeException while executing runnable "
+ + runnable + " with executor " + executor, e);
+ }
+ }
+
+ static final CancellationException cancellationExceptionWithCause(
+ @Nullable String message, @Nullable Throwable cause) {
+ CancellationException exception = new CancellationException(message);
+ exception.initCause(cause);
+ return exception;
+ }
+
+ private abstract static class AtomicHelper {
+ /** Non volatile write of the thread to the {@link Waiter#thread} field. */
+ abstract void putThread(Waiter waiter, Thread newValue);
+
+ /** Non volatile write of the waiter to the {@link Waiter#next} field. */
+ abstract void putNext(Waiter waiter, Waiter newValue);
+
+ /** Performs a CAS operation on the {@link #waiters} field. */
+ abstract boolean casWaiters(AbstractFuture<?> future, Waiter expect, Waiter update);
+
+ /** Performs a CAS operation on the {@link #listeners} field. */
+ abstract boolean casListeners(AbstractFuture<?> future, Listener expect, Listener update);
+
+ /** Performs a CAS operation on the {@link #value} field. */
+ abstract boolean casValue(AbstractFuture<?> future, Object expect, Object update);
+ }
+
+ /**
+ * {@link AtomicHelper} based on {@link sun.misc.Unsafe}.
+ *
+ * <p>Static initialization of this class will fail if the {@link sun.misc.Unsafe} object cannot
+ * be accessed.
+ */
+ private static final class UnsafeAtomicHelper extends AtomicHelper {
+ static final sun.misc.Unsafe UNSAFE;
+ static final long LISTENERS_OFFSET;
+ static final long WAITERS_OFFSET;
+ static final long VALUE_OFFSET;
+ static final long WAITER_THREAD_OFFSET;
+ static final long WAITER_NEXT_OFFSET;
+
+ static {
+ sun.misc.Unsafe unsafe = null;
+ try {
+ unsafe = sun.misc.Unsafe.getUnsafe();
+ } catch (SecurityException tryReflectionInstead) {
+ try {
+ unsafe = AccessController.doPrivileged(
+ new PrivilegedExceptionAction<sun.misc.Unsafe>() {
+ @Override public sun.misc.Unsafe run() throws Exception {
+ Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+ for (java.lang.reflect.Field f : k.getDeclaredFields()) {
+ f.setAccessible(true);
+ Object x = f.get(null);
+ if (k.isInstance(x)) {
+ return k.cast(x);
+ }
+ }
+ throw new NoSuchFieldError("the Unsafe");
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw new RuntimeException("Could not initialize intrinsics", e.getCause());
+ }
+ }
+ try {
+ Class<?> abstractFuture = AbstractFuture.class;
+ WAITERS_OFFSET = unsafe.objectFieldOffset(abstractFuture.getDeclaredField("waiters"));
+ LISTENERS_OFFSET = unsafe.objectFieldOffset(abstractFuture.getDeclaredField("listeners"));
+ VALUE_OFFSET = unsafe.objectFieldOffset(abstractFuture.getDeclaredField("value"));
+ WAITER_THREAD_OFFSET = unsafe.objectFieldOffset(Waiter.class.getDeclaredField("thread"));
+ WAITER_NEXT_OFFSET = unsafe.objectFieldOffset(Waiter.class.getDeclaredField("next"));
+ UNSAFE = unsafe;
+ } catch (Exception e) {
+ throw Throwables.propagate(e);
}
- return -1;
}
- /*
- * We always allow a release to go through, this means the state has been
- * successfully changed and the result is available.
- */
@Override
- protected boolean tryReleaseShared(int finalState) {
- setState(finalState);
- return true;
+ void putThread(Waiter waiter, Thread newValue) {
+ UNSAFE.putObject(waiter, WAITER_THREAD_OFFSET, newValue);
}
- /**
- * Blocks until the task is complete or the timeout expires. Throws a
- * {@link TimeoutException} if the timer expires, otherwise behaves like
- * {@link #get()}.
- */
- V get(long nanos) throws TimeoutException, CancellationException,
- ExecutionException, InterruptedException {
+ @Override
+ void putNext(Waiter waiter, Waiter newValue) {
+ UNSAFE.putObject(waiter, WAITER_NEXT_OFFSET, newValue);
+ }
- // Attempt to acquire the shared lock with a timeout.
- if (!tryAcquireSharedNanos(-1, nanos)) {
- throw new TimeoutException("Timeout waiting for task.");
- }
+ /** Performs a CAS operation on the {@link #waiters} field. */
+ @Override
+ boolean casWaiters(AbstractFuture<?> future, Waiter expect, Waiter update) {
+ return UNSAFE.compareAndSwapObject(future, WAITERS_OFFSET, expect, update);
+ }
- return getValue();
- }
-
- /**
- * Blocks until {@link #complete(Object, Throwable, int)} has been
- * successfully called. Throws a {@link CancellationException} if the task
- * was cancelled, or a {@link ExecutionException} if the task completed with
- * an error.
- */
- V get() throws CancellationException, ExecutionException,
- InterruptedException {
-
- // Acquire the shared lock allowing interruption.
- acquireSharedInterruptibly(-1);
- return getValue();
- }
-
- /**
- * Implementation of the actual value retrieval. Will return the value
- * on success, an exception on failure, a cancellation on cancellation, or
- * an illegal state if the synchronizer is in an invalid state.
- */
- private V getValue() throws CancellationException, ExecutionException {
- int state = getState();
- switch (state) {
- case COMPLETED:
- if (exception != null) {
- throw new ExecutionException(exception);
- } else {
- return value;
- }
+ /** Performs a CAS operation on the {@link #listeners} field. */
+ @Override
+ boolean casListeners(AbstractFuture<?> future, Listener expect, Listener update) {
+ return UNSAFE.compareAndSwapObject(future, LISTENERS_OFFSET, expect, update);
+ }
+
+ /** Performs a CAS operation on the {@link #value} field. */
+ @Override
+ boolean casValue(AbstractFuture<?> future, Object expect, Object update) {
+ return UNSAFE.compareAndSwapObject(future, VALUE_OFFSET, expect, update);
+ }
+ }
+
+ /** {@link AtomicHelper} based on {@link AtomicReferenceFieldUpdater}. */
+ private static final class SafeAtomicHelper extends AtomicHelper {
+ final AtomicReferenceFieldUpdater<Waiter, Thread> waiterThreadUpdater;
+ final AtomicReferenceFieldUpdater<Waiter, Waiter> waiterNextUpdater;
+ final AtomicReferenceFieldUpdater<AbstractFuture, Waiter> waitersUpdater;
+ final AtomicReferenceFieldUpdater<AbstractFuture, Listener> listenersUpdater;
+ final AtomicReferenceFieldUpdater<AbstractFuture, Object> valueUpdater;
+
+ SafeAtomicHelper(
+ AtomicReferenceFieldUpdater<Waiter, Thread> waiterThreadUpdater,
+ AtomicReferenceFieldUpdater<Waiter, Waiter> waiterNextUpdater,
+ AtomicReferenceFieldUpdater<AbstractFuture, Waiter> waitersUpdater,
+ AtomicReferenceFieldUpdater<AbstractFuture, Listener> listenersUpdater,
+ AtomicReferenceFieldUpdater<AbstractFuture, Object> valueUpdater) {
+ this.waiterThreadUpdater = waiterThreadUpdater;
+ this.waiterNextUpdater = waiterNextUpdater;
+ this.waitersUpdater = waitersUpdater;
+ this.listenersUpdater = listenersUpdater;
+ this.valueUpdater = valueUpdater;
+ }
+
+ @Override
+ void putThread(Waiter waiter, Thread newValue) {
+ waiterThreadUpdater.lazySet(waiter, newValue);
+ }
+
+ @Override
+ void putNext(Waiter waiter, Waiter newValue) {
+ waiterNextUpdater.lazySet(waiter, newValue);
+ }
+
+ @Override
+ boolean casWaiters(AbstractFuture<?> future, Waiter expect, Waiter update) {
+ return waitersUpdater.compareAndSet(future, expect, update);
+ }
+
+ @Override
+ boolean casListeners(AbstractFuture<?> future, Listener expect, Listener update) {
+ return listenersUpdater.compareAndSet(future, expect, update);
+ }
+
+ @Override
+ boolean casValue(AbstractFuture<?> future, Object expect, Object update) {
+ return valueUpdater.compareAndSet(future, expect, update);
+ }
+ }
+
+ /**
+ * {@link AtomicHelper} based on {@code synchronized} and volatile writes.
+ *
+ * <p>This is an implementation of last resort for when certain basic VM features are broken
+ * (like AtomicReferenceFieldUpdater).
+ */
+ private static final class SynchronizedHelper extends AtomicHelper {
+ @Override
+ void putThread(Waiter waiter, Thread newValue) {
+ waiter.thread = newValue;
+ }
- case CANCELLED:
- case INTERRUPTED:
- throw cancellationExceptionWithCause(
- "Task was cancelled.", exception);
+ @Override
+ void putNext(Waiter waiter, Waiter newValue) {
+ waiter.next = newValue;
+ }
- default:
- throw new IllegalStateException(
- "Error, synchronizer in invalid state: " + state);
+ @Override
+ boolean casWaiters(AbstractFuture<?> future, Waiter expect, Waiter update) {
+ synchronized (future) {
+ if (future.waiters == expect) {
+ future.waiters = update;
+ return true;
+ }
+ return false;
}
}
- /**
- * Checks if the state is {@link #COMPLETED}, {@link #CANCELLED}, or {@link
- * INTERRUPTED}.
- */
- boolean isDone() {
- return (getState() & (COMPLETED | CANCELLED | INTERRUPTED)) != 0;
- }
-
- /**
- * Checks if the state is {@link #CANCELLED} or {@link #INTERRUPTED}.
- */
- boolean isCancelled() {
- return (getState() & (CANCELLED | INTERRUPTED)) != 0;
- }
-
- /**
- * Checks if the state is {@link #INTERRUPTED}.
- */
- boolean wasInterrupted() {
- return getState() == INTERRUPTED;
- }
-
- /**
- * Transition to the COMPLETED state and set the value.
- */
- boolean set(@Nullable V v) {
- return complete(v, null, COMPLETED);
- }
-
- /**
- * Transition to the COMPLETED state and set the exception.
- */
- boolean setException(Throwable t) {
- return complete(null, t, COMPLETED);
- }
-
- /**
- * Transition to the CANCELLED or INTERRUPTED state.
- */
- boolean cancel(boolean interrupt) {
- return complete(null, null, interrupt ? INTERRUPTED : CANCELLED);
- }
-
- /**
- * Implementation of completing a task. Either {@code v} or {@code t} will
- * be set but not both. The {@code finalState} is the state to change to
- * from {@link #RUNNING}. If the state is not in the RUNNING state we
- * return {@code false} after waiting for the state to be set to a valid
- * final state ({@link #COMPLETED}, {@link #CANCELLED}, or {@link
- * #INTERRUPTED}).
- *
- * @param v the value to set as the result of the computation.
- * @param t the exception to set as the result of the computation.
- * @param finalState the state to transition to.
- */
- private boolean complete(@Nullable V v, @Nullable Throwable t,
- int finalState) {
- boolean doCompletion = compareAndSetState(RUNNING, COMPLETING);
- if (doCompletion) {
- // If this thread successfully transitioned to COMPLETING, set the value
- // and exception and then release to the final state.
- this.value = v;
- // Don't actually construct a CancellationException until necessary.
- this.exception = ((finalState & (CANCELLED | INTERRUPTED)) != 0)
- ? new CancellationException("Future.cancel() was called.") : t;
- releaseShared(finalState);
- } else if (getState() == COMPLETING) {
- // If some other thread is currently completing the future, block until
- // they are done so we can guarantee completion.
- acquireShared(-1);
+ @Override
+ boolean casListeners(AbstractFuture<?> future, Listener expect, Listener update) {
+ synchronized (future) {
+ if (future.listeners == expect) {
+ future.listeners = update;
+ return true;
+ }
+ return false;
}
- return doCompletion;
}
- }
- static final CancellationException cancellationExceptionWithCause(
- @Nullable String message, @Nullable Throwable cause) {
- CancellationException exception = new CancellationException(message);
- exception.initCause(cause);
- return exception;
+ @Override
+ boolean casValue(AbstractFuture<?> future, Object expect, Object update) {
+ synchronized (future) {
+ if (future.value == expect) {
+ future.value = update;
+ return true;
+ }
+ return false;
+ }
+ }
}
}
diff --git a/guava/src/com/google/common/util/concurrent/AbstractIdleService.java b/guava/src/com/google/common/util/concurrent/AbstractIdleService.java
index 23a56e1..9b2d1a2 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractIdleService.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractIdleService.java
@@ -18,7 +18,7 @@ package com.google.common.util.concurrent;
import com.google.common.annotations.Beta;
import com.google.common.base.Supplier;
-import com.google.common.base.Throwables;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -38,14 +38,20 @@ import java.util.concurrent.TimeoutException;
public abstract class AbstractIdleService implements Service {
/* Thread names will look like {@code "MyService STARTING"}. */
- private final Supplier<String> threadNameSupplier = new Supplier<String>() {
+ private final Supplier<String> threadNameSupplier = new ThreadNameSupplier();
+
+ @WeakOuter
+ private final class ThreadNameSupplier implements Supplier<String> {
@Override public String get() {
return serviceName() + " " + state();
}
- };
+ }
/* use AbstractService for state management */
- private final Service delegate = new AbstractService() {
+ private final Service delegate = new DelegateService();
+
+ @WeakOuter
+ private final class DelegateService extends AbstractService {
@Override protected final void doStart() {
MoreExecutors.renamingDecorator(executor(), threadNameSupplier)
.execute(new Runnable() {
@@ -55,7 +61,6 @@ public abstract class AbstractIdleService implements Service {
notifyStarted();
} catch (Throwable t) {
notifyFailed(t);
- throw Throwables.propagate(t);
}
}
});
@@ -70,12 +75,15 @@ public abstract class AbstractIdleService implements Service {
notifyStopped();
} catch (Throwable t) {
notifyFailed(t);
- throw Throwables.propagate(t);
}
}
});
}
- };
+
+ @Override public String toString() {
+ return AbstractIdleService.this.toString();
+ }
+ }
/** Constructor for use by subclasses. */
protected AbstractIdleService() {}
diff --git a/guava/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java b/guava/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java
index 1208153..a1c4f3b 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java
@@ -20,13 +20,14 @@ import com.google.common.annotations.Beta;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.Callable;
+import java.util.concurrent.RunnableFuture;
import javax.annotation.Nullable;
/**
- * Abstract {@link ListeningExecutorService} implementation that creates
- * {@link ListenableFutureTask} instances for each {@link Runnable} and {@link Callable} submitted
- * to it. These tasks are run with the abstract {@link #execute execute(Runnable)} method.
+ * Abstract {@link ListeningExecutorService} implementation that creates {@link ListenableFuture}
+ * instances for each {@link Runnable} and {@link Callable} submitted to it. These tasks are run
+ * with the abstract {@link #execute execute(Runnable)} method.
*
* <p>In addition to {@link #execute}, subclasses must implement all methods related to shutdown and
* termination.
@@ -38,12 +39,14 @@ import javax.annotation.Nullable;
public abstract class AbstractListeningExecutorService
extends AbstractExecutorService implements ListeningExecutorService {
- @Override protected final <T> ListenableFutureTask<T> newTaskFor(Runnable runnable, T value) {
- return ListenableFutureTask.create(runnable, value);
+ /** @since 19.0 (present with return type {@code ListenableFutureTask} since 14.0) */
+ @Override protected final <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
+ return TrustedListenableFutureTask.create(runnable, value);
}
- @Override protected final <T> ListenableFutureTask<T> newTaskFor(Callable<T> callable) {
- return ListenableFutureTask.create(callable);
+ /** @since 19.0 (present with return type {@code ListenableFutureTask} since 14.0) */
+ @Override protected final <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
+ return TrustedListenableFutureTask.create(callable);
}
@Override public ListenableFuture<?> submit(Runnable task) {
diff --git a/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java b/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java
index b45440e..70a5fac 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java
@@ -16,12 +16,13 @@
package com.google.common.util.concurrent;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
-import com.google.common.base.Throwables;
+import com.google.j2objc.annotations.WeakOuter;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
@@ -120,6 +121,8 @@ public abstract class AbstractScheduledService implements Service {
*/
public static Scheduler newFixedDelaySchedule(final long initialDelay, final long delay,
final TimeUnit unit) {
+ checkNotNull(unit);
+ checkArgument(delay > 0, "delay must be > 0, found %s", delay);
return new Scheduler() {
@Override
public Future<?> schedule(AbstractService service, ScheduledExecutorService executor,
@@ -139,6 +142,8 @@ public abstract class AbstractScheduledService implements Service {
*/
public static Scheduler newFixedRateSchedule(final long initialDelay, final long period,
final TimeUnit unit) {
+ checkNotNull(unit);
+ checkArgument(period > 0, "period must be > 0, found %s", period);
return new Scheduler() {
@Override
public Future<?> schedule(AbstractService service, ScheduledExecutorService executor,
@@ -156,7 +161,10 @@ public abstract class AbstractScheduledService implements Service {
}
/* use AbstractService for state management */
- private final AbstractService delegate = new AbstractService() {
+ private final AbstractService delegate = new ServiceDelegate();
+
+ @WeakOuter
+ private final class ServiceDelegate extends AbstractService {
// A handle to the running task so that we can stop it when a shutdown has been requested.
// These two fields are volatile because their values will be accessed from multiple threads.
@@ -165,28 +173,37 @@ public abstract class AbstractScheduledService implements Service {
// This lock protects the task so we can ensure that none of the template methods (startUp,
// shutDown or runOneIteration) run concurrently with one another.
+ // TODO(lukes): why don't we use ListenableFuture to sequence things? Then we could drop the
+ // lock.
private final ReentrantLock lock = new ReentrantLock();
-
- private final Runnable task = new Runnable() {
+
+ @WeakOuter
+ class Task implements Runnable {
@Override public void run() {
lock.lock();
try {
+ if (runningTask.isCancelled()) {
+ // task may have been cancelled while blocked on the lock.
+ return;
+ }
AbstractScheduledService.this.runOneIteration();
} catch (Throwable t) {
try {
shutDown();
} catch (Exception ignored) {
- logger.log(Level.WARNING,
+ logger.log(Level.WARNING,
"Error while attempting to shut down the service after failure.", ignored);
}
notifyFailed(t);
- throw Throwables.propagate(t);
+ runningTask.cancel(false); // prevent future invocations.
} finally {
lock.unlock();
}
}
- };
-
+ }
+
+ private final Runnable task = new Task();
+
@Override protected final void doStart() {
executorService = MoreExecutors.renamingDecorator(executor(), new Supplier<String>() {
@Override public String get() {
@@ -202,7 +219,10 @@ public abstract class AbstractScheduledService implements Service {
notifyStarted();
} catch (Throwable t) {
notifyFailed(t);
- throw Throwables.propagate(t);
+ if (runningTask != null) {
+ // prevent the task from running if possible
+ runningTask.cancel(false);
+ }
} finally {
lock.unlock();
}
@@ -211,7 +231,7 @@ public abstract class AbstractScheduledService implements Service {
}
@Override protected final void doStop() {
- runningTask.cancel(false);
+ runningTask.cancel(false);
executorService.execute(new Runnable() {
@Override public void run() {
try {
@@ -231,13 +251,16 @@ public abstract class AbstractScheduledService implements Service {
notifyStopped();
} catch (Throwable t) {
notifyFailed(t);
- throw Throwables.propagate(t);
}
}
});
}
- };
-
+
+ @Override public String toString() {
+ return AbstractScheduledService.this.toString();
+ }
+ }
+
/** Constructor for use by subclasses. */
protected AbstractScheduledService() {}
@@ -284,12 +307,13 @@ public abstract class AbstractScheduledService implements Service {
* {@linkplain Service.State#TERMINATED fails}.
*/
protected ScheduledExecutorService executor() {
- final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(
- new ThreadFactory() {
- @Override public Thread newThread(Runnable runnable) {
- return MoreExecutors.newThread(serviceName(), runnable);
- }
- });
+ @WeakOuter class ThreadFactoryImpl implements ThreadFactory {
+ @Override public Thread newThread(Runnable runnable) {
+ return MoreExecutors.newThread(serviceName(), runnable);
+ }
+ }
+ final ScheduledExecutorService executor =
+ Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl());
// Add a listener to shutdown the executor after the service is stopped. This ensures that the
// JVM shutdown will not be prevented from exiting after this service has stopped or failed.
// Technically this listener is added after start() was called so it is a little gross, but it
@@ -443,14 +467,22 @@ public abstract class AbstractScheduledService implements Service {
* Atomically reschedules this task and assigns the new future to {@link #currentFuture}.
*/
public void reschedule() {
+ // invoke the callback outside the lock, prevents some shenanigans.
+ Schedule schedule;
+ try {
+ schedule = CustomScheduler.this.getNextSchedule();
+ } catch (Throwable t) {
+ service.notifyFailed(t);
+ return;
+ }
// We reschedule ourselves with a lock held for two reasons. 1. we want to make sure that
// cancel calls cancel on the correct future. 2. we want to make sure that the assignment
// to currentFuture doesn't race with itself so that currentFuture is assigned in the
// correct order.
+ Throwable scheduleFailure = null;
lock.lock();
try {
if (currentFuture == null || !currentFuture.isCancelled()) {
- final Schedule schedule = CustomScheduler.this.getNextSchedule();
currentFuture = executor.schedule(this, schedule.delay, schedule.unit);
}
} catch (Throwable e) {
@@ -459,10 +491,17 @@ public abstract class AbstractScheduledService implements Service {
// because the service does not monitor the state of the future so if the exception is not
// caught and forwarded to the service the task would stop executing but the service would
// have no idea.
- service.notifyFailed(e);
+ // TODO(lukes): consider building everything in terms of ListenableScheduledFuture then
+ // the AbstractService could monitor the future directly. Rescheduling is still hard...
+ // but it would help with some of these lock ordering issues.
+ scheduleFailure = e;
} finally {
lock.unlock();
}
+ // Call notifyFailed outside the lock to avoid lock ordering issues.
+ if (scheduleFailure != null) {
+ service.notifyFailed(scheduleFailure);
+ }
}
// N.B. Only protect cancel and isCancelled because those are the only methods that are
@@ -478,9 +517,20 @@ public abstract class AbstractScheduledService implements Service {
}
}
+ @Override
+ public boolean isCancelled() {
+ lock.lock();
+ try {
+ return currentFuture.isCancelled();
+ } finally {
+ lock.unlock();
+ }
+ }
+
@Override
protected Future<Void> delegate() {
- throw new UnsupportedOperationException("Only cancel is supported by this future");
+ throw new UnsupportedOperationException(
+ "Only cancel and isCancelled is supported by this future");
}
}
@@ -510,7 +560,7 @@ public abstract class AbstractScheduledService implements Service {
*/
public Schedule(long delay, TimeUnit unit) {
this.delay = delay;
- this.unit = Preconditions.checkNotNull(unit);
+ this.unit = checkNotNull(unit);
}
}
diff --git a/guava/src/com/google/common/util/concurrent/AbstractService.java b/guava/src/com/google/common/util/concurrent/AbstractService.java
index 0e996ed..fa5f0b2 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractService.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractService.java
@@ -30,6 +30,7 @@ import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.ListenerCallQueue.Callback;
import com.google.common.util.concurrent.Monitor.Guard;
import com.google.common.util.concurrent.Service.State; // javadoc needs this
+import com.google.j2objc.annotations.WeakOuter;
import java.util.ArrayList;
import java.util.Collections;
@@ -54,28 +55,28 @@ import javax.annotation.concurrent.Immutable;
*/
@Beta
public abstract class AbstractService implements Service {
- private static final Callback<Listener> STARTING_CALLBACK =
+ private static final Callback<Listener> STARTING_CALLBACK =
new Callback<Listener>("starting()") {
@Override void call(Listener listener) {
listener.starting();
}
};
- private static final Callback<Listener> RUNNING_CALLBACK =
+ private static final Callback<Listener> RUNNING_CALLBACK =
new Callback<Listener>("running()") {
@Override void call(Listener listener) {
listener.running();
}
};
- private static final Callback<Listener> STOPPING_FROM_STARTING_CALLBACK =
+ private static final Callback<Listener> STOPPING_FROM_STARTING_CALLBACK =
stoppingCallback(STARTING);
- private static final Callback<Listener> STOPPING_FROM_RUNNING_CALLBACK =
+ private static final Callback<Listener> STOPPING_FROM_RUNNING_CALLBACK =
stoppingCallback(RUNNING);
-
- private static final Callback<Listener> TERMINATED_FROM_NEW_CALLBACK =
+
+ private static final Callback<Listener> TERMINATED_FROM_NEW_CALLBACK =
terminatedCallback(NEW);
- private static final Callback<Listener> TERMINATED_FROM_RUNNING_CALLBACK =
+ private static final Callback<Listener> TERMINATED_FROM_RUNNING_CALLBACK =
terminatedCallback(RUNNING);
- private static final Callback<Listener> TERMINATED_FROM_STOPPING_CALLBACK =
+ private static final Callback<Listener> TERMINATED_FROM_STOPPING_CALLBACK =
terminatedCallback(STOPPING);
private static Callback<Listener> terminatedCallback(final State from) {
@@ -85,7 +86,7 @@ public abstract class AbstractService implements Service {
}
};
}
-
+
private static Callback<Listener> stoppingCallback(final State from) {
return new Callback<Listener>("stopping({from = " + from + "})") {
@Override void call(Listener listener) {
@@ -93,47 +94,75 @@ public abstract class AbstractService implements Service {
}
};
}
-
+
private final Monitor monitor = new Monitor();
- private final Guard isStartable = new Guard(monitor) {
+ private final Guard isStartable = new IsStartableGuard();
+
+ @WeakOuter
+ private final class IsStartableGuard extends Guard {
+ IsStartableGuard() {
+ super(AbstractService.this.monitor);
+ }
+
@Override public boolean isSatisfied() {
return state() == NEW;
}
- };
+ }
+
+ private final Guard isStoppable = new IsStoppableGuard();
+
+ @WeakOuter
+ private final class IsStoppableGuard extends Guard {
+ IsStoppableGuard() {
+ super(AbstractService.this.monitor);
+ }
- private final Guard isStoppable = new Guard(monitor) {
@Override public boolean isSatisfied() {
return state().compareTo(RUNNING) <= 0;
}
- };
+ }
+
+ private final Guard hasReachedRunning = new HasReachedRunningGuard();
+
+ @WeakOuter
+ private final class HasReachedRunningGuard extends Guard {
+ HasReachedRunningGuard() {
+ super(AbstractService.this.monitor);
+ }
- private final Guard hasReachedRunning = new Guard(monitor) {
@Override public boolean isSatisfied() {
return state().compareTo(RUNNING) >= 0;
}
- };
+ }
+
+ private final Guard isStopped = new IsStoppedGuard();
+
+ @WeakOuter
+ private final class IsStoppedGuard extends Guard {
+ IsStoppedGuard() {
+ super(AbstractService.this.monitor);
+ }
- private final Guard isStopped = new Guard(monitor) {
@Override public boolean isSatisfied() {
return state().isTerminal();
}
- };
+ }
/**
* The listeners to notify during a state transition.
*/
@GuardedBy("monitor")
- private final List<ListenerCallQueue<Listener>> listeners =
+ private final List<ListenerCallQueue<Listener>> listeners =
Collections.synchronizedList(new ArrayList<ListenerCallQueue<Listener>>());
-
+
/**
* The current state of the service. This should be written with the lock held but can be read
* without it because it is an immutable object in a volatile field. This is desirable so that
* methods like {@link #state}, {@link #failureCause} and notably {@link #toString} can be run
- * without grabbing the lock.
- *
- * <p>To update this field correctly the lock must be held to guarantee that the state is
+ * without grabbing the lock.
+ *
+ * <p>To update this field correctly the lock must be held to guarantee that the state is
* consistent.
*/
@GuardedBy("monitor")
@@ -141,15 +170,15 @@ public abstract class AbstractService implements Service {
/** Constructor for use by subclasses. */
protected AbstractService() {}
-
+
/**
- * This method is called by {@link #startAsync} to initiate service startup. The invocation of
+ * This method is called by {@link #startAsync} to initiate service startup. The invocation of
* this method should cause a call to {@link #notifyStarted()}, either during this method's run,
* or after it has returned. If startup fails, the invocation should cause a call to
* {@link #notifyFailed(Throwable)} instead.
*
* <p>This method should return promptly; prefer to do work on a different thread where it is
- * convenient. It is invoked exactly once on service startup, even when {@link #startAsync} is
+ * convenient. It is invoked exactly once on service startup, even when {@link #startAsync} is
* called multiple times.
*/
protected abstract void doStart();
@@ -161,7 +190,7 @@ public abstract class AbstractService implements Service {
* {@link #notifyFailed(Throwable)} instead.
*
* <p> This method should return promptly; prefer to do work on a different thread where it is
- * convenient. It is invoked exactly once on service shutdown, even when {@link #stopAsync} is
+ * convenient. It is invoked exactly once on service shutdown, even when {@link #stopAsync} is
* called multiple times.
*/
protected abstract void doStop();
@@ -172,7 +201,6 @@ public abstract class AbstractService implements Service {
snapshot = new StateSnapshot(STARTING);
starting();
doStart();
- // TODO(user): justify why we are catching Throwable and not RuntimeException
} catch (Throwable startupFailure) {
notifyFailed(startupFailure);
} finally {
@@ -211,8 +239,6 @@ public abstract class AbstractService implements Service {
default:
throw new AssertionError("Unexpected state: " + previous);
}
- // TODO(user): justify why we are catching Throwable and not RuntimeException. Also, we
- // may inadvertently catch our AssertionErrors.
} catch (Throwable shutdownFailure) {
notifyFailed(shutdownFailure);
} finally {
@@ -231,7 +257,7 @@ public abstract class AbstractService implements Service {
monitor.leave();
}
}
-
+
@Override public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException {
if (monitor.enterWhenUninterruptibly(hasReachedRunning, timeout, unit)) {
try {
@@ -240,12 +266,11 @@ public abstract class AbstractService implements Service {
monitor.leave();
}
} else {
- // It is possible due to races the we are currently in the expected state even though we
+ // It is possible due to races the we are currently in the expected state even though we
// timed out. e.g. if we weren't event able to grab the lock within the timeout we would never
// even check the guard. I don't think we care too much about this use case but it could lead
// to a confusing error message.
- throw new TimeoutException("Timed out waiting for " + this + " to reach the RUNNING state. "
- + "Current state: " + state());
+ throw new TimeoutException("Timed out waiting for " + this + " to reach the RUNNING state.");
}
}
@@ -257,7 +282,7 @@ public abstract class AbstractService implements Service {
monitor.leave();
}
}
-
+
@Override public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException {
if (monitor.enterWhenUninterruptibly(isStopped, timeout, unit)) {
try {
@@ -266,7 +291,7 @@ public abstract class AbstractService implements Service {
monitor.leave();
}
} else {
- // It is possible due to races the we are currently in the expected state even though we
+ // It is possible due to races the we are currently in the expected state even though we
// timed out. e.g. if we weren't event able to grab the lock within the timeout we would never
// even check the guard. I don't think we care too much about this use case but it could lead
// to a confusing error message.
@@ -274,7 +299,7 @@ public abstract class AbstractService implements Service {
+ "Current state: " + state());
}
}
-
+
/** Checks that the current state is equal to the expected state. */
@GuardedBy("monitor")
private void checkCurrentState(State expected) {
@@ -282,10 +307,10 @@ public abstract class AbstractService implements Service {
if (actual != expected) {
if (actual == FAILED) {
// Handle this specially so that we can include the failureCause, if there is one.
- throw new IllegalStateException("Expected the service to be " + expected
+ throw new IllegalStateException("Expected the service to be " + expected
+ ", but the service has FAILED", failureCause());
}
- throw new IllegalStateException("Expected the service to be " + expected + ", but was "
+ throw new IllegalStateException("Expected the service to be " + expected + ", but was "
+ actual);
}
}
@@ -299,7 +324,7 @@ public abstract class AbstractService implements Service {
protected final void notifyStarted() {
monitor.enter();
try {
- // We have to examine the internal state of the snapshot here to properly handle the stop
+ // We have to examine the internal state of the snapshot here to properly handle the stop
// while starting case.
if (snapshot.state != STARTING) {
IllegalStateException failure = new IllegalStateException(
@@ -310,7 +335,7 @@ public abstract class AbstractService implements Service {
if (snapshot.shutdownWhenStartupFinishes) {
snapshot = new StateSnapshot(STOPPING);
- // We don't call listeners here because we already did that when we set the
+ // We don't call listeners here because we already did that when we set the
// shutdownWhenStartupFinishes flag.
doStop();
} else {
@@ -392,7 +417,7 @@ public abstract class AbstractService implements Service {
public final State state() {
return snapshot.externalState();
}
-
+
/**
* @since 14.0
*/
@@ -400,7 +425,7 @@ public abstract class AbstractService implements Service {
public final Throwable failureCause() {
return snapshot.failureCause();
}
-
+
/**
* @since 13.0
*/
@@ -422,7 +447,7 @@ public abstract class AbstractService implements Service {
return getClass().getSimpleName() + " [" + state() + "]";
}
- /**
+ /**
* Attempts to execute all the listeners in {@link #listeners} while not holding the
* {@link #monitor}.
*/
@@ -485,7 +510,7 @@ public abstract class AbstractService implements Service {
}
}.enqueueOn(listeners);
}
-
+
/**
* An immutable snapshot of the current state of the service. This class represents a consistent
* snapshot of the state and therefore it can be used to answer simple queries without needing to
@@ -504,22 +529,22 @@ public abstract class AbstractService implements Service {
* up.
*/
final boolean shutdownWhenStartupFinishes;
-
+
/**
* The exception that caused this service to fail. This will be {@code null}
* unless the service has failed.
*/
@Nullable
final Throwable failure;
-
+
StateSnapshot(State internalState) {
this(internalState, false, null);
}
-
+
StateSnapshot(
State internalState, boolean shutdownWhenStartupFinishes, @Nullable Throwable failure) {
- checkArgument(!shutdownWhenStartupFinishes || internalState == STARTING,
- "shudownWhenStartupFinishes can only be set if state is STARTING. Got %s instead.",
+ checkArgument(!shutdownWhenStartupFinishes || internalState == STARTING,
+ "shudownWhenStartupFinishes can only be set if state is STARTING. Got %s instead.",
internalState);
checkArgument(!(failure != null ^ internalState == FAILED),
"A failure cause should be set if and only if the state is failed. Got %s and %s "
@@ -528,7 +553,7 @@ public abstract class AbstractService implements Service {
this.shutdownWhenStartupFinishes = shutdownWhenStartupFinishes;
this.failure = failure;
}
-
+
/** @see Service#state() */
State externalState() {
if (shutdownWhenStartupFinishes && state == STARTING) {
@@ -537,10 +562,10 @@ public abstract class AbstractService implements Service {
return state;
}
}
-
+
/** @see Service#failureCause() */
Throwable failureCause() {
- checkState(state == FAILED,
+ checkState(state == FAILED,
"failureCause() is only valid if the service has failed, service is %s", state);
return failure;
}
diff --git a/guava/src/com/google/common/util/concurrent/AggregateFuture.java b/guava/src/com/google/common/util/concurrent/AggregateFuture.java
new file mode 100644
index 0000000..28d5dca
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AggregateFuture.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2006 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
+import com.google.common.collect.ImmutableCollection;
+import com.google.j2objc.annotations.WeakOuter;
+
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.Nullable;
+
+/**
+ * A future made up of a collection of sub-futures.
+ *
+ * @param <InputT> the type of the individual inputs
+ * @param <OutputT> the type of the output (i.e. this) future
+ */
+ at GwtCompatible
+abstract class AggregateFuture<InputT, OutputT> extends AbstractFuture.TrustedFuture<OutputT> {
+ private static final Logger logger =
+ Logger.getLogger(AggregateFuture.class.getName());
+
+ private RunningState runningState;
+
+ @Override final void done() {
+ super.done();
+
+ // Let go of the memory held by the running state
+ this.runningState = null;
+ }
+
+ // TODO(cpovirk): Use maybePropagateCancellation() if the performance is OK and the code is clean.
+ @Override public final boolean cancel(boolean mayInterruptIfRunning) {
+ // Must get a reference to the futures before we cancel, as they'll be cleared out.
+ RunningState localRunningState = runningState;
+ ImmutableCollection<? extends ListenableFuture<? extends InputT>> futures =
+ (localRunningState != null) ? localRunningState.futures : null;
+ // Cancel all the component futures.
+ boolean cancelled = super.cancel(mayInterruptIfRunning);
+ // & is faster than the branch required for &&
+ if (cancelled & futures != null) {
+ for (ListenableFuture<?> future : futures) {
+ future.cancel(mayInterruptIfRunning);
+ }
+ }
+ return cancelled;
+ }
+
+ @GwtIncompatible("Interruption not supported")
+ @Override protected final void interruptTask() {
+ RunningState localRunningState = runningState;
+ if (localRunningState != null) {
+ localRunningState.interruptTask();
+ }
+ }
+
+ /**
+ * Must be called at the end of each sub-class's constructor.
+ */
+ final void init(RunningState runningState) {
+ this.runningState = runningState;
+ runningState.init();
+ }
+
+ @WeakOuter
+ abstract class RunningState extends AggregateFutureState implements Runnable {
+ private ImmutableCollection<? extends ListenableFuture<? extends InputT>> futures;
+ private final boolean allMustSucceed;
+ private final boolean collectsValues;
+
+ RunningState(ImmutableCollection<? extends ListenableFuture<? extends InputT>> futures,
+ boolean allMustSucceed, boolean collectsValues) {
+ super(futures.size());
+ this.futures = checkNotNull(futures);
+ this.allMustSucceed = allMustSucceed;
+ this.collectsValues = collectsValues;
+ }
+
+ /* Used in the !allMustSucceed case so we don't have to instantiate a listener. */
+ @Override public final void run() {
+ decrementCountAndMaybeComplete();
+ }
+
+ /**
+ * The "real" initialization; we can't put this in the constructor because, in the case where
+ * futures are already complete, we would not initialize the subclass before calling
+ * {@link #handleOneInputDone}. As this is called after the subclass is constructed, we're
+ * guaranteed to have properly initialized the subclass.
+ */
+ private void init() {
+ // Corner case: List is empty.
+ if (futures.isEmpty()) {
+ handleAllCompleted();
+ return;
+ }
+
+ // NOTE: If we ever want to use a custom executor here, have a look at
+ // CombinedFuture as we'll need to handle RejectedExecutionException
+
+ if (allMustSucceed) {
+ // We need fail fast, so we have to keep track of which future failed so we can propagate
+ // the exception immediately
+
+ // Register a listener on each Future in the list to update
+ // the state of this future.
+ // Note that if all the futures on the list are done prior to completing
+ // this loop, the last call to addListener() will callback to
+ // setOneValue(), transitively call our cleanup listener, and set
+ // this.futures to null.
+ // This is not actually a problem, since the foreach only needs
+ // this.futures to be non-null at the beginning of the loop.
+ int i = 0;
+ for (final ListenableFuture<? extends InputT> listenable : futures) {
+ final int index = i++;
+ listenable.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ handleOneInputDone(index, listenable);
+ } finally {
+ decrementCountAndMaybeComplete();
+ }
+ }
+ }, directExecutor());
+ }
+ } else {
+ // We'll only call the callback when all futures complete, regardless of whether some failed
+ // Hold off on calling setOneValue until all complete, so we can share the same listener
+ for (ListenableFuture<? extends InputT> listenable : futures) {
+ listenable.addListener(this, directExecutor());
+ }
+ }
+ }
+
+ /**
+ * Fails this future with the given Throwable if {@link #allMustSucceed} is
+ * true. Also, logs the throwable if it is an {@link Error} or if
+ * {@link #allMustSucceed} is {@code true}, the throwable did not cause
+ * this future to fail, and it is the first time we've seen that particular Throwable.
+ */
+ private void handleException(Throwable throwable) {
+ checkNotNull(throwable);
+
+ boolean completedWithFailure = false;
+ boolean firstTimeSeeingThisException = true;
+ if (allMustSucceed) {
+ // As soon as the first one fails, throw the exception up.
+ // The result of all other inputs is then ignored.
+ completedWithFailure = setException(throwable);
+ if (completedWithFailure) {
+ releaseResourcesAfterFailure();
+ } else {
+ // Go up the causal chain to see if we've already seen this cause; if we have,
+ // even if it's wrapped by a different exception, don't log it.
+ firstTimeSeeingThisException = addCausalChain(getOrInitSeenExceptions(), throwable);
+ }
+ }
+
+ // | and & used because it's faster than the branch required for || and &&
+ if (throwable instanceof Error
+ | (allMustSucceed & !completedWithFailure & firstTimeSeeingThisException)) {
+ String message =
+ (throwable instanceof Error)
+ ? "Input Future failed with Error"
+ : "Got more than one input Future failure. Logging failures after the first";
+ logger.log(Level.SEVERE, message, throwable);
+ }
+ }
+
+ @Override
+ final void addInitialException(Set<Throwable> seen) {
+ if (!isCancelled()) {
+ addCausalChain(seen, trustedGetException());
+ }
+ }
+
+ /**
+ * Handles the input at the given index completing.
+ */
+ private void handleOneInputDone(int index, Future<? extends InputT> future) {
+ // The only cases in which this Future should already be done are (a) if
+ // it was cancelled or (b) if an input failed and we propagated that
+ // immediately because of allMustSucceed.
+ checkState(allMustSucceed || !isDone() || isCancelled(),
+ "Future was done before all dependencies completed");
+
+ try {
+ checkState(future.isDone(),
+ "Tried to set value from future which is not done");
+ if (allMustSucceed) {
+ if (future.isCancelled()) {
+ // this.cancel propagates the cancellation to children; we use super.cancel
+ // to set our own state but let the input futures keep running
+ // as some of them may be used elsewhere.
+ AggregateFuture.super.cancel(false);
+ } else {
+ // We always get the result so that we can have fail-fast, even if we don't collect
+ InputT result = getUninterruptibly(future);
+ if (collectsValues) {
+ collectOneValue(allMustSucceed, index, result);
+ }
+ }
+ } else if (collectsValues && !future.isCancelled()) {
+ collectOneValue(allMustSucceed, index, getUninterruptibly(future));
+ }
+ } catch (ExecutionException e) {
+ handleException(e.getCause());
+ } catch (Throwable t) {
+ handleException(t);
+ }
+ }
+
+ private void decrementCountAndMaybeComplete() {
+ int newRemaining = decrementRemainingAndGet();
+ checkState(newRemaining >= 0, "Less than 0 remaining futures");
+ if (newRemaining == 0) {
+ processCompleted();
+ }
+ }
+
+ private void processCompleted() {
+ // Collect the values if (a) our output requires collecting them and (b) we haven't been
+ // collecting them as we go. (We've collected them as we go only if we needed to fail fast)
+ if (collectsValues & !allMustSucceed) {
+ int i = 0;
+ for (ListenableFuture<? extends InputT> listenable : futures) {
+ handleOneInputDone(i++, listenable);
+ }
+ }
+ handleAllCompleted();
+ }
+
+ /**
+ * Listeners implicitly keep a reference to {@link RunningState} as they're inner classes,
+ * so we free resources here as well for the allMustSucceed=true case (i.e. when a future fails,
+ * we immediately release resources we no longer need); additionally, the future will release
+ * its reference to {@link RunningState}, which should free all associated memory when all the
+ * futures complete & the listeners are released.
+ *
+ * TODO(user): Write tests for memory retention
+ */
+ void releaseResourcesAfterFailure() {
+ this.futures = null;
+ }
+
+ /**
+ * Called only if {@code collectsValues} is true.
+ *
+ * <p>If {@code allMustSucceed} is true, called as each future completes; otherwise,
+ * called for each future when all futures complete.
+ */
+ abstract void collectOneValue(boolean allMustSucceed, int index, @Nullable InputT returnValue);
+
+ abstract void handleAllCompleted();
+
+ void interruptTask() {}
+ }
+
+ /** Adds the chain to the seen set, and returns whether all the chain was new to us. */
+ private static boolean addCausalChain(Set<Throwable> seen, Throwable t) {
+ for (; t != null; t = t.getCause()) {
+ boolean firstTimeSeen = seen.add(t);
+ if (!firstTimeSeen) {
+ /*
+ * We've seen this, so we've seen its causes, too. No need to re-add them. (There's one case
+ * where this isn't true, but we ignore it: If we record an exception, then someone calls
+ * initCause() on it, and then we examine it again, we'll conclude that we've seen the whole
+ * chain before when it fact we haven't. But this should be rare.)
+ */
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AggregateFutureState.java b/guava/src/com/google/common/util/concurrent/AggregateFutureState.java
new file mode 100644
index 0000000..393c74a
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AggregateFutureState.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.collect.Sets.newConcurrentHashSet;
+import static java.util.concurrent.atomic.AtomicIntegerFieldUpdater.newUpdater;
+import static java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+/**
+ * A helper which does some thread-safe operations for aggregate futures, which must be implemented
+ * differently in GWT. Namely:
+ * <p>Lazily initializes a set of seen exceptions
+ * <p>Decrements a counter atomically
+ */
+ at GwtCompatible(emulated = true)
+abstract class AggregateFutureState {
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private static final AtomicReferenceFieldUpdater<AggregateFutureState, Set<Throwable>>
+ SEEN_EXCEPTIONS_UDPATER = newUpdater(
+ AggregateFutureState.class, (Class) Set.class, "seenExceptions");
+
+ private static final AtomicIntegerFieldUpdater<AggregateFutureState>
+ REMAINING_COUNT_UPDATER = newUpdater(AggregateFutureState.class, "remaining");
+
+ // Lazily initialized the first time we see an exception; not released until all the input futures
+ // & this future completes. Released when the future releases the reference to the running state
+ private volatile Set<Throwable> seenExceptions = null;
+ @SuppressWarnings("unused") private volatile int remaining;
+
+ AggregateFutureState(int remainingFutures) {
+ this.remaining = remainingFutures;
+ }
+
+ final Set<Throwable> getOrInitSeenExceptions() {
+ /*
+ * The initialization of seenExceptions has to be more complicated than we'd like. The simple
+ * approach would be for each caller CAS it from null to a Set populated with its exception. But
+ * there's another race: If the first thread fails with an exception and a second thread
+ * immediately fails with the same exception:
+ *
+ * Thread1: calls setException(), which returns true, context switch before it can CAS
+ * seenExceptions to its exception
+ *
+ * Thread2: calls setException(), which returns false, CASes seenExceptions to its exception,
+ * and wrongly believes that its exception is new (leading it to logging it when it shouldn't)
+ *
+ * Our solution is for threads to CAS seenExceptions from null to a Set population with _the
+ * initial exception_, no matter which thread does the work. This ensures that seenExceptions
+ * always contains not just the current thread's exception but also the initial thread's.
+ */
+ Set<Throwable> seenExceptionsLocal = seenExceptions;
+ if (seenExceptionsLocal == null) {
+ seenExceptionsLocal = newConcurrentHashSet();
+ /*
+ * Other handleException() callers may see this as soon as we publish it. We need to populate
+ * it with the initial failure before we do, or else they may think that the initial failure
+ * has never been seen before.
+ */
+ addInitialException(seenExceptionsLocal);
+
+ SEEN_EXCEPTIONS_UDPATER.compareAndSet(this, null, seenExceptionsLocal);
+ /*
+ * If another handleException() caller created the set, we need to use that copy in case yet
+ * other callers have added to it.
+ *
+ * This read is guaranteed to get us the right value because we only set this once (here).
+ */
+ seenExceptionsLocal = seenExceptions;
+ }
+ return seenExceptionsLocal;
+ }
+
+ /** Populates {@code seen} with the exception that was passed to {@code setException}. */
+ abstract void addInitialException(Set<Throwable> seen);
+
+ final int decrementRemainingAndGet() {
+ return REMAINING_COUNT_UPDATER.decrementAndGet(this);
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AsyncFunction.java b/guava/src/com/google/common/util/concurrent/AsyncFunction.java
index cdb1228..c804e91 100644
--- a/guava/src/com/google/common/util/concurrent/AsyncFunction.java
+++ b/guava/src/com/google/common/util/concurrent/AsyncFunction.java
@@ -16,15 +16,21 @@
package com.google.common.util.concurrent;
+import com.google.common.annotations.GwtCompatible;
+
import java.util.concurrent.Future;
+import javax.annotation.Nullable;
+
/**
* Transforms a value, possibly asynchronously. For an example usage and more
- * information, see {@link Futures#transform(ListenableFuture, AsyncFunction)}.
+ * information, see
+ * {@link Futures#transformAsync(ListenableFuture, AsyncFunction)}.
*
* @author Chris Povirk
* @since 11.0
*/
+ at GwtCompatible
public interface AsyncFunction<I, O> {
/**
* Returns an output {@code Future} to use in place of the given {@code
@@ -34,5 +40,5 @@ public interface AsyncFunction<I, O> {
* <p>Throwing an exception from this method is equivalent to returning a
* failing {@code Future}.
*/
- ListenableFuture<O> apply(I input) throws Exception;
+ ListenableFuture<O> apply(@Nullable I input) throws Exception;
}
diff --git a/guava/src/com/google/common/util/concurrent/AsyncSettableFuture.java b/guava/src/com/google/common/util/concurrent/AsyncSettableFuture.java
deleted file mode 100644
index 469cdb9..0000000
--- a/guava/src/com/google/common/util/concurrent/AsyncSettableFuture.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2012 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.util.concurrent;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import javax.annotation.Nullable;
-
-/**
- * A settable future that can be set asynchronously via {@link #setFuture}.
- * A similar effect could be accomplished by adding a listener to the delegate
- * future that sets a normal settable future after the delegate is complete.
- * This approach gains us the ability to keep track of whether a delegate has
- * been set (i.e. so that we can prevent collisions from setting it twice and
- * can know before the computation is done whether it has been set), as well
- * as improved cancellation semantics (i.e. if either future is cancelled,
- * then the other one is too). This class is thread-safe.
- *
- * @param <V> The result type returned by the Future's {@code get} method.
- *
- * @author Stephen Hicks
- */
-final class AsyncSettableFuture<V> extends ForwardingListenableFuture<V> {
-
- /** Creates a new asynchronously-settable future. */
- public static <V> AsyncSettableFuture<V> create() {
- return new AsyncSettableFuture<V>();
- }
-
- private final NestedFuture<V> nested = new NestedFuture<V>();
- private final ListenableFuture<V> dereferenced = Futures.dereference(nested);
-
- private AsyncSettableFuture() {}
-
- @Override protected ListenableFuture<V> delegate() {
- return dereferenced;
- }
-
- /**
- * Sets this future to forward to the given future. Returns {@code true}
- * if the future was able to be set (i.e. it hasn't been set already).
- */
- public boolean setFuture(ListenableFuture<? extends V> future) {
- return nested.setFuture(checkNotNull(future));
- }
-
- /**
- * Convenience method that calls {@link #setFuture} on a {@link
- * Futures#immediateFuture}. Returns {@code true} if the future
- * was able to be set (i.e. it hasn't been set already).
- */
- public boolean setValue(@Nullable V value) {
- return setFuture(Futures.immediateFuture(value));
- }
-
- /**
- * Convenience method that calls {@link #setFuture} on a {@link
- * Futures#immediateFailedFuture}. Returns {@code true} if the
- * future was able to be set (i.e. it hasn't been set already).
- */
- public boolean setException(Throwable exception) {
- return setFuture(Futures.<V>immediateFailedFuture(exception));
- }
-
- /**
- * Returns {@code true} if this future has been (possibly asynchronously) set.
- * Note that a {@code false} result in no way gaurantees that a later call
- * to, e.g., {@link #setFuture} will succeed, since another thread could
- * make the call in between. This is somewhat analogous to {@link #isDone},
- * but since setting and completing are not the same event, it is useful to
- * have this method broken out.
- */
- public boolean isSet() {
- return nested.isDone();
- }
-
- private static final class NestedFuture<V> extends AbstractFuture<ListenableFuture<? extends V>> {
- boolean setFuture(ListenableFuture<? extends V> value) {
- boolean result = set(value);
- if (isCancelled()) {
- value.cancel(wasInterrupted());
- }
- return result;
- }
- }
-}
diff --git a/guava/src/com/google/common/util/concurrent/AtomicLongMap.java b/guava/src/com/google/common/util/concurrent/AtomicLongMap.java
index d0af965..35fafaf 100644
--- a/guava/src/com/google/common/util/concurrent/AtomicLongMap.java
+++ b/guava/src/com/google/common/util/concurrent/AtomicLongMap.java
@@ -23,6 +23,7 @@ import com.google.common.base.Function;
import com.google.common.collect.Maps;
import java.util.Collections;
+import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
@@ -255,10 +256,12 @@ public final class AtomicLongMap<K> {
* of the zero values have been removed and others have not.
*/
public void removeAllZeros() {
- for (K key : map.keySet()) {
- AtomicLong atomic = map.get(key);
+ Iterator<Map.Entry<K, AtomicLong>> entryIterator = map.entrySet().iterator();
+ while (entryIterator.hasNext()) {
+ Map.Entry<K, AtomicLong> entry = entryIterator.next();
+ AtomicLong atomic = entry.getValue();
if (atomic != null && atomic.get() == 0L) {
- map.remove(key, atomic);
+ entryIterator.remove();
}
}
}
diff --git a/guava/src/com/google/common/util/concurrent/Callables.java b/guava/src/com/google/common/util/concurrent/Callables.java
index 11c67fc..ca0f824 100644
--- a/guava/src/com/google/common/util/concurrent/Callables.java
+++ b/guava/src/com/google/common/util/concurrent/Callables.java
@@ -18,6 +18,8 @@ package com.google.common.util.concurrent;
import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Supplier;
import java.util.concurrent.Callable;
@@ -30,6 +32,7 @@ import javax.annotation.Nullable;
* @author Isaac Shum
* @since 1.0
*/
+ at GwtCompatible(emulated = true)
public final class Callables {
private Callables() {}
@@ -54,6 +57,7 @@ public final class Callables {
* @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
* for each invocation of the wrapped callable.
*/
+ @GwtIncompatible("threads")
static <T> Callable<T> threadRenaming(final Callable<T> callable,
final Supplier<String> nameSupplier) {
checkNotNull(nameSupplier);
@@ -83,6 +87,7 @@ public final class Callables {
* @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
* for each invocation of the wrapped callable.
*/
+ @GwtIncompatible("threads")
static Runnable threadRenaming(final Runnable task, final Supplier<String> nameSupplier) {
checkNotNull(nameSupplier);
checkNotNull(task);
@@ -103,6 +108,7 @@ public final class Callables {
}
/** Tries to set name of the given {@link Thread}, returns true if successful. */
+ @GwtIncompatible("threads")
private static boolean trySetName(final String threadName, Thread currentThread) {
// In AppEngine this will always fail, should we test for that explicitly using
// MoreExecutors.isAppEngine. More generally, is there a way to see if we have the modifyThread
diff --git a/guava/src/com/google/common/util/concurrent/CheckedFuture.java b/guava/src/com/google/common/util/concurrent/CheckedFuture.java
index e286e2a..70d461e 100644
--- a/guava/src/com/google/common/util/concurrent/CheckedFuture.java
+++ b/guava/src/com/google/common/util/concurrent/CheckedFuture.java
@@ -17,6 +17,7 @@
package com.google.common.util.concurrent;
import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
@@ -29,6 +30,14 @@ import java.util.concurrent.TimeoutException;
* of the {@code get} methods that can throw a checked exception. This makes it
* easier to create a future that executes logic which can throw an exception.
*
+ * <p><b>Warning:</b> We recommend against using {@code CheckedFuture} in new
+ * projects. {@code CheckedFuture} is difficult to build libraries atop. {@code
+ * CheckedFuture} ports of methods like {@link Futures#transformAsync} have
+ * historically had bugs, and some of these bugs are necessary, unavoidable
+ * consequences of the {@code CheckedFuture} API. Additionally, {@code
+ * CheckedFuture} encourages users to take exceptions from one thread and
+ * rethrow them in another, producing confusing stack traces.
+ *
* <p>A common implementation is {@link Futures#immediateCheckedFuture}.
*
* <p>Implementations of this interface must adapt the exceptions thrown by
@@ -41,14 +50,15 @@ import java.util.concurrent.TimeoutException;
* {@link Future} or as an asynchronous callback mechanism as needed. This
* allows multiple callbacks to be registered for a particular task, and the
* future will guarantee execution of all listeners when the task completes.
- *
- * <p>For a simpler alternative to CheckedFuture, consider accessing Future
- * values with {@link Futures#get(Future, Class) Futures.get()}.
+ *
+ * <p>For a simpler alternative to CheckedFuture, consider accessing Future
+ * values with {@link Futures#getChecked(Future, Class) Futures.getChecked()}.
*
* @author Sven Mawson
* @since 1.0
*/
@Beta
+ at GwtCompatible
public interface CheckedFuture<V, X extends Exception>
extends ListenableFuture<V> {
diff --git a/guava/src/com/google/common/util/concurrent/CollectionFuture.java b/guava/src/com/google/common/util/concurrent/CollectionFuture.java
new file mode 100644
index 0000000..2bf9320
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/CollectionFuture.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2006 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.j2objc.annotations.WeakOuter;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+/**
+ * Aggregate future that collects (stores) results of each future.
+ */
+ at GwtCompatible
+abstract class CollectionFuture<V, C> extends AggregateFuture<V, C> {
+
+ @WeakOuter
+ abstract class CollectionFutureRunningState extends RunningState {
+ private List<Optional<V>> values;
+
+ CollectionFutureRunningState(
+ ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
+ boolean allMustSucceed) {
+ super(futures, allMustSucceed, true);
+
+ this.values = futures.isEmpty() ? ImmutableList.<Optional<V>>of()
+ : Lists.<Optional<V>>newArrayListWithCapacity(futures.size());
+
+ // Populate the results list with null initially.
+ for (int i = 0; i < futures.size(); ++i) {
+ values.add(null);
+ }
+ }
+
+ @Override
+ final void collectOneValue(boolean allMustSucceed, int index, @Nullable V returnValue) {
+ List<Optional<V>> localValues = values;
+
+ if (localValues != null) {
+ localValues.set(index, Optional.fromNullable(returnValue));
+ } else {
+ // Some other future failed or has been cancelled, causing this one to
+ // also be cancelled or have an exception set. This should only happen
+ // if allMustSucceed is true or if the output itself has been
+ // cancelled.
+ checkState(allMustSucceed || isCancelled(),
+ "Future was done before all dependencies completed");
+ }
+ }
+
+ @Override
+ final void handleAllCompleted() {
+ List<Optional<V>> localValues = values;
+ if (localValues != null) {
+ set(combine(localValues));
+ } else {
+ checkState(isDone());
+ }
+ }
+
+ @Override
+ void releaseResourcesAfterFailure() {
+ super.releaseResourcesAfterFailure();
+ this.values = null;
+ }
+
+ abstract C combine(List<Optional<V>> values);
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java b/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java
index e438cec..7752d19 100644
--- a/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java
+++ b/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java
@@ -27,6 +27,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+import com.google.j2objc.annotations.Weak;
import java.util.ArrayList;
import java.util.Arrays;
@@ -519,7 +520,7 @@ public class CycleDetectingLockFactory {
static final StackTraceElement[] EMPTY_STACK_TRACE =
new StackTraceElement[0];
- static Set<String> EXCLUDED_CLASS_NAMES = ImmutableSet.of(
+ static final Set<String> EXCLUDED_CLASS_NAMES = ImmutableSet.of(
CycleDetectingLockFactory.class.getName(),
ExampleStackTrace.class.getName(),
LockGraphNode.class.getName());
@@ -665,10 +666,8 @@ public class CycleDetectingLockFactory {
// can happen because multiple locks may share the same LockGraphNode. In
// this situation, throw an IllegalStateException as defined by contract
// described in the documentation of WithExplicitOrdering.
- Preconditions.checkState(
- this != acquiredLock,
- "Attempted to acquire multiple locks with the same rank " +
- acquiredLock.getLockName());
+ Preconditions.checkState(this != acquiredLock,
+ "Attempted to acquire multiple locks with the same rank %s", acquiredLock.getLockName());
if (allowedPriorLocks.containsKey(acquiredLock)) {
// The acquisition ordering from "acquiredLock" to "this" has already
@@ -778,7 +777,7 @@ public class CycleDetectingLockFactory {
LockGraphNode node = lock.getLockGraphNode();
// Iterate in reverse because locks are usually locked/unlocked in a
// LIFO order.
- for (int i = acquiredLockList.size() - 1; i >=0; i--) {
+ for (int i = acquiredLockList.size() - 1; i >= 0; i--) {
if (acquiredLockList.get(i) == node) {
acquiredLockList.remove(i);
break;
@@ -911,7 +910,7 @@ public class CycleDetectingLockFactory {
private class CycleDetectingReentrantReadLock
extends ReentrantReadWriteLock.ReadLock {
- final CycleDetectingReentrantReadWriteLock readWriteLock;
+ @Weak final CycleDetectingReentrantReadWriteLock readWriteLock;
CycleDetectingReentrantReadLock(
CycleDetectingReentrantReadWriteLock readWriteLock) {
@@ -973,7 +972,7 @@ public class CycleDetectingLockFactory {
private class CycleDetectingReentrantWriteLock
extends ReentrantReadWriteLock.WriteLock {
- final CycleDetectingReentrantReadWriteLock readWriteLock;
+ @Weak final CycleDetectingReentrantReadWriteLock readWriteLock;
CycleDetectingReentrantWriteLock(
CycleDetectingReentrantReadWriteLock readWriteLock) {
diff --git a/guava/src/com/google/common/util/concurrent/ExecutionList.java b/guava/src/com/google/common/util/concurrent/ExecutionList.java
index cb9fc82..0e35048 100644
--- a/guava/src/com/google/common/util/concurrent/ExecutionList.java
+++ b/guava/src/com/google/common/util/concurrent/ExecutionList.java
@@ -16,8 +16,9 @@
package com.google.common.util.concurrent;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
import java.util.concurrent.Executor;
import java.util.logging.Level;
@@ -27,18 +28,16 @@ import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
/**
- * <p>A list of listeners, each with an associated {@code Executor}, that
- * guarantees that every {@code Runnable} that is {@linkplain #add added} will
- * be executed after {@link #execute()} is called. Any {@code Runnable} added
- * after the call to {@code execute} is still guaranteed to execute. There is no
- * guarantee, however, that listeners will be executed in the order that they
- * are added.
+ * A support class for {@code ListenableFuture} implementations to manage their listeners. An
+ * instance contains a list of listeners, each with an associated {@code Executor}, and guarantees
+ * that every {@code Runnable} that is {@linkplain #add added} will be executed after {@link
+ * #execute()} is called. Any {@code Runnable} added after the call to {@code execute} is still
+ * guaranteed to execute. There is no guarantee, however, that listeners will be executed in the
+ * order that they are added.
*
- * <p>Exceptions thrown by a listener will be propagated up to the executor.
- * Any exception thrown during {@code Executor.execute} (e.g., a {@code
- * RejectedExecutionException} or an exception thrown by {@linkplain
- * MoreExecutors#directExecutor direct execution}) will be caught and
- * logged.
+ * <p>Exceptions thrown by a listener will be propagated up to the executor. Any exception thrown
+ * during {@code Executor.execute} (e.g., a {@code RejectedExecutionException} or an exception
+ * thrown by {@linkplain MoreExecutors#directExecutor direct execution}) will be caught and logged.
*
* @author Nishant Thakkar
* @author Sven Mawson
@@ -49,8 +48,8 @@ public final class ExecutionList {
@VisibleForTesting static final Logger log = Logger.getLogger(ExecutionList.class.getName());
/**
- * The runnable, executor pairs to execute. This acts as a stack threaded through the
- * {@link RunnableExecutorPair#next} field.
+ * The runnable, executor pairs to execute. This acts as a stack threaded through the {@link
+ * RunnableExecutorPair#next} field.
*/
@GuardedBy("this")
private RunnableExecutorPair runnables;
@@ -61,61 +60,49 @@ public final class ExecutionList {
public ExecutionList() {}
/**
- * Adds the {@code Runnable} and accompanying {@code Executor} to the list of
- * listeners to execute. If execution has already begun, the listener is
- * executed immediately.
+ * Adds the {@code Runnable} and accompanying {@code Executor} to the list of listeners to
+ * execute. If execution has already begun, the listener is executed immediately.
*
- * <p>Note: For fast, lightweight listeners that would be safe to execute in
- * any thread, consider {@link MoreExecutors#directExecutor}. For heavier
- * listeners, {@code directExecutor()} carries some caveats: First, the
- * thread that the listener runs in depends on whether the {@code
- * ExecutionList} has been executed at the time it is added. In particular,
- * listeners may run in the thread that calls {@code add}. Second, the thread
- * that calls {@link #execute} may be an internal implementation thread, such
- * as an RPC network thread, and {@code directExecutor()} listeners may
- * run in this thread. Finally, during the execution of a {@code
- * directExecutor} listener, all other registered but unexecuted
- * listeners are prevented from running, even if those listeners are to run
- * in other executors.
+ * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
+ * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation.
*/
public void add(Runnable runnable, Executor executor) {
- // Fail fast on a null. We throw NPE here because the contract of
- // Executor states that it throws NPE on null listener, so we propagate
- // that contract up into the add method as well.
- Preconditions.checkNotNull(runnable, "Runnable was null.");
- Preconditions.checkNotNull(executor, "Executor was null.");
+ // Fail fast on a null. We throw NPE here because the contract of Executor states that it
+ // throws NPE on null listener, so we propagate that contract up into the add method as well.
+ checkNotNull(runnable, "Runnable was null.");
+ checkNotNull(executor, "Executor was null.");
- // Lock while we check state. We must maintain the lock while adding the
- // new pair so that another thread can't run the list out from under us.
- // We only add to the list if we have not yet started execution.
+ // Lock while we check state. We must maintain the lock while adding the new pair so that
+ // another thread can't run the list out from under us. We only add to the list if we have not
+ // yet started execution.
synchronized (this) {
if (!executed) {
runnables = new RunnableExecutorPair(runnable, executor, runnables);
return;
}
}
- // Execute the runnable immediately. Because of scheduling this may end up
- // getting called before some of the previously added runnables, but we're
- // OK with that. If we want to change the contract to guarantee ordering
- // among runnables we'd have to modify the logic here to allow it.
+ // Execute the runnable immediately. Because of scheduling this may end up getting called before
+ // some of the previously added runnables, but we're OK with that. If we want to change the
+ // contract to guarantee ordering among runnables we'd have to modify the logic here to allow
+ // it.
executeListener(runnable, executor);
}
/**
- * Runs this execution list, executing all existing pairs in the order they
- * were added. However, note that listeners added after this point may be
- * executed before those previously added, and note that the execution order
- * of all listeners is ultimately chosen by the implementations of the
- * supplied executors.
+ * Runs this execution list, executing all existing pairs in the order they were added. However,
+ * note that listeners added after this point may be executed before those previously added, and
+ * note that the execution order of all listeners is ultimately chosen by the implementations of
+ * the supplied executors.
*
- * <p>This method is idempotent. Calling it several times in parallel is
- * semantically equivalent to calling it exactly once.
+ * <p>This method is idempotent. Calling it several times in parallel is semantically equivalent
+ * to calling it exactly once.
*
* @since 10.0 (present in 1.0 as {@code run})
*/
public void execute() {
- // Lock while we update our state so the add method above will finish adding
- // any listeners before we start to run them.
+ // Lock while we update our state so the add method above will finish adding any listeners
+ // before we start to run them.
RunnableExecutorPair list;
synchronized (this) {
if (executed) {
@@ -128,11 +115,11 @@ public final class ExecutionList {
// If we succeeded then list holds all the runnables we to execute. The pairs in the stack are
// in the opposite order from how they were added so we need to reverse the list to fulfill our
// contract.
- // This is somewhat annoying, but turns out to be very fast in practice. Alternatively, we
+ // This is somewhat annoying, but turns out to be very fast in practice. Alternatively, we
// could drop the contract on the method that enforces this queue like behavior since depending
// on it is likely to be a bug anyway.
- // N.B. All writes to the list and the next pointers must have happened before the above
+ // N.B. All writes to the list and the next pointers must have happened before the above
// synchronized block, so we can iterate the list without the lock held here.
RunnableExecutorPair reversedList = null;
while (list != null) {
@@ -148,16 +135,16 @@ public final class ExecutionList {
}
/**
- * Submits the given runnable to the given {@link Executor} catching and logging all
- * {@linkplain RuntimeException runtime exceptions} thrown by the executor.
+ * Submits the given runnable to the given {@link Executor} catching and logging all {@linkplain
+ * RuntimeException runtime exceptions} thrown by the executor.
*/
private static void executeListener(Runnable runnable, Executor executor) {
try {
executor.execute(runnable);
} catch (RuntimeException e) {
- // Log it and keep going, bad runnable and/or executor. Don't
- // punish the other runnables if we're given a bad one. We only
- // catch RuntimeException because we want Errors to propagate up.
+ // Log it and keep going, bad runnable and/or executor. Don't punish the other runnables if
+ // we're given a bad one. We only catch RuntimeException because we want Errors to propagate
+ // up.
log.log(Level.SEVERE, "RuntimeException while executing runnable "
+ runnable + " with executor " + executor, e);
}
diff --git a/guava/src/com/google/common/util/concurrent/FutureCallback.java b/guava/src/com/google/common/util/concurrent/FutureCallback.java
index efab08f..691d5d3 100644
--- a/guava/src/com/google/common/util/concurrent/FutureCallback.java
+++ b/guava/src/com/google/common/util/concurrent/FutureCallback.java
@@ -16,6 +16,8 @@
package com.google.common.util.concurrent;
+import com.google.common.annotations.GwtCompatible;
+
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -30,6 +32,7 @@ import javax.annotation.Nullable;
* @author Anthony Zana
* @since 10.0
*/
+ at GwtCompatible
public interface FutureCallback<V> {
/**
* Invoked with the result of the {@code Future} computation when it is
diff --git a/guava/src/com/google/common/util/concurrent/FutureFallback.java b/guava/src/com/google/common/util/concurrent/FutureFallback.java
index 7d03c67..cb7fcc6 100644
--- a/guava/src/com/google/common/util/concurrent/FutureFallback.java
+++ b/guava/src/com/google/common/util/concurrent/FutureFallback.java
@@ -17,32 +17,36 @@
package com.google.common.util.concurrent;
import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
- * Provides a backup {@code Future} to replace an earlier failed {@code Future}.
- * An implementation of this interface can be applied to an input {@code Future}
- * with {@link Futures#withFallback}.
+ * Provides a backup {@code Future} to replace an earlier failed {@code Future}. An implementation
+ * of this interface can be applied to an input {@code Future} with {@link Futures#withFallback}.
*
* @param <V> the result type of the provided backup {@code Future}
*
* @author Bruno Diniz
* @since 14.0
+ * @deprecated This interface's main user, {@link Futures#withFallback(ListenableFuture,
+ * FutureFallback) Futures.withFallback}, has been updated to use {@link AsyncFunction}. We
+ * recommend that other APIs be updated in the same way. This interface will be removed in Guava
+ * release 20.0.
*/
@Beta
+ at Deprecated
+ at GwtCompatible
public interface FutureFallback<V> {
/**
- * Returns a {@code Future} to be used in place of the {@code Future} that
- * failed with the given exception. The exception is provided so that the
- * {@code Fallback} implementation can conditionally determine whether to
- * propagate the exception or to attempt to recover.
+ * Returns a {@code Future} to be used in place of the {@code Future} that failed with the given
+ * exception. The exception is provided so that the {@code Fallback} implementation can
+ * conditionally determine whether to propagate the exception or to attempt to recover.
*
- * @param t the exception that made the future fail. If the future's {@link
- * Future#get() get} method throws an {@link ExecutionException}, then the
- * cause is passed to this method. Any other thrown object is passed
- * unaltered.
+ * @param t the exception that made the future fail. If the future's {@link Future#get() get}
+ * method throws an {@link ExecutionException}, then the cause is passed to this method. Any
+ * other thrown object is passed unaltered.
*/
ListenableFuture<V> create(Throwable t) throws Exception;
}
diff --git a/guava/src/com/google/common/util/concurrent/Futures.java b/guava/src/com/google/common/util/concurrent/Futures.java
index 650ff26..3fb81d0 100644
--- a/guava/src/com/google/common/util/concurrent/Futures.java
+++ b/guava/src/com/google/common/util/concurrent/Futures.java
@@ -16,46 +16,38 @@
package com.google.common.util.concurrent;
-import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.Platform.isInstanceOfThrowableClass;
import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
-import static java.lang.Thread.currentThread;
-import static java.util.Arrays.asList;
import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
-import com.google.common.collect.Ordering;
import com.google.common.collect.Queues;
-import com.google.common.collect.Sets;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
@@ -63,7 +55,7 @@ import javax.annotation.Nullable;
*
* <p>Many of these methods use the {@link ListenableFuture} API; consult the
* Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained">
+ * "https://github.com/google/guava/wiki/ListenableFutureExplained">
* {@code ListenableFuture}</a>.
*
* @author Kevin Bourrillion
@@ -72,13 +64,66 @@ import javax.annotation.Nullable;
* @since 1.0
*/
@Beta
-public final class Futures {
+ at GwtCompatible(emulated = true)
+public final class Futures extends GwtFuturesCatchingSpecialization {
+
+ // A note on memory visibility.
+ // Many of the utilities in this class (transform, withFallback, withTimeout, asList, combine)
+ // have two requirements that significantly complicate their design.
+ // 1. Cancellation should propagate from the returned future to the input future(s).
+ // 2. The returned futures shouldn't unnecessarily 'pin' their inputs after completion.
+ //
+ // A consequence of these requirements is that the delegate futures cannot be stored in
+ // final fields.
+ //
+ // For simplicity the rest of this description will discuss Futures.catching since it is the
+ // simplest instance, though very similar descriptions apply to many other classes in this file.
+ //
+ // In the constructor of AbstractCatchingFuture, the delegate future is assigned to a field
+ // 'inputFuture'. That field is non-final and non-volatile. There are 2 places where the
+ // 'inputFuture' field is read and where we will have to consider visibility of the write
+ // operation in the constructor.
+ //
+ // 1. In the listener that performs the callback. In this case it is fine since inputFuture is
+ // assigned prior to calling addListener, and addListener happens-before any invocation of the
+ // listener. Notably, this means that 'volatile' is unnecessary to make 'inputFuture' visible
+ // to the listener.
+ //
+ // 2. In done() where we may propagate cancellation to the input. In this case it is _not_ fine.
+ // There is currently nothing that enforces that the write to inputFuture in the constructor is
+ // visible to done(). This is because there is no happens before edge between the write and a
+ // (hypothetical) unsafe read by our caller. Note: adding 'volatile' does not fix this issue,
+ // it would just add an edge such that if done() observed non-null, then it would also
+ // definitely observe all earlier writes, but we still have no guarantee that done() would see
+ // the inital write (just stronger guarantees if it does).
+ //
+ // See: http://cs.oswego.edu/pipermail/concurrency-interest/2015-January/013800.html
+ // For a (long) discussion about this specific issue and the general futility of life.
+ //
+ // For the time being we are OK with the problem discussed above since it requires a caller to
+ // introduce a very specific kind of data-race. And given the other operations performed by these
+ // methods that involve volatile read/write operations, in practice there is no issue. Also, the
+ // way in such a visibility issue would surface is most likely as a failure of cancel() to
+ // propagate to the input. Cancellation propagation is fundamentally racy so this is fine.
+ //
+ // Future versions of the JMM may revise safe construction semantics in such a way that we can
+ // safely publish these objects and we won't need this whole discussion.
+ // TODO(user,lukes): consider adding volatile to all these fields since in current known JVMs
+ // that should resolve the issue. This comes at the cost of adding more write barriers to the
+ // implementations.
+
private Futures() {}
/**
- * Creates a {@link CheckedFuture} out of a normal {@link ListenableFuture}
- * and a {@link Function} that maps from {@link Exception} instances into the
- * appropriate checked type.
+ * Creates a {@link CheckedFuture} out of a normal {@link ListenableFuture} and a {@link Function}
+ * that maps from {@link Exception} instances into the appropriate checked type.
+ *
+ * <p><b>Warning:</b> We recommend against using {@code CheckedFuture} in new projects. {@code
+ * CheckedFuture} is difficult to build libraries atop. {@code CheckedFuture} ports of methods
+ * like {@link Futures#transformAsync} have historically had bugs, and some of these bugs are
+ * necessary, unavoidable consequences of the {@code CheckedFuture} API. Additionally, {@code
+ * CheckedFuture} encourages users to take exceptions from one thread and rethrow them in another,
+ * producing confusing stack traces.
*
* <p>The given mapping function will be applied to an
* {@link InterruptedException}, a {@link CancellationException}, or an
@@ -87,6 +132,8 @@ public final class Futures {
*
* @since 9.0 (source-compatible since 1.0)
*/
+ @GwtIncompatible("TODO")
+ @CheckReturnValue
public static <V, X extends Exception> CheckedFuture<V, X> makeChecked(
ListenableFuture<V> future, Function<? super Exception, X> mapper) {
return new MappingCheckedFuture<V, X>(checkNotNull(future), mapper);
@@ -138,6 +185,8 @@ public final class Futures {
}
private static class ImmediateSuccessfulFuture<V> extends ImmediateFuture<V> {
+ static final ImmediateSuccessfulFuture<Object> NULL =
+ new ImmediateSuccessfulFuture<Object>(null);
@Nullable private final V value;
@@ -151,6 +200,7 @@ public final class Futures {
}
}
+ @GwtIncompatible("TODO")
private static class ImmediateSuccessfulCheckedFuture<V, X extends Exception>
extends ImmediateFuture<V> implements CheckedFuture<V, X> {
@@ -191,6 +241,7 @@ public final class Futures {
}
}
+ @GwtIncompatible("TODO")
private static class ImmediateCancelledFuture<V> extends ImmediateFuture<V> {
private final CancellationException thrown;
@@ -211,6 +262,7 @@ public final class Futures {
}
}
+ @GwtIncompatible("TODO")
private static class ImmediateFailedCheckedFuture<V, X extends Exception>
extends ImmediateFuture<V> implements CheckedFuture<V, X> {
@@ -243,7 +295,14 @@ public final class Futures {
* be canceled or timed out and its {@code isDone()} method always returns
* {@code true}.
*/
+ @CheckReturnValue
public static <V> ListenableFuture<V> immediateFuture(@Nullable V value) {
+ if (value == null) {
+ // This cast is safe because null is assignable to V for all V (i.e. it is covariant)
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ ListenableFuture<V> typedNull = (ListenableFuture) ImmediateSuccessfulFuture.NULL;
+ return typedNull;
+ }
return new ImmediateSuccessfulFuture<V>(value);
}
@@ -255,6 +314,8 @@ public final class Futures {
* method always returns {@code true}. Calling {@code get()} or {@code
* checkedGet()} will immediately return the provided value.
*/
+ @GwtIncompatible("TODO")
+ @CheckReturnValue
public static <V, X extends Exception> CheckedFuture<V, X>
immediateCheckedFuture(@Nullable V value) {
return new ImmediateSuccessfulCheckedFuture<V, X>(value);
@@ -269,6 +330,7 @@ public final class Futures {
* throw the provided {@code Throwable} wrapped in an {@code
* ExecutionException}.
*/
+ @CheckReturnValue
public static <V> ListenableFuture<V> immediateFailedFuture(
Throwable throwable) {
checkNotNull(throwable);
@@ -281,6 +343,8 @@ public final class Futures {
*
* @since 14.0
*/
+ @GwtIncompatible("TODO")
+ @CheckReturnValue
public static <V> ListenableFuture<V> immediateCancelledFuture() {
return new ImmediateCancelledFuture<V>();
}
@@ -295,6 +359,8 @@ public final class Futures {
* ExecutionException}, and calling {@code checkedGet()} will throw the
* provided exception itself.
*/
+ @GwtIncompatible("TODO")
+ @CheckReturnValue
public static <V, X extends Exception> CheckedFuture<V, X>
immediateFailedCheckedFuture(X exception) {
checkNotNull(exception);
@@ -345,34 +411,25 @@ public final class Futures {
* }
* });}</pre>
*
- * <p>Note: If the derived {@code Future} is slow or heavyweight to create
- * (whether the {@code Future} itself is slow or heavyweight to complete is
- * irrelevant), consider {@linkplain #withFallback(ListenableFuture,
- * FutureFallback, Executor) supplying an executor}. If you do not supply an
- * executor, {@code withFallback} will use a
- * {@linkplain MoreExecutors#directExecutor direct executor}, which carries
- * some caveats for heavier operations. For example, the call to {@code
- * fallback.create} may run on an unpredictable or undesirable thread:
- *
- * <ul>
- * <li>If the input {@code Future} is done at the time {@code withFallback}
- * is called, {@code withFallback} will call {@code fallback.create} inline.
- * <li>If the input {@code Future} is not yet done, {@code withFallback} will
- * schedule {@code fallback.create} to be run by the thread that completes
- * the input {@code Future}, which may be an internal system thread such as
- * an RPC network thread.
- * </ul>
- *
- * <p>Also note that, regardless of which thread executes the {@code
- * fallback.create}, all other registered but unexecuted listeners are
- * prevented from running during its execution, even if those listeners are
- * to run in other executors.
+ * <p>This overload, which does not accept an executor, uses {@code
+ * directExecutor}, a dangerous choice in some cases. See the discussion in
+ * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation. The documentation's warnings about "lightweight listeners"
+ * refer here to the work done during {@code FutureFallback.create}, not to
+ * any work done to complete the returned {@code Future}.
*
* @param input the primary input {@code Future}
* @param fallback the {@link FutureFallback} implementation to be called if
* {@code input} fails
* @since 14.0
+ * @deprecated Use {@link #catchingAsync(ListenableFuture, Class,
+ * AsyncFunction) catchingAsync(input, Throwable.class,
+ * fallbackImplementedAsAnAsyncFunction)}, usually replacing {@code
+ * Throwable.class} with the specific type you want to handle. This method
+ * will be removed in Guava release 20.0.
*/
+ @Deprecated
+ @CheckReturnValue
public static <V> ListenableFuture<V> withFallback(
ListenableFuture<? extends V> input,
FutureFallback<? extends V> fallback) {
@@ -423,12 +480,12 @@ public final class Futures {
* }
* }, directExecutor());}</pre>
*
- * <p>When the execution of {@code fallback.create} is fast and lightweight
- * (though the {@code Future} it returns need not meet these criteria),
- * consider {@linkplain #withFallback(ListenableFuture, FutureFallback)
- * omitting the executor} or explicitly specifying {@code
- * directExecutor}. However, be aware of the caveats documented in the
- * link above.
+ * <p>When selecting an executor, note that {@code directExecutor} is
+ * dangerous in some cases. See the discussion in the {@link
+ * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+ * The documentation's warnings about "lightweight listeners" refer here to
+ * the work done during {@code FutureFallback.create}, not to any work done to
+ * complete the returned {@code Future}.
*
* @param input the primary input {@code Future}
* @param fallback the {@link FutureFallback} implementation to be called if
@@ -436,72 +493,476 @@ public final class Futures {
* @param executor the executor that runs {@code fallback} if {@code input}
* fails
* @since 14.0
+ * @deprecated Use {@link #catchingAsync(ListenableFuture, Class,
+ * AsyncFunction, Executor) catchingAsync(input, Throwable.class,
+ * fallbackImplementedAsAnAsyncFunction, executor)}, usually replacing
+ * {@code Throwable.class} with the specific type you want to handle. This method
+ * will be removed in Guava release 20.0.
*/
+ @Deprecated
+ @CheckReturnValue
public static <V> ListenableFuture<V> withFallback(
ListenableFuture<? extends V> input,
FutureFallback<? extends V> fallback, Executor executor) {
+ return catchingAsync(
+ input, Throwable.class, asAsyncFunction(fallback), executor);
+ }
+
+ /**
+ * Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the
+ * primary input fails with the given {@code exceptionType}, from the result provided by the
+ * {@code fallback}. {@link Function#apply} is not invoked until the primary input has failed, so
+ * if the primary input succeeds, it is never invoked. If, during the invocation of {@code
+ * fallback}, an exception is thrown, this exception is used as the result of the output {@code
+ * Future}.
+ *
+ * <p>Usage example:
+ *
+ * <pre> {@code
+ * ListenableFuture<Integer> fetchCounterFuture = ...;
+ *
+ * // Falling back to a zero counter in case an exception happens when
+ * // processing the RPC to fetch counters.
+ * ListenableFuture<Integer> faultTolerantFuture = Futures.catching(
+ * fetchCounterFuture, FetchException.class,
+ * new Function<FetchException, Integer>() {
+ * public Integer apply(FetchException e) {
+ * return 0;
+ * }
+ * });}</pre>
+ *
+ * <p>This overload, which does not accept an executor, uses {@code directExecutor}, a dangerous
+ * choice in some cases. See the discussion in the {@link ListenableFuture#addListener
+ * ListenableFuture.addListener} documentation. The documentation's warnings about "lightweight
+ * listeners" refer here to the work done during {@code Function.apply}.
+ *
+ * @param input the primary input {@code Future}
+ * @param exceptionType the exception type that triggers use of {@code fallback}. To avoid hiding
+ * bugs and other unrecoverable errors, callers should prefer more specific types, avoiding
+ * {@code Throwable.class} in particular.
+ * @param fallback the {@link Function} implementation to be called if {@code input} fails with
+ * the expected exception type
+ * @since 19.0
+ */
+ @GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
+ @CheckReturnValue
+ public static <V, X extends Throwable> ListenableFuture<V> catching(
+ ListenableFuture<? extends V> input, Class<X> exceptionType,
+ Function<? super X, ? extends V> fallback) {
+ CatchingFuture<V, X> future = new CatchingFuture<V, X>(input, exceptionType, fallback);
+ input.addListener(future, directExecutor());
+ return future;
+ }
+
+ /**
+ * Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the
+ * primary input fails with the given {@code exceptionType}, from the result provided by the
+ * {@code fallback}. {@link Function#apply} is not invoked until the primary input has failed, so
+ * if the primary input succeeds, it is never invoked. If, during the invocation of {@code
+ * fallback}, an exception is thrown, this exception is used as the result of the output {@code
+ * Future}.
+ *
+ * <p>Usage example:
+ *
+ * <pre> {@code
+ * ListenableFuture<Integer> fetchCounterFuture = ...;
+ *
+ * // Falling back to a zero counter in case an exception happens when
+ * // processing the RPC to fetch counters.
+ * ListenableFuture<Integer> faultTolerantFuture = Futures.catching(
+ * fetchCounterFuture, FetchException.class,
+ * new Function<FetchException, Integer>() {
+ * public Integer apply(FetchException e) {
+ * return 0;
+ * }
+ * }, directExecutor());}</pre>
+ *
+ * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
+ * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation. The documentation's warnings about "lightweight listeners" refer here to the
+ * work done during {@code Function.apply}.
+ *
+ * @param input the primary input {@code Future}
+ * @param exceptionType the exception type that triggers use of {@code fallback}. To avoid hiding
+ * bugs and other unrecoverable errors, callers should prefer more specific types, avoiding
+ * {@code Throwable.class} in particular.
+ * @param fallback the {@link Function} implementation to be called if {@code input} fails with
+ * the expected exception type
+ * @param executor the executor that runs {@code fallback} if {@code input} fails
+ * @since 19.0
+ */
+ @GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
+ @CheckReturnValue
+ public static <V, X extends Throwable> ListenableFuture<V> catching(
+ ListenableFuture<? extends V> input, Class<X> exceptionType,
+ Function<? super X, ? extends V> fallback, Executor executor) {
+ CatchingFuture<V, X> future = new CatchingFuture<V, X>(input, exceptionType, fallback);
+ input.addListener(future, rejectionPropagatingExecutor(executor, future));
+ return future;
+ }
+
+ /**
+ * Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the
+ * primary input fails with the given {@code exceptionType}, from the result provided by the
+ * {@code fallback}. {@link AsyncFunction#apply} is not invoked until the primary input has
+ * failed, so if the primary input succeeds, it is never invoked. If, during the invocation of
+ * {@code fallback}, an exception is thrown, this exception is used as the result of the output
+ * {@code Future}.
+ *
+ * <p>Usage examples:
+ *
+ * <pre> {@code
+ * ListenableFuture<Integer> fetchCounterFuture = ...;
+ *
+ * // Falling back to a zero counter in case an exception happens when
+ * // processing the RPC to fetch counters.
+ * ListenableFuture<Integer> faultTolerantFuture = Futures.catchingAsync(
+ * fetchCounterFuture, FetchException.class,
+ * new AsyncFunction<FetchException, Integer>() {
+ * public ListenableFuture<Integer> apply(FetchException e) {
+ * return immediateFuture(0);
+ * }
+ * });}</pre>
+ *
+ * <p>The fallback can also choose to propagate the original exception when desired:
+ *
+ * <pre> {@code
+ * ListenableFuture<Integer> fetchCounterFuture = ...;
+ *
+ * // Falling back to a zero counter only in case the exception was a
+ * // TimeoutException.
+ * ListenableFuture<Integer> faultTolerantFuture = Futures.catchingAsync(
+ * fetchCounterFuture, FetchException.class,
+ * new AsyncFunction<FetchException, Integer>() {
+ * public ListenableFuture<Integer> apply(FetchException e)
+ * throws FetchException {
+ * if (omitDataOnFetchFailure) {
+ * return immediateFuture(0);
+ * }
+ * throw e;
+ * }
+ * });}</pre>
+ *
+ * <p>This overload, which does not accept an executor, uses {@code directExecutor}, a dangerous
+ * choice in some cases. See the discussion in the {@link ListenableFuture#addListener
+ * ListenableFuture.addListener} documentation. The documentation's warnings about "lightweight
+ * listeners" refer here to the work done during {@code AsyncFunction.apply}, not to any work done
+ * to complete the returned {@code Future}.
+ *
+ * @param input the primary input {@code Future}
+ * @param exceptionType the exception type that triggers use of {@code fallback}. To avoid hiding
+ * bugs and other unrecoverable errors, callers should prefer more specific types, avoiding
+ * {@code Throwable.class} in particular.
+ * @param fallback the {@link AsyncFunction} implementation to be called if {@code input} fails
+ * with the expected exception type
+ * @since 19.0 (similar functionality in 14.0 as {@code withFallback})
+ */
+ @GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
+ // TODO(kak): @CheckReturnValue
+ public static <V, X extends Throwable> ListenableFuture<V> catchingAsync(
+ ListenableFuture<? extends V> input, Class<X> exceptionType,
+ AsyncFunction<? super X, ? extends V> fallback) {
+ AsyncCatchingFuture<V, X> future =
+ new AsyncCatchingFuture<V, X>(input, exceptionType, fallback);
+ input.addListener(future, directExecutor());
+ return future;
+ }
+
+ /**
+ * Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the
+ * primary input fails with the given {@code exceptionType}, from the result provided by the
+ * {@code fallback}. {@link AsyncFunction#apply} is not invoked until the primary input has
+ * failed, so if the primary input succeeds, it is never invoked. If, during the invocation of
+ * {@code fallback}, an exception is thrown, this exception is used as the result of the output
+ * {@code Future}.
+ *
+ * <p>Usage examples:
+ *
+ * <pre> {@code
+ * ListenableFuture<Integer> fetchCounterFuture = ...;
+ *
+ * // Falling back to a zero counter in case an exception happens when
+ * // processing the RPC to fetch counters.
+ * ListenableFuture<Integer> faultTolerantFuture = Futures.catchingAsync(
+ * fetchCounterFuture, FetchException.class,
+ * new AsyncFunction<FetchException, Integer>() {
+ * public ListenableFuture<Integer> apply(FetchException e) {
+ * return immediateFuture(0);
+ * }
+ * }, directExecutor());}</pre>
+ *
+ * <p>The fallback can also choose to propagate the original exception when desired:
+ *
+ * <pre> {@code
+ * ListenableFuture<Integer> fetchCounterFuture = ...;
+ *
+ * // Falling back to a zero counter only in case the exception was a
+ * // TimeoutException.
+ * ListenableFuture<Integer> faultTolerantFuture = Futures.catchingAsync(
+ * fetchCounterFuture, FetchException.class,
+ * new AsyncFunction<FetchException, Integer>() {
+ * public ListenableFuture<Integer> apply(FetchException e)
+ * throws FetchException {
+ * if (omitDataOnFetchFailure) {
+ * return immediateFuture(0);
+ * }
+ * throw e;
+ * }
+ * }, directExecutor());}</pre>
+ *
+ * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
+ * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation. The documentation's warnings about "lightweight listeners" refer here to the
+ * work done during {@code AsyncFunction.apply}, not to any work done to complete the returned
+ * {@code Future}.
+ *
+ * @param input the primary input {@code Future}
+ * @param exceptionType the exception type that triggers use of {@code fallback}. To avoid hiding
+ * bugs and other unrecoverable errors, callers should prefer more specific types, avoiding
+ * {@code Throwable.class} in particular.
+ * @param fallback the {@link AsyncFunction} implementation to be called if {@code input} fails
+ * with the expected exception type
+ * @param executor the executor that runs {@code fallback} if {@code input} fails
+ * @since 19.0 (similar functionality in 14.0 as {@code withFallback})
+ */
+ @GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
+ // TODO(kak): @CheckReturnValue
+ public static <V, X extends Throwable> ListenableFuture<V> catchingAsync(
+ ListenableFuture<? extends V> input, Class<X> exceptionType,
+ AsyncFunction<? super X, ? extends V> fallback, Executor executor) {
+ AsyncCatchingFuture<V, X> future =
+ new AsyncCatchingFuture<V, X>(input, exceptionType, fallback);
+ input.addListener(future, rejectionPropagatingExecutor(executor, future));
+ return future;
+ }
+
+ @Deprecated
+ static <V> AsyncFunction<Throwable, V> asAsyncFunction(final FutureFallback<V> fallback) {
checkNotNull(fallback);
- return new FallbackFuture<V>(input, fallback, executor);
+ return new AsyncFunction<Throwable, V>() {
+ @Override
+ public ListenableFuture<V> apply(Throwable t) throws Exception {
+ return checkNotNull(fallback.create(t), "FutureFallback.create returned null instead of a "
+ + "Future. Did you mean to return immediateFuture(null)?");
+ }
+ };
+ }
+
+ private abstract static class AbstractCatchingFuture<V, X extends Throwable, F>
+ extends AbstractFuture.TrustedFuture<V> implements Runnable {
+ @Nullable ListenableFuture<? extends V> inputFuture;
+ @Nullable Class<X> exceptionType;
+ @Nullable F fallback;
+
+ AbstractCatchingFuture(
+ ListenableFuture<? extends V> inputFuture, Class<X> exceptionType, F fallback) {
+ this.inputFuture = checkNotNull(inputFuture);
+ this.exceptionType = checkNotNull(exceptionType);
+ this.fallback = checkNotNull(fallback);
+ }
+
+ @Override public final void run() {
+ ListenableFuture<? extends V> localInputFuture = inputFuture;
+ Class<X> localExceptionType = exceptionType;
+ F localFallback = fallback;
+ if (localInputFuture == null | localExceptionType == null | localFallback == null
+ | isCancelled()) {
+ return;
+ }
+ inputFuture = null;
+ exceptionType = null;
+ fallback = null;
+
+ Throwable throwable;
+ try {
+ set(getUninterruptibly(localInputFuture));
+ return;
+ } catch (ExecutionException e) {
+ throwable = e.getCause();
+ } catch (Throwable e) { // this includes cancellation exception
+ throwable = e;
+ }
+ try {
+ if (isInstanceOfThrowableClass(throwable, localExceptionType)) {
+ @SuppressWarnings("unchecked") // verified safe by isInstance
+ X castThrowable = (X) throwable;
+ doFallback(localFallback, castThrowable);
+ } else {
+ setException(throwable);
+ }
+ } catch (Throwable e) {
+ setException(e);
+ }
+ }
+
+ /** Template method for subtypes to actually run the fallback. */
+ abstract void doFallback(F fallback, X throwable) throws Exception;
+
+ @Override final void done() {
+ maybePropagateCancellation(inputFuture);
+ this.inputFuture = null;
+ this.exceptionType = null;
+ this.fallback = null;
+ }
}
/**
- * A future that falls back on a second, generated future, in case its
- * original future fails.
+ * A {@link AbstractCatchingFuture} that delegates to an {@link AsyncFunction}
+ * and {@link #setFuture(ListenableFuture)} to implement {@link #doFallback}
*/
- private static class FallbackFuture<V> extends AbstractFuture<V> {
-
- private volatile ListenableFuture<? extends V> running;
-
- FallbackFuture(ListenableFuture<? extends V> input,
- final FutureFallback<? extends V> fallback,
- final Executor executor) {
- running = input;
- addCallback(running, new FutureCallback<V>() {
- @Override
- public void onSuccess(V value) {
- set(value);
+ static final class AsyncCatchingFuture<V, X extends Throwable>
+ extends AbstractCatchingFuture<V, X, AsyncFunction<? super X, ? extends V>> {
+
+ AsyncCatchingFuture(ListenableFuture<? extends V> input, Class<X> exceptionType,
+ AsyncFunction<? super X, ? extends V> fallback) {
+ super(input, exceptionType, fallback);
+ }
+
+ @Override void doFallback(
+ AsyncFunction<? super X, ? extends V> fallback, X cause) throws Exception {
+ ListenableFuture<? extends V> replacement = fallback.apply(cause);
+ checkNotNull(replacement, "AsyncFunction.apply returned null instead of a Future. "
+ + "Did you mean to return immediateFuture(null)?");
+ setFuture(replacement);
+ }
+ }
+
+ /**
+ * A {@link AbstractCatchingFuture} that delegates to a {@link Function}
+ * and {@link #set(Object)} to implement {@link #doFallback}
+ */
+ static final class CatchingFuture<V, X extends Throwable>
+ extends AbstractCatchingFuture<V, X, Function<? super X, ? extends V>> {
+ CatchingFuture(ListenableFuture<? extends V> input, Class<X> exceptionType,
+ Function<? super X, ? extends V> fallback) {
+ super(input, exceptionType, fallback);
+ }
+
+ @Override void doFallback(Function<? super X, ? extends V> fallback, X cause) throws Exception {
+ V replacement = fallback.apply(cause);
+ set(replacement);
+ }
+ }
+
+ /**
+ * Returns a future that delegates to another but will finish early (via a
+ * {@link TimeoutException} wrapped in an {@link ExecutionException}) if the
+ * specified duration expires.
+ *
+ * <p>The delegate future is interrupted and cancelled if it times out.
+ *
+ * @param delegate The future to delegate to.
+ * @param time when to timeout the future
+ * @param unit the time unit of the time parameter
+ * @param scheduledExecutor The executor service to enforce the timeout.
+ *
+ * @since 19.0
+ */
+ @GwtIncompatible("java.util.concurrent.ScheduledExecutorService")
+ @CheckReturnValue
+ public static <V> ListenableFuture<V> withTimeout(ListenableFuture<V> delegate,
+ long time, TimeUnit unit, ScheduledExecutorService scheduledExecutor) {
+ TimeoutFuture<V> result = new TimeoutFuture<V>(delegate);
+ TimeoutFuture.Fire<V> fire = new TimeoutFuture.Fire<V>(result);
+ result.timer = scheduledExecutor.schedule(fire, time, unit);
+ delegate.addListener(fire, directExecutor());
+ return result;
+ }
+
+ /**
+ * Future that delegates to another but will finish early (via a {@link
+ * TimeoutException} wrapped in an {@link ExecutionException}) if the
+ * specified duration expires.
+ * The delegate future is interrupted and cancelled if it times out.
+ */
+ private static final class TimeoutFuture<V> extends AbstractFuture.TrustedFuture<V> {
+ // Memory visibility of these fields.
+ // There are two cases to consider.
+ // 1. visibility of the writes to these fields to Fire.run
+ // The initial write to delegateRef is made definitely visible via the semantics of
+ // addListener/SES.schedule. The later racy write in cancel() is not guaranteed to be
+ // observed, however that is fine since the correctness is based on the atomic state in
+ // our base class.
+ // The initial write to timer is never definitely visible to Fire.run since it is assigned
+ // after SES.schedule is called. Therefore Fire.run has to check for null. However, it
+ // should be visible if Fire.run is called by delegate.addListener since addListener is
+ // called after the assignment to timer, and importantly this is the main situation in which
+ // we need to be able to see the write.
+ // 2. visibility of the writes to cancel
+ // Since these fields are non-final that means that TimeoutFuture is not being 'safely
+ // published', thus a motivated caller may be able to expose the reference to another thread
+ // that would then call cancel() and be unable to cancel the delegate.
+ // There are a number of ways to solve this, none of which are very pretty, and it is
+ // currently believed to be a purely theoretical problem (since the other actions should
+ // supply sufficient write-barriers).
+
+ @Nullable ListenableFuture<V> delegateRef;
+ @Nullable Future<?> timer;
+
+ TimeoutFuture(ListenableFuture<V> delegate) {
+ this.delegateRef = Preconditions.checkNotNull(delegate);
+ }
+
+ /** A runnable that is called when the delegate or the timer completes. */
+ private static final class Fire<V> implements Runnable {
+ @Nullable TimeoutFuture<V> timeoutFutureRef;
+
+ Fire(TimeoutFuture<V> timeoutFuture) {
+ this.timeoutFutureRef = timeoutFuture;
+ }
+
+ @Override public void run() {
+ // If either of these reads return null then we must be after a successful cancel
+ // or another call to this method.
+ TimeoutFuture<V> timeoutFuture = timeoutFutureRef;
+ if (timeoutFuture == null) {
+ return;
+ }
+ ListenableFuture<V> delegate = timeoutFuture.delegateRef;
+ if (delegate == null) {
+ return;
}
- @Override
- public void onFailure(Throwable t) {
- if (isCancelled()) {
- return;
- }
+ /*
+ * If we're about to complete the TimeoutFuture, we want to release our reference to it.
+ * Otherwise, we'll pin it (and its result) in memory until the timeout task is GCed. (The
+ * need to clear our reference to the TimeoutFuture is the reason we use a *static* nested
+ * class with a manual reference back to the "containing" class.)
+ *
+ * This has the nice-ish side effect of limiting reentrancy: run() calls
+ * timeoutFuture.setException() calls run(). That reentrancy would already be harmless,
+ * since timeoutFuture can be set (and delegate cancelled) only once. (And "set only once"
+ * is important for other reasons: run() can still be invoked concurrently in different
+ * threads, even with the above null checks.)
+ */
+ timeoutFutureRef = null;
+ if (delegate.isDone()) {
+ timeoutFuture.setFuture(delegate);
+ } else {
try {
- running = fallback.create(t);
- if (isCancelled()) { // in case cancel called in the meantime
- running.cancel(wasInterrupted());
- return;
- }
- addCallback(running, new FutureCallback<V>() {
- @Override
- public void onSuccess(V value) {
- set(value);
- }
-
- @Override
- public void onFailure(Throwable t) {
- if (running.isCancelled()) {
- cancel(false);
- } else {
- setException(t);
- }
- }
- }, directExecutor());
- } catch (Throwable e) {
- setException(e);
+ // TODO(lukes): this stack trace is particularly useless (all it does is point at the
+ // scheduledexecutorservice thread), consider eliminating it altogether?
+ timeoutFuture.setException(new TimeoutException("Future timed out: " + delegate));
+ } finally {
+ delegate.cancel(true);
}
}
- }, executor);
+ }
}
- @Override
- public boolean cancel(boolean mayInterruptIfRunning) {
- if (super.cancel(mayInterruptIfRunning)) {
- running.cancel(mayInterruptIfRunning);
- return true;
+ @Override void done() {
+ maybePropagateCancellation(delegateRef);
+
+ Future<?> localTimer = timer;
+ // Try to cancel the timer as an optimization
+ // timer may be null if this call to run was by the timer task since there is no
+ // happens-before edge between the assignment to timer and an execution of the timer task.
+ if (localTimer != null) {
+ localTimer.cancel(false);
}
- return false;
+
+ delegateRef = null;
+ timer = null;
}
}
@@ -523,28 +984,12 @@ public final class Futures {
* ListenableFuture<QueryResult> queryFuture =
* transform(rowKeyFuture, queryFunction);}</pre>
*
- * <p>Note: If the derived {@code Future} is slow or heavyweight to create
- * (whether the {@code Future} itself is slow or heavyweight to complete is
- * irrelevant), consider {@linkplain #transform(ListenableFuture,
- * AsyncFunction, Executor) supplying an executor}. If you do not supply an
- * executor, {@code transform} will use a
- * {@linkplain MoreExecutors#directExecutor direct executor}, which carries
- * some caveats for heavier operations. For example, the call to {@code
- * function.apply} may run on an unpredictable or undesirable thread:
- *
- * <ul>
- * <li>If the input {@code Future} is done at the time {@code transform} is
- * called, {@code transform} will call {@code function.apply} inline.
- * <li>If the input {@code Future} is not yet done, {@code transform} will
- * schedule {@code function.apply} to be run by the thread that completes the
- * input {@code Future}, which may be an internal system thread such as an
- * RPC network thread.
- * </ul>
- *
- * <p>Also note that, regardless of which thread executes the {@code
- * function.apply}, all other registered but unexecuted listeners are
- * prevented from running during its execution, even if those listeners are
- * to run in other executors.
+ * <p>This overload, which does not accept an executor, uses {@code
+ * directExecutor}, a dangerous choice in some cases. See the discussion in
+ * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation. The documentation's warnings about "lightweight listeners"
+ * refer here to the work done during {@code AsyncFunction.apply}, not to any
+ * work done to complete the returned {@code Future}.
*
* <p>The returned {@code Future} attempts to keep its cancellation state in
* sync with that of the input future and that of the future returned by the
@@ -559,13 +1004,15 @@ public final class Futures {
* @return A future that holds result of the function (if the input succeeded)
* or the original input's failure (if not)
* @since 11.0
+ * @deprecated These {@code AsyncFunction} overloads of {@code transform} are
+ * being renamed to {@code transformAsync}. (The {@code Function}
+ * overloads are keeping the "transform" name.) This method will be removed in Guava release
+ * 20.0.
*/
+ @Deprecated
public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
AsyncFunction<? super I, ? extends O> function) {
- ChainingListenableFuture<I, O> output =
- new ChainingListenableFuture<I, O>(function, input);
- input.addListener(output, directExecutor());
- return output;
+ return transformAsync(input, function);
}
/**
@@ -586,6 +1033,13 @@ public final class Futures {
* ListenableFuture<QueryResult> queryFuture =
* transform(rowKeyFuture, queryFunction, executor);}</pre>
*
+ * <p>When selecting an executor, note that {@code directExecutor} is
+ * dangerous in some cases. See the discussion in the {@link
+ * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+ * The documentation's warnings about "lightweight listeners" refer here to
+ * the work done during {@code AsyncFunction.apply}, not to any work done to
+ * complete the returned {@code Future}.
+ *
* <p>The returned {@code Future} attempts to keep its cancellation state in
* sync with that of the input future and that of the future returned by the
* chain function. That is, if the returned {@code Future} is cancelled, it
@@ -593,12 +1047,6 @@ public final class Futures {
* cancelled, the returned {@code Future} will receive a callback in which it
* will attempt to cancel itself.
*
- * <p>When the execution of {@code function.apply} is fast and lightweight
- * (though the {@code Future} it returns need not meet these criteria),
- * consider {@linkplain #transform(ListenableFuture, AsyncFunction) omitting
- * the executor} or explicitly specifying {@code directExecutor}.
- * However, be aware of the caveats documented in the link above.
- *
* @param input The future to transform
* @param function A function to transform the result of the input future
* to the result of the output future
@@ -606,39 +1054,133 @@ public final class Futures {
* @return A future that holds result of the function (if the input succeeded)
* or the original input's failure (if not)
* @since 11.0
+ * @deprecated These {@code AsyncFunction} overloads of {@code transform} are
+ * being renamed to {@code transformAsync}. (The {@code Function}
+ * overloads are keeping the "transform" name.) This method will be removed in Guava release
+ * 20.0.
*/
+ @Deprecated
public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
AsyncFunction<? super I, ? extends O> function,
Executor executor) {
+ return transformAsync(input, function, executor);
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is asynchronously derived from the result
+ * of the given {@code Future}. More precisely, the returned {@code Future} takes its result from
+ * a {@code Future} produced by applying the given {@code AsyncFunction} to the result of the
+ * original {@code Future}. Example:
+ *
+ * <pre> {@code
+ * ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+ * AsyncFunction<RowKey, QueryResult> queryFunction =
+ * new AsyncFunction<RowKey, QueryResult>() {
+ * public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+ * return dataService.read(rowKey);
+ * }
+ * };
+ * ListenableFuture<QueryResult> queryFuture =
+ * transformAsync(rowKeyFuture, queryFunction);}</pre>
+ *
+ * <p>This overload, which does not accept an executor, uses {@code directExecutor}, a dangerous
+ * choice in some cases. See the discussion in the {@link ListenableFuture#addListener
+ * ListenableFuture.addListener} documentation. The documentation's warnings about "lightweight
+ * listeners" refer here to the work done during {@code AsyncFunction.apply}, not to any work done
+ * to complete the returned {@code Future}.
+ *
+ * <p>The returned {@code Future} attempts to keep its cancellation state in sync with that of the
+ * input future and that of the future returned by the function. That is, if the returned {@code
+ * Future} is cancelled, it will attempt to cancel the other two, and if either of the other two
+ * is cancelled, the returned {@code Future} will receive a callback in which it will attempt to
+ * cancel itself.
+ *
+ * @param input The future to transform
+ * @param function A function to transform the result of the input future to the result of the
+ * output future
+ * @return A future that holds result of the function (if the input succeeded) or the original
+ * input's failure (if not)
+ * @since 19.0 (in 11.0 as {@code transform})
+ */
+ public static <I, O> ListenableFuture<O> transformAsync(
+ ListenableFuture<I> input, AsyncFunction<? super I, ? extends O> function) {
+ AsyncChainingFuture<I, O> output = new AsyncChainingFuture<I, O>(input, function);
+ input.addListener(output, directExecutor());
+ return output;
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is asynchronously derived from the result
+ * of the given {@code Future}. More precisely, the returned {@code Future} takes its result from
+ * a {@code Future} produced by applying the given {@code AsyncFunction} to the result of the
+ * original {@code Future}. Example:
+ *
+ * <pre> {@code
+ * ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+ * AsyncFunction<RowKey, QueryResult> queryFunction =
+ * new AsyncFunction<RowKey, QueryResult>() {
+ * public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+ * return dataService.read(rowKey);
+ * }
+ * };
+ * ListenableFuture<QueryResult> queryFuture =
+ * transformAsync(rowKeyFuture, queryFunction, executor);}</pre>
+ *
+ * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
+ * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation. The documentation's warnings about "lightweight listeners" refer here to the
+ * work done during {@code AsyncFunction.apply}, not to any work done to complete the returned
+ * {@code Future}.
+ *
+ * <p>The returned {@code Future} attempts to keep its cancellation state in sync with that of the
+ * input future and that of the future returned by the chain function. That is, if the returned
+ * {@code Future} is cancelled, it will attempt to cancel the other two, and if either of the
+ * other two is cancelled, the returned {@code Future} will receive a callback in which it will
+ * attempt to cancel itself.
+ *
+ * @param input The future to transform
+ * @param function A function to transform the result of the input future to the result of the
+ * output future
+ * @param executor Executor to run the function in.
+ * @return A future that holds result of the function (if the input succeeded) or the original
+ * input's failure (if not)
+ * @since 19.0 (in 11.0 as {@code transform})
+ */
+ public static <I, O> ListenableFuture<O> transformAsync(ListenableFuture<I> input,
+ AsyncFunction<? super I, ? extends O> function, Executor executor) {
checkNotNull(executor);
- ChainingListenableFuture<I, O> output =
- new ChainingListenableFuture<I, O>(function, input);
- input.addListener(rejectionPropagatingRunnable(output, output, executor), directExecutor());
+ AsyncChainingFuture<I, O> output = new AsyncChainingFuture<I, O>(input, function);
+ input.addListener(output, rejectionPropagatingExecutor(executor, output));
return output;
}
/**
- * Returns a Runnable that will invoke the delegate Runnable on the delegate executor, but if the
- * task is rejected, it will propagate that rejection to the output future.
+ * Returns an Executor that will propagate {@link RejectedExecutionException} from the delegate
+ * executor to the given {@code future}.
+ *
+ * <p>Note, the returned executor can only be used once.
*/
- private static Runnable rejectionPropagatingRunnable(
- final AbstractFuture<?> outputFuture,
- final Runnable delegateTask,
- final Executor delegateExecutor) {
- return new Runnable() {
- @Override public void run() {
- final AtomicBoolean thrownFromDelegate = new AtomicBoolean(true);
+ private static Executor rejectionPropagatingExecutor(
+ final Executor delegate, final AbstractFuture<?> future) {
+ checkNotNull(delegate);
+ if (delegate == directExecutor()) {
+ // directExecutor() cannot throw RejectedExecutionException
+ return delegate;
+ }
+ return new Executor() {
+ volatile boolean thrownFromDelegate = true;
+ @Override public void execute(final Runnable command) {
try {
- delegateExecutor.execute(new Runnable() {
+ delegate.execute(new Runnable() {
@Override public void run() {
- thrownFromDelegate.set(false);
- delegateTask.run();
+ thrownFromDelegate = false;
+ command.run();
}
});
} catch (RejectedExecutionException e) {
- if (thrownFromDelegate.get()) {
+ if (thrownFromDelegate) {
// wrap exception?
- outputFuture.setException(e);
+ future.setException(e);
}
// otherwise it must have been thrown from a transitive call and the delegate runnable
// should have handled it.
@@ -663,26 +1205,11 @@ public final class Futures {
* ListenableFuture<List<Row>> rowsFuture =
* transform(queryFuture, rowsFunction);}</pre>
*
- * <p>Note: If the transformation is slow or heavyweight, consider {@linkplain
- * #transform(ListenableFuture, Function, Executor) supplying an executor}.
- * If you do not supply an executor, {@code transform} will use an inline
- * executor, which carries some caveats for heavier operations. For example,
- * the call to {@code function.apply} may run on an unpredictable or
- * undesirable thread:
- *
- * <ul>
- * <li>If the input {@code Future} is done at the time {@code transform} is
- * called, {@code transform} will call {@code function.apply} inline.
- * <li>If the input {@code Future} is not yet done, {@code transform} will
- * schedule {@code function.apply} to be run by the thread that completes the
- * input {@code Future}, which may be an internal system thread such as an
- * RPC network thread.
- * </ul>
- *
- * <p>Also note that, regardless of which thread executes the {@code
- * function.apply}, all other registered but unexecuted listeners are
- * prevented from running during its execution, even if those listeners are
- * to run in other executors.
+ * <p>This overload, which does not accept an executor, uses {@code
+ * directExecutor}, a dangerous choice in some cases. See the discussion in
+ * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation. The documentation's warnings about "lightweight listeners"
+ * refer here to the work done during {@code Function.apply}.
*
* <p>The returned {@code Future} attempts to keep its cancellation state in
* sync with that of the input future. That is, if the returned {@code Future}
@@ -703,8 +1230,7 @@ public final class Futures {
public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
final Function<? super I, ? extends O> function) {
checkNotNull(function);
- ChainingListenableFuture<I, O> output =
- new ChainingListenableFuture<I, O>(asAsyncFunction(function), input);
+ ChainingFuture<I, O> output = new ChainingFuture<I, O>(input, function);
input.addListener(output, directExecutor());
return output;
}
@@ -725,6 +1251,12 @@ public final class Futures {
* ListenableFuture<List<Row>> rowsFuture =
* transform(queryFuture, rowsFunction, executor);}</pre>
*
+ * <p>When selecting an executor, note that {@code directExecutor} is
+ * dangerous in some cases. See the discussion in the {@link
+ * ListenableFuture#addListener ListenableFuture.addListener} documentation.
+ * The documentation's warnings about "lightweight listeners" refer here to
+ * the work done during {@code Function.apply}.
+ *
* <p>The returned {@code Future} attempts to keep its cancellation state in
* sync with that of the input future. That is, if the returned {@code Future}
* is cancelled, it will attempt to cancel the input, and if the input is
@@ -734,11 +1266,6 @@ public final class Futures {
* <p>An example use of this method is to convert a serializable object
* returned from an RPC into a POJO.
*
- * <p>When the transformation is fast and lightweight, consider {@linkplain
- * #transform(ListenableFuture, Function) omitting the executor} or
- * explicitly specifying {@code directExecutor}. However, be aware of the
- * caveats documented in the link above.
- *
* @param input The future to transform
* @param function A Function to transform the results of the provided future
* to the results of the returned future.
@@ -749,18 +1276,9 @@ public final class Futures {
public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
final Function<? super I, ? extends O> function, Executor executor) {
checkNotNull(function);
- return transform(input, asAsyncFunction(function), executor);
- }
-
- /** Wraps the given function as an AsyncFunction. */
- private static <I, O> AsyncFunction<I, O> asAsyncFunction(
- final Function<? super I, ? extends O> function) {
- return new AsyncFunction<I, O>() {
- @Override public ListenableFuture<O> apply(I input) {
- O output = function.apply(input);
- return immediateFuture(output);
- }
- };
+ ChainingFuture<I, O> output = new ChainingFuture<I, O>(input, function);
+ input.addListener(output, rejectionPropagatingExecutor(executor, output));
+ return output;
}
/**
@@ -786,6 +1304,8 @@ public final class Futures {
* @return A future that returns the result of the transformation.
* @since 10.0
*/
+ @GwtIncompatible("TODO")
+ @CheckReturnValue
public static <I, O> Future<O> lazyTransform(final Future<I> input,
final Function<? super I, ? extends O> function) {
checkNotNull(input);
@@ -848,49 +1368,32 @@ public final class Futures {
* href="http://code.google.com/p/guava-libraries/issues/detail?id=1548">we
* should remove the {@code UndeclaredThrowableException} special case</a>.
*/
- private static class ChainingListenableFuture<I, O>
- extends AbstractFuture<O> implements Runnable {
-
- private AsyncFunction<? super I, ? extends O> function;
- private ListenableFuture<? extends I> inputFuture;
- private volatile ListenableFuture<? extends O> outputFuture;
-
- private ChainingListenableFuture(
- AsyncFunction<? super I, ? extends O> function,
- ListenableFuture<? extends I> inputFuture) {
- this.function = checkNotNull(function);
+ private abstract static class AbstractChainingFuture<I, O, F>
+ extends AbstractFuture.TrustedFuture<O> implements Runnable {
+ // In theory, this field might not be visible to a cancel() call in certain circumstances. For
+ // details, see the comments on the fields of TimeoutFuture.
+ @Nullable ListenableFuture<? extends I> inputFuture;
+ @Nullable F function;
+
+ AbstractChainingFuture(ListenableFuture<? extends I> inputFuture, F function) {
this.inputFuture = checkNotNull(inputFuture);
+ this.function = checkNotNull(function);
}
@Override
- public boolean cancel(boolean mayInterruptIfRunning) {
- /*
- * Our additional cancellation work needs to occur even if
- * !mayInterruptIfRunning, so we can't move it into interruptTask().
- */
- if (super.cancel(mayInterruptIfRunning)) {
- // This should never block since only one thread is allowed to cancel
- // this Future.
- cancel(inputFuture, mayInterruptIfRunning);
- cancel(outputFuture, mayInterruptIfRunning);
- return true;
- }
- return false;
- }
-
- private void cancel(@Nullable Future<?> future,
- boolean mayInterruptIfRunning) {
- if (future != null) {
- future.cancel(mayInterruptIfRunning);
- }
- }
-
- @Override
- public void run() {
+ public final void run() {
try {
+ ListenableFuture<? extends I> localInputFuture = inputFuture;
+ F localFunction = function;
+ if (isCancelled() | localInputFuture == null | localFunction == null) {
+ return;
+ }
+ inputFuture = null;
+ function = null;
+
I sourceResult;
try {
- sourceResult = getUninterruptibly(inputFuture);
+ sourceResult = getUninterruptibly(localInputFuture);
} catch (CancellationException e) {
// Cancel this future and return.
// At this point, inputFuture is cancelled and outputFuture doesn't
@@ -902,35 +1405,7 @@ public final class Futures {
setException(e.getCause());
return;
}
-
- final ListenableFuture<? extends O> outputFuture = this.outputFuture =
- Preconditions.checkNotNull(function.apply(sourceResult),
- "AsyncFunction may not return null.");
- if (isCancelled()) {
- outputFuture.cancel(wasInterrupted());
- this.outputFuture = null;
- return;
- }
- outputFuture.addListener(new Runnable() {
- @Override
- public void run() {
- try {
- set(getUninterruptibly(outputFuture));
- } catch (CancellationException e) {
- // Cancel this future and return.
- // At this point, inputFuture and outputFuture are done, so the
- // value of mayInterruptIfRunning is irrelevant.
- cancel(false);
- return;
- } catch (ExecutionException e) {
- // Set the cause of the exception as this future's exception
- setException(e.getCause());
- } finally {
- // Don't pin inputs beyond completion
- ChainingListenableFuture.this.outputFuture = null;
- }
- }
- }, directExecutor());
+ doTransform(localFunction, sourceResult);
} catch (UndeclaredThrowableException e) {
// Set the cause of the exception as this future's exception
setException(e.getCause());
@@ -938,12 +1413,56 @@ public final class Futures {
// This exception is irrelevant in this thread, but useful for the
// client
setException(t);
- } finally {
- // Don't pin inputs beyond completion
- function = null;
- inputFuture = null;
}
}
+
+ /** Template method for subtypes to actually run the transform. */
+ abstract void doTransform(F function, I result) throws Exception;
+
+ @Override final void done() {
+ maybePropagateCancellation(inputFuture);
+ this.inputFuture = null;
+ this.function = null;
+ }
+ }
+
+ /**
+ * A {@link AbstractChainingFuture} that delegates to an {@link AsyncFunction} and
+ * {@link #setFuture(ListenableFuture)} to implement {@link #doTransform}.
+ */
+ private static final class AsyncChainingFuture<I, O>
+ extends AbstractChainingFuture<I, O, AsyncFunction<? super I, ? extends O>> {
+ AsyncChainingFuture(ListenableFuture<? extends I> inputFuture,
+ AsyncFunction<? super I, ? extends O> function) {
+ super(inputFuture, function);
+ }
+
+ @Override
+ void doTransform(AsyncFunction<? super I, ? extends O> function, I input) throws Exception {
+ ListenableFuture<? extends O> outputFuture = function.apply(input);
+ checkNotNull(outputFuture, "AsyncFunction.apply returned null instead of a Future. "
+ + "Did you mean to return immediateFuture(null)?");
+ setFuture(outputFuture);
+ }
+ }
+
+ /**
+ * A {@link AbstractChainingFuture} that delegates to a {@link Function} and
+ * {@link #set(Object)} to implement {@link #doTransform}.
+ */
+ private static final class ChainingFuture<I, O>
+ extends AbstractChainingFuture<I, O, Function<? super I, ? extends O>> {
+
+ ChainingFuture(ListenableFuture<? extends I> inputFuture,
+ Function<? super I, ? extends O> function) {
+ super(inputFuture, function);
+ }
+
+ @Override
+ void doTransform(Function<? super I, ? extends O> function, I input) {
+ // TODO(lukes): move the UndeclaredThrowable catch block here?
+ set(function.apply(input));
+ }
}
/**
@@ -968,9 +1487,10 @@ public final class Futures {
* @since 13.0
*/
@SuppressWarnings({"rawtypes", "unchecked"})
+ @CheckReturnValue
public static <V> ListenableFuture<V> dereference(
ListenableFuture<? extends ListenableFuture<? extends V>> nested) {
- return Futures.transform((ListenableFuture) nested, (AsyncFunction) DEREFERENCER);
+ return transformAsync((ListenableFuture) nested, (AsyncFunction) DEREFERENCER);
}
/**
@@ -1000,9 +1520,11 @@ public final class Futures {
* @since 10.0
*/
@Beta
+ @SafeVarargs
+ @CheckReturnValue
public static <V> ListenableFuture<List<V>> allAsList(
ListenableFuture<? extends V>... futures) {
- return listFuture(ImmutableList.copyOf(futures), true, directExecutor());
+ return new ListFuture<V>(ImmutableList.copyOf(futures), true);
}
/**
@@ -1022,60 +1544,10 @@ public final class Futures {
* @since 10.0
*/
@Beta
+ @CheckReturnValue
public static <V> ListenableFuture<List<V>> allAsList(
Iterable<? extends ListenableFuture<? extends V>> futures) {
- return listFuture(ImmutableList.copyOf(futures), true, directExecutor());
- }
-
- private static final class WrappedCombiner<T> implements Callable<T> {
- final Callable<T> delegate;
- CombinerFuture<T> outputFuture;
-
- WrappedCombiner(Callable<T> delegate) {
- this.delegate = checkNotNull(delegate);
- }
-
- @Override public T call() throws Exception {
- try {
- return delegate.call();
- } catch (ExecutionException e) {
- outputFuture.setException(e.getCause());
- } catch (CancellationException e) {
- outputFuture.cancel(false);
- }
- // at this point the return value doesn't matter since we already called setException or
- // cancel so the future is done.
- return null;
- }
- }
-
- private static final class CombinerFuture<V> extends ListenableFutureTask<V> {
- ImmutableList<ListenableFuture<?>> futures;
-
- CombinerFuture(Callable<V> callable, ImmutableList<ListenableFuture<?>> futures) {
- super(callable);
- this.futures = futures;
- }
-
- @Override public boolean cancel(boolean mayInterruptIfRunning) {
- ImmutableList<ListenableFuture<?>> futures = this.futures;
- if (super.cancel(mayInterruptIfRunning)) {
- for (ListenableFuture<?> future : futures) {
- future.cancel(mayInterruptIfRunning);
- }
- return true;
- }
- return false;
- }
-
- @Override protected void done() {
- super.done();
- futures = null;
- }
-
- @Override protected void setException(Throwable t) {
- super.setException(t);
- }
+ return new ListFuture<V>(ImmutableList.copyOf(futures), true);
}
/**
@@ -1086,6 +1558,8 @@ public final class Futures {
*
* @since 15.0
*/
+ @GwtIncompatible("TODO")
+ @CheckReturnValue
public static <V> ListenableFuture<V> nonCancellationPropagating(
ListenableFuture<V> future) {
return new NonCancellationPropagatingFuture<V>(future);
@@ -1094,23 +1568,15 @@ public final class Futures {
/**
* A wrapped future that does not propagate cancellation to its delegate.
*/
- private static class NonCancellationPropagatingFuture<V>
- extends AbstractFuture<V> {
+ @GwtIncompatible("TODO")
+ private static final class NonCancellationPropagatingFuture<V>
+ extends AbstractFuture.TrustedFuture<V> {
NonCancellationPropagatingFuture(final ListenableFuture<V> delegate) {
- checkNotNull(delegate);
- addCallback(delegate, new FutureCallback<V>() {
- @Override
- public void onSuccess(V result) {
- set(result);
- }
-
- @Override
- public void onFailure(Throwable t) {
- if (delegate.isCancelled()) {
- cancel(false);
- } else {
- setException(t);
- }
+ delegate.addListener(new Runnable() {
+ @Override public void run() {
+ // This prevents cancellation from propagating because we don't assign delegate until
+ // delegate is already done, so calling cancel() on it is a no-op.
+ setFuture(delegate);
}
}, directExecutor());
}
@@ -1132,9 +1598,11 @@ public final class Futures {
* @since 10.0
*/
@Beta
+ @SafeVarargs
+ @CheckReturnValue
public static <V> ListenableFuture<List<V>> successfulAsList(
ListenableFuture<? extends V>... futures) {
- return listFuture(ImmutableList.copyOf(futures), false, directExecutor());
+ return new ListFuture<V>(ImmutableList.copyOf(futures), false);
}
/**
@@ -1153,9 +1621,10 @@ public final class Futures {
* @since 10.0
*/
@Beta
+ @CheckReturnValue
public static <V> ListenableFuture<List<V>> successfulAsList(
Iterable<? extends ListenableFuture<? extends V>> futures) {
- return listFuture(ImmutableList.copyOf(futures), false, directExecutor());
+ return new ListFuture<V>(ImmutableList.copyOf(futures), false);
}
/**
@@ -1172,11 +1641,13 @@ public final class Futures {
* @since 17.0
*/
@Beta
+ @GwtIncompatible("TODO")
+ @CheckReturnValue
public static <T> ImmutableList<ListenableFuture<T>> inCompletionOrder(
Iterable<? extends ListenableFuture<? extends T>> futures) {
// A CLQ may be overkill here. We could save some pointers/memory by synchronizing on an
// ArrayDeque
- final ConcurrentLinkedQueue<AsyncSettableFuture<T>> delegates =
+ final ConcurrentLinkedQueue<SettableFuture<T>> delegates =
Queues.newConcurrentLinkedQueue();
ImmutableList.Builder<ListenableFuture<T>> listBuilder = ImmutableList.builder();
// Using SerializingExecutor here will ensure that each CompletionOrderListener executes
@@ -1191,7 +1662,7 @@ public final class Futures {
// a directExecutor listener on one of the output futures which is an antipattern anyway.
SerializingExecutor executor = new SerializingExecutor(directExecutor());
for (final ListenableFuture<? extends T> future : futures) {
- AsyncSettableFuture<T> delegate = AsyncSettableFuture.create();
+ SettableFuture<T> delegate = SettableFuture.create();
// Must make sure to add the delegate to the queue first in case the future is already done
delegates.add(delegate);
future.addListener(new Runnable() {
@@ -1225,26 +1696,10 @@ public final class Futures {
* }
* });}</pre>
*
- * <p>Note: If the callback is slow or heavyweight, consider {@linkplain
- * #addCallback(ListenableFuture, FutureCallback, Executor) supplying an
- * executor}. If you do not supply an executor, {@code addCallback} will use
- * a {@linkplain MoreExecutors#directExecutor direct executor}, which carries
- * some caveats for heavier operations. For example, the callback may run on
- * an unpredictable or undesirable thread:
- *
- * <ul>
- * <li>If the input {@code Future} is done at the time {@code addCallback} is
- * called, {@code addCallback} will execute the callback inline.
- * <li>If the input {@code Future} is not yet done, {@code addCallback} will
- * schedule the callback to be run by the thread that completes the input
- * {@code Future}, which may be an internal system thread such as an RPC
- * network thread.
- * </ul>
- *
- * <p>Also note that, regardless of which thread executes the callback, all
- * other registered but unexecuted listeners are prevented from running
- * during its execution, even if those listeners are to run in other
- * executors.
+ * <p>This overload, which does not accept an executor, uses {@code
+ * directExecutor}, a dangerous choice in some cases. See the discussion in
+ * the {@link ListenableFuture#addListener ListenableFuture.addListener}
+ * documentation.
*
* <p>For a more general interface to attach a completion listener to a
* {@code Future}, see {@link ListenableFuture#addListener addListener}.
@@ -1281,10 +1736,9 @@ public final class Futures {
* }
* }, e);}</pre>
*
- * <p>When the callback is fast and lightweight, consider {@linkplain
- * #addCallback(ListenableFuture, FutureCallback) omitting the executor} or
- * explicitly specifying {@code directExecutor}. However, be aware of the
- * caveats documented in the link above.
+ * <p>When selecting an executor, note that {@code directExecutor} is
+ * dangerous in some cases. See the discussion in the {@link
+ * ListenableFuture#addListener ListenableFuture.addListener} documentation.
*
* <p>For a more general interface to attach a completion listener to a
* {@code Future}, see {@link ListenableFuture#addListener addListener}.
@@ -1368,22 +1822,14 @@ public final class Futures {
* @throws IllegalArgumentException if {@code exceptionClass} extends {@code
* RuntimeException} or does not have a suitable constructor
* @since 10.0
+ * @deprecated Use {@link #getChecked(Future, Class)}. This method will be
+ * removed in Guava release 20.0.
*/
+ @Deprecated
+ @GwtIncompatible("reflection")
public static <V, X extends Exception> V get(
Future<V> future, Class<X> exceptionClass) throws X {
- checkNotNull(future);
- checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass),
- "Futures.get exception type (%s) must not be a RuntimeException",
- exceptionClass);
- try {
- return future.get();
- } catch (InterruptedException e) {
- currentThread().interrupt();
- throw newWithCause(exceptionClass, e);
- } catch (ExecutionException e) {
- wrapAndThrowExceptionOrError(e.getCause(), exceptionClass);
- throw new AssertionError();
- }
+ return getChecked(future, exceptionClass);
}
/**
@@ -1433,37 +1879,124 @@ public final class Futures {
* @throws IllegalArgumentException if {@code exceptionClass} extends {@code
* RuntimeException} or does not have a suitable constructor
* @since 10.0
+ * @deprecated Use {@link #getChecked(Future, Class, long, TimeUnit)}, noting
+ * the change in parameter order. This method will be removed in Guava
+ * release 20.0.
*/
+ @Deprecated
+ @GwtIncompatible("reflection")
public static <V, X extends Exception> V get(
Future<V> future, long timeout, TimeUnit unit, Class<X> exceptionClass)
throws X {
- checkNotNull(future);
- checkNotNull(unit);
- checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass),
- "Futures.get exception type (%s) must not be a RuntimeException",
- exceptionClass);
- try {
- return future.get(timeout, unit);
- } catch (InterruptedException e) {
- currentThread().interrupt();
- throw newWithCause(exceptionClass, e);
- } catch (TimeoutException e) {
- throw newWithCause(exceptionClass, e);
- } catch (ExecutionException e) {
- wrapAndThrowExceptionOrError(e.getCause(), exceptionClass);
- throw new AssertionError();
- }
+ return getChecked(future, exceptionClass, timeout, unit);
}
- private static <X extends Exception> void wrapAndThrowExceptionOrError(
- Throwable cause, Class<X> exceptionClass) throws X {
- if (cause instanceof Error) {
- throw new ExecutionError((Error) cause);
- }
- if (cause instanceof RuntimeException) {
- throw new UncheckedExecutionException(cause);
- }
- throw newWithCause(exceptionClass, cause);
+ /**
+ * Returns the result of {@link Future#get()}, converting most exceptions to a
+ * new instance of the given checked exception type. This reduces boilerplate
+ * for a common use of {@code Future} in which it is unnecessary to
+ * programmatically distinguish between exception types or to extract other
+ * information from the exception instance.
+ *
+ * <p>Exceptions from {@code Future.get} are treated as follows:
+ * <ul>
+ * <li>Any {@link ExecutionException} has its <i>cause</i> wrapped in an
+ * {@code X} if the cause is a checked exception, an {@link
+ * UncheckedExecutionException} if the cause is a {@code
+ * RuntimeException}, or an {@link ExecutionError} if the cause is an
+ * {@code Error}.
+ * <li>Any {@link InterruptedException} is wrapped in an {@code X} (after
+ * restoring the interrupt).
+ * <li>Any {@link CancellationException} is propagated untouched, as is any
+ * other {@link RuntimeException} (though {@code get} implementations are
+ * discouraged from throwing such exceptions).
+ * </ul>
+ *
+ * <p>The overall principle is to continue to treat every checked exception as a
+ * checked exception, every unchecked exception as an unchecked exception, and
+ * every error as an error. In addition, the cause of any {@code
+ * ExecutionException} is wrapped in order to ensure that the new stack trace
+ * matches that of the current thread.
+ *
+ * <p>Instances of {@code exceptionClass} are created by choosing an arbitrary
+ * public constructor that accepts zero or more arguments, all of type {@code
+ * String} or {@code Throwable} (preferring constructors with at least one
+ * {@code String}) and calling the constructor via reflection. If the
+ * exception did not already have a cause, one is set by calling {@link
+ * Throwable#initCause(Throwable)} on it. If no such constructor exists, an
+ * {@code IllegalArgumentException} is thrown.
+ *
+ * @throws X if {@code get} throws any checked exception except for an {@code
+ * ExecutionException} whose cause is not itself a checked exception
+ * @throws UncheckedExecutionException if {@code get} throws an {@code
+ * ExecutionException} with a {@code RuntimeException} as its cause
+ * @throws ExecutionError if {@code get} throws an {@code ExecutionException}
+ * with an {@code Error} as its cause
+ * @throws CancellationException if {@code get} throws a {@code
+ * CancellationException}
+ * @throws IllegalArgumentException if {@code exceptionClass} extends {@code
+ * RuntimeException} or does not have a suitable constructor
+ * @since 19.0 (in 10.0 as {@code get})
+ */
+ @GwtIncompatible("reflection")
+ public static <V, X extends Exception> V getChecked(
+ Future<V> future, Class<X> exceptionClass) throws X {
+ return FuturesGetChecked.getChecked(future, exceptionClass);
+ }
+
+ /**
+ * Returns the result of {@link Future#get(long, TimeUnit)}, converting most
+ * exceptions to a new instance of the given checked exception type. This
+ * reduces boilerplate for a common use of {@code Future} in which it is
+ * unnecessary to programmatically distinguish between exception types or to
+ * extract other information from the exception instance.
+ *
+ * <p>Exceptions from {@code Future.get} are treated as follows:
+ * <ul>
+ * <li>Any {@link ExecutionException} has its <i>cause</i> wrapped in an
+ * {@code X} if the cause is a checked exception, an {@link
+ * UncheckedExecutionException} if the cause is a {@code
+ * RuntimeException}, or an {@link ExecutionError} if the cause is an
+ * {@code Error}.
+ * <li>Any {@link InterruptedException} is wrapped in an {@code X} (after
+ * restoring the interrupt).
+ * <li>Any {@link TimeoutException} is wrapped in an {@code X}.
+ * <li>Any {@link CancellationException} is propagated untouched, as is any
+ * other {@link RuntimeException} (though {@code get} implementations are
+ * discouraged from throwing such exceptions).
+ * </ul>
+ *
+ * <p>The overall principle is to continue to treat every checked exception as a
+ * checked exception, every unchecked exception as an unchecked exception, and
+ * every error as an error. In addition, the cause of any {@code
+ * ExecutionException} is wrapped in order to ensure that the new stack trace
+ * matches that of the current thread.
+ *
+ * <p>Instances of {@code exceptionClass} are created by choosing an arbitrary
+ * public constructor that accepts zero or more arguments, all of type {@code
+ * String} or {@code Throwable} (preferring constructors with at least one
+ * {@code String}) and calling the constructor via reflection. If the
+ * exception did not already have a cause, one is set by calling {@link
+ * Throwable#initCause(Throwable)} on it. If no such constructor exists, an
+ * {@code IllegalArgumentException} is thrown.
+ *
+ * @throws X if {@code get} throws any checked exception except for an {@code
+ * ExecutionException} whose cause is not itself a checked exception
+ * @throws UncheckedExecutionException if {@code get} throws an {@code
+ * ExecutionException} with a {@code RuntimeException} as its cause
+ * @throws ExecutionError if {@code get} throws an {@code ExecutionException}
+ * with an {@code Error} as its cause
+ * @throws CancellationException if {@code get} throws a {@code
+ * CancellationException}
+ * @throws IllegalArgumentException if {@code exceptionClass} extends {@code
+ * RuntimeException} or does not have a suitable constructor
+ * @since 19.0 (in 10.0 as {@code get} and with different parameter order)
+ */
+ @GwtIncompatible("reflection")
+ public static <V, X extends Exception> V getChecked(
+ Future<V> future, Class<X> exceptionClass, long timeout, TimeUnit unit)
+ throws X {
+ return FuturesGetChecked.getChecked(future, exceptionClass, timeout, unit);
}
/**
@@ -1503,6 +2036,7 @@ public final class Futures {
* CancellationException}
* @since 10.0
*/
+ @GwtIncompatible("TODO")
public static <V> V getUnchecked(Future<V> future) {
checkNotNull(future);
try {
@@ -1513,6 +2047,7 @@ public final class Futures {
}
}
+ @GwtIncompatible("TODO")
private static void wrapAndThrowUnchecked(Throwable cause) {
if (cause instanceof Error) {
throw new ExecutionError((Error) cause);
@@ -1526,11 +2061,6 @@ public final class Futures {
}
/*
- * TODO(user): FutureChecker interface for these to be static methods on? If
- * so, refer to it in the (static-method) Futures.get documentation
- */
-
- /*
* Arguably we don't need a timed getUnchecked because any operation slow
* enough to require a timeout is heavyweight enough to throw a checked
* exception and therefore be inappropriate to use with getUnchecked. Further,
@@ -1539,259 +2069,40 @@ public final class Futures {
* wasn't thrown by the computation -- makes sense, and if we don't convert
* it, the user still has to write a try-catch block.
*
- * If you think you would use this method, let us know.
+ * If you think you would use this method, let us know. You might also also
+ * look into the Fork-Join framework:
+ * http://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html
*/
- private static <X extends Exception> X newWithCause(
- Class<X> exceptionClass, Throwable cause) {
- // getConstructors() guarantees this as long as we don't modify the array.
- @SuppressWarnings("unchecked")
- List<Constructor<X>> constructors =
- (List) Arrays.asList(exceptionClass.getConstructors());
- for (Constructor<X> constructor : preferringStrings(constructors)) {
- @Nullable X instance = newFromConstructor(constructor, cause);
- if (instance != null) {
- if (instance.getCause() == null) {
- instance.initCause(cause);
- }
- return instance;
- }
- }
- throw new IllegalArgumentException(
- "No appropriate constructor for exception of type " + exceptionClass
- + " in response to chained exception", cause);
- }
-
- private static <X extends Exception> List<Constructor<X>>
- preferringStrings(List<Constructor<X>> constructors) {
- return WITH_STRING_PARAM_FIRST.sortedCopy(constructors);
- }
-
- private static final Ordering<Constructor<?>> WITH_STRING_PARAM_FIRST =
- Ordering.natural().onResultOf(new Function<Constructor<?>, Boolean>() {
- @Override public Boolean apply(Constructor<?> input) {
- return asList(input.getParameterTypes()).contains(String.class);
- }
- }).reverse();
-
- @Nullable private static <X> X newFromConstructor(
- Constructor<X> constructor, Throwable cause) {
- Class<?>[] paramTypes = constructor.getParameterTypes();
- Object[] params = new Object[paramTypes.length];
- for (int i = 0; i < paramTypes.length; i++) {
- Class<?> paramType = paramTypes[i];
- if (paramType.equals(String.class)) {
- params[i] = cause.toString();
- } else if (paramType.equals(Throwable.class)) {
- params[i] = cause;
- } else {
- return null;
- }
- }
- try {
- return constructor.newInstance(params);
- } catch (IllegalArgumentException e) {
- return null;
- } catch (InstantiationException e) {
- return null;
- } catch (IllegalAccessException e) {
- return null;
- } catch (InvocationTargetException e) {
- return null;
- }
- }
-
- private interface FutureCombiner<V, C> {
- C combine(List<Optional<V>> values);
- }
-
- private static class CombinedFuture<V, C> extends AbstractFuture<C> {
- private static final Logger logger =
- Logger.getLogger(CombinedFuture.class.getName());
-
- ImmutableCollection<? extends ListenableFuture<? extends V>> futures;
- final boolean allMustSucceed;
- final AtomicInteger remaining;
- FutureCombiner<V, C> combiner;
- List<Optional<V>> values;
- final Object seenExceptionsLock = new Object();
- Set<Throwable> seenExceptions;
-
- CombinedFuture(
- ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
- boolean allMustSucceed, Executor listenerExecutor,
- FutureCombiner<V, C> combiner) {
- this.futures = futures;
- this.allMustSucceed = allMustSucceed;
- this.remaining = new AtomicInteger(futures.size());
- this.combiner = combiner;
- this.values = Lists.newArrayListWithCapacity(futures.size());
- init(listenerExecutor);
- }
-
- /**
- * Must be called at the end of the constructor.
- */
- protected void init(final Executor listenerExecutor) {
- // First, schedule cleanup to execute when the Future is done.
- addListener(new Runnable() {
- @Override
- public void run() {
- // Cancel all the component futures.
- if (CombinedFuture.this.isCancelled()) {
- for (ListenableFuture<?> future : CombinedFuture.this.futures) {
- future.cancel(CombinedFuture.this.wasInterrupted());
- }
- }
-
- // Let go of the memory held by other futures
- CombinedFuture.this.futures = null;
-
- // By now the values array has either been set as the Future's value,
- // or (in case of failure) is no longer useful.
- CombinedFuture.this.values = null;
-
- // The combiner may also hold state, so free that as well
- CombinedFuture.this.combiner = null;
- }
- }, directExecutor());
-
- // Now begin the "real" initialization.
-
- // Corner case: List is empty.
- if (futures.isEmpty()) {
- set(combiner.combine(ImmutableList.<Optional<V>>of()));
- return;
- }
-
- // Populate the results list with null initially.
- for (int i = 0; i < futures.size(); ++i) {
- values.add(null);
- }
-
- // Register a listener on each Future in the list to update
- // the state of this future.
- // Note that if all the futures on the list are done prior to completing
- // this loop, the last call to addListener() will callback to
- // setOneValue(), transitively call our cleanup listener, and set
- // this.futures to null.
- // This is not actually a problem, since the foreach only needs
- // this.futures to be non-null at the beginning of the loop.
- int i = 0;
- for (final ListenableFuture<? extends V> listenable : futures) {
- final int index = i++;
- listenable.addListener(new Runnable() {
- @Override
- public void run() {
- setOneValue(index, listenable);
- }
- }, listenerExecutor);
- }
- }
-
- /**
- * Fails this future with the given Throwable if {@link #allMustSucceed} is
- * true. Also, logs the throwable if it is an {@link Error} or if
- * {@link #allMustSucceed} is {@code true}, the throwable did not cause
- * this future to fail, and it is the first time we've seen that particular Throwable.
- */
- private void setExceptionAndMaybeLog(Throwable throwable) {
- boolean visibleFromOutputFuture = false;
- boolean firstTimeSeeingThisException = true;
- if (allMustSucceed) {
- // As soon as the first one fails, throw the exception up.
- // The result of all other inputs is then ignored.
- visibleFromOutputFuture = super.setException(throwable);
-
- synchronized (seenExceptionsLock) {
- if (seenExceptions == null) {
- seenExceptions = Sets.newHashSet();
- }
- firstTimeSeeingThisException = seenExceptions.add(throwable);
- }
- }
-
- if (throwable instanceof Error
- || (allMustSucceed && !visibleFromOutputFuture && firstTimeSeeingThisException)) {
- logger.log(Level.SEVERE, "input future failed.", throwable);
- }
+ /** Used for {@link #allAsList} and {@link #successfulAsList}. */
+ private static final class ListFuture<V> extends CollectionFuture<V, List<V>> {
+ ListFuture(ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
+ boolean allMustSucceed) {
+ init(new ListFutureRunningState(futures, allMustSucceed));
}
- /**
- * Sets the value at the given index to that of the given future.
- */
- private void setOneValue(int index, Future<? extends V> future) {
- List<Optional<V>> localValues = values;
- // TODO(user): This check appears to be redundant since values is
- // assigned null only after the future completes. However, values
- // is not volatile so it may be possible for us to observe the changes
- // to these two values in a different order... which I think is why
- // we need to check both. Clear up this craziness either by making
- // values volatile or proving that it doesn't need to be for some other
- // reason.
- if (isDone() || localValues == null) {
- // Some other future failed or has been cancelled, causing this one to
- // also be cancelled or have an exception set. This should only happen
- // if allMustSucceed is true or if the output itself has been
- // cancelled.
- checkState(allMustSucceed || isCancelled(),
- "Future was done before all dependencies completed");
+ private final class ListFutureRunningState extends CollectionFutureRunningState {
+ ListFutureRunningState(ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
+ boolean allMustSucceed) {
+ super(futures, allMustSucceed);
}
- try {
- checkState(future.isDone(),
- "Tried to set value from future which is not done");
- V returnValue = getUninterruptibly(future);
- if (localValues != null) {
- localValues.set(index, Optional.fromNullable(returnValue));
- }
- } catch (CancellationException e) {
- if (allMustSucceed) {
- // Set ourselves as cancelled. Let the input futures keep running
- // as some of them may be used elsewhere.
- cancel(false);
- }
- } catch (ExecutionException e) {
- setExceptionAndMaybeLog(e.getCause());
- } catch (Throwable t) {
- setExceptionAndMaybeLog(t);
- } finally {
- int newRemaining = remaining.decrementAndGet();
- checkState(newRemaining >= 0, "Less than 0 remaining futures");
- if (newRemaining == 0) {
- FutureCombiner<V, C> localCombiner = combiner;
- if (localCombiner != null && localValues != null) {
- set(localCombiner.combine(localValues));
- } else {
- checkState(isDone());
- }
+ @Override
+ public List<V> combine(List<Optional<V>> values) {
+ List<V> result = Lists.newArrayList();
+ for (Optional<V> element : values) {
+ result.add(element != null ? element.orNull() : null);
}
+ return Collections.unmodifiableList(result);
}
}
}
- /** Used for {@link #allAsList} and {@link #successfulAsList}. */
- private static <V> ListenableFuture<List<V>> listFuture(
- ImmutableList<ListenableFuture<? extends V>> futures,
- boolean allMustSucceed, Executor listenerExecutor) {
- return new CombinedFuture<V, List<V>>(
- futures, allMustSucceed, listenerExecutor,
- new FutureCombiner<V, List<V>>() {
- @Override
- public List<V> combine(List<Optional<V>> values) {
- List<V> result = Lists.newArrayList();
- for (Optional<V> element : values) {
- result.add(element != null ? element.orNull() : null);
- }
- return Collections.unmodifiableList(result);
- }
- });
- }
-
/**
* A checked future that uses a function to map from exceptions to the
* appropriate checked type.
*/
+ @GwtIncompatible("TODO")
private static class MappingCheckedFuture<V, X extends Exception> extends
AbstractCheckedFuture<V, X> {
diff --git a/guava/src/com/google/common/util/concurrent/FuturesGetChecked.java b/guava/src/com/google/common/util/concurrent/FuturesGetChecked.java
new file mode 100644
index 0000000..99441ea
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/FuturesGetChecked.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2006 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.Thread.currentThread;
+import static java.util.Arrays.asList;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.collect.Ordering;
+import com.google.j2objc.annotations.J2ObjCIncompatible;
+
+import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.annotation.Nullable;
+
+/**
+ * Static methods used to implement {@link Futures#getChecked(Future, Class)}.
+ */
+final class FuturesGetChecked {
+ static <V, X extends Exception> V getChecked(Future<V> future, Class<X> exceptionClass) throws X {
+ return getChecked(bestGetCheckedTypeValidator(), future, exceptionClass);
+ }
+
+ /**
+ * Implementation of {@link Futures#getChecked(Future, Class)}.
+ */
+ @VisibleForTesting
+ static <V, X extends Exception> V getChecked(
+ GetCheckedTypeValidator validator, Future<V> future, Class<X> exceptionClass) throws X {
+ validator.validateClass(exceptionClass);
+ try {
+ return future.get();
+ } catch (InterruptedException e) {
+ currentThread().interrupt();
+ throw newWithCause(exceptionClass, e);
+ } catch (ExecutionException e) {
+ wrapAndThrowExceptionOrError(e.getCause(), exceptionClass);
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * Implementation of {@link Futures#getChecked(Future, Class, long, TimeUnit)}.
+ */
+ static <V, X extends Exception> V getChecked(
+ Future<V> future, Class<X> exceptionClass, long timeout, TimeUnit unit) throws X {
+ // TODO(cpovirk): benchmark a version of this method that accepts a GetCheckedTypeValidator
+ bestGetCheckedTypeValidator().validateClass(exceptionClass);
+ try {
+ return future.get(timeout, unit);
+ } catch (InterruptedException e) {
+ currentThread().interrupt();
+ throw newWithCause(exceptionClass, e);
+ } catch (TimeoutException e) {
+ throw newWithCause(exceptionClass, e);
+ } catch (ExecutionException e) {
+ wrapAndThrowExceptionOrError(e.getCause(), exceptionClass);
+ throw new AssertionError();
+ }
+ }
+
+ @VisibleForTesting
+ interface GetCheckedTypeValidator {
+ void validateClass(Class<? extends Exception> exceptionClass);
+ }
+
+ private static GetCheckedTypeValidator bestGetCheckedTypeValidator() {
+ return GetCheckedTypeValidatorHolder.BEST_VALIDATOR;
+ }
+
+ @VisibleForTesting
+ static GetCheckedTypeValidator weakSetValidator() {
+ return GetCheckedTypeValidatorHolder.WeakSetValidator.INSTANCE;
+ }
+
+ @J2ObjCIncompatible // ClassValue
+ @VisibleForTesting
+ static GetCheckedTypeValidator classValueValidator() {
+ return GetCheckedTypeValidatorHolder.ClassValueValidator.INSTANCE;
+ }
+
+ /**
+ * Provides a check of whether an exception type is valid for use with
+ * {@link FuturesGetChecked#getChecked(Future, Class)}, possibly using caching.
+ *
+ * <p>Uses reflection to gracefully fall back to when certain implementations aren't available.
+ */
+ @VisibleForTesting
+ static class GetCheckedTypeValidatorHolder {
+ static final String CLASS_VALUE_VALIDATOR_NAME =
+ GetCheckedTypeValidatorHolder.class.getName() + "$ClassValueValidator";
+
+ static final GetCheckedTypeValidator BEST_VALIDATOR = getBestValidator();
+
+ @IgnoreJRERequirement // getChecked falls back to another implementation if necessary
+ @J2ObjCIncompatible // ClassValue
+ enum ClassValueValidator implements GetCheckedTypeValidator {
+ INSTANCE;
+
+ /*
+ * Static final fields are presumed to be fastest, based on our experience with
+ * UnsignedBytesBenchmark. TODO(cpovirk): benchmark this
+ */
+ private static final ClassValue<Boolean> isValidClass =
+ new ClassValue<Boolean>() {
+ @Override
+ protected Boolean computeValue(Class<?> type) {
+ checkExceptionClassValidity(type.asSubclass(Exception.class));
+ return true;
+ }
+ };
+
+ @Override
+ public void validateClass(Class<? extends Exception> exceptionClass) {
+ isValidClass.get(exceptionClass); // throws if invalid; returns safely (and caches) if valid
+ }
+ }
+
+ enum WeakSetValidator implements GetCheckedTypeValidator {
+ INSTANCE;
+
+ /*
+ * Static final fields are presumed to be fastest, based on our experience with
+ * UnsignedBytesBenchmark. TODO(cpovirk): benchmark this
+ */
+ /*
+ * A CopyOnWriteArraySet<WeakReference> is faster than a newSetFromMap of a MapMaker map with
+ * weakKeys() and concurrencyLevel(1), even up to at least 12 cached exception types.
+ */
+ private static final Set<WeakReference<Class<? extends Exception>>> validClasses =
+ new CopyOnWriteArraySet<WeakReference<Class<? extends Exception>>>();
+
+ @Override
+ public void validateClass(Class<? extends Exception> exceptionClass) {
+ for (WeakReference<Class<? extends Exception>> knownGood : validClasses) {
+ if (exceptionClass.equals(knownGood.get())) {
+ return;
+ }
+ // TODO(cpovirk): if reference has been cleared, remove it?
+ }
+ checkExceptionClassValidity(exceptionClass);
+
+ /*
+ * It's very unlikely that any loaded Futures class will see getChecked called with more
+ * than a handful of exceptions. But it seems prudent to set a cap on how many we'll cache.
+ * This avoids out-of-control memory consumption, and it keeps the cache from growing so
+ * large that doing the lookup is noticeably slower than redoing the work would be.
+ *
+ * Ideally we'd have a real eviction policy, but until we see a problem in practice, I hope
+ * that this will suffice. I have not even benchmarked with different size limits.
+ */
+ if (validClasses.size() > 1000) {
+ validClasses.clear();
+ }
+
+ validClasses.add(new WeakReference<Class<? extends Exception>>(exceptionClass));
+ }
+ }
+
+ /**
+ * Returns the ClassValue-using validator, or falls back to the "weak Set" implementation if
+ * unable to do so.
+ */
+ static GetCheckedTypeValidator getBestValidator() {
+ try {
+ Class<?> theClass = Class.forName(CLASS_VALUE_VALIDATOR_NAME);
+ return (GetCheckedTypeValidator) theClass.getEnumConstants()[0];
+ } catch (Throwable t) { // ensure we really catch *everything*
+ return weakSetValidator();
+ }
+ }
+ }
+
+ // TODO(cpovirk): change parameter order to match other helper methods (Class, Throwable)?
+ private static <X extends Exception> void wrapAndThrowExceptionOrError(
+ Throwable cause, Class<X> exceptionClass) throws X {
+ if (cause instanceof Error) {
+ throw new ExecutionError((Error) cause);
+ }
+ if (cause instanceof RuntimeException) {
+ throw new UncheckedExecutionException(cause);
+ }
+ throw newWithCause(exceptionClass, cause);
+ }
+
+ /*
+ * TODO(user): FutureChecker interface for these to be static methods on? If
+ * so, refer to it in the (static-method) Futures.getChecked documentation
+ */
+
+ private static boolean hasConstructorUsableByGetChecked(
+ Class<? extends Exception> exceptionClass) {
+ try {
+ newWithCause(exceptionClass, new Exception());
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ private static <X extends Exception> X newWithCause(Class<X> exceptionClass, Throwable cause) {
+ // getConstructors() guarantees this as long as we don't modify the array.
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ List<Constructor<X>> constructors = (List) Arrays.asList(exceptionClass.getConstructors());
+ for (Constructor<X> constructor : preferringStrings(constructors)) {
+ @Nullable X instance = newFromConstructor(constructor, cause);
+ if (instance != null) {
+ if (instance.getCause() == null) {
+ instance.initCause(cause);
+ }
+ return instance;
+ }
+ }
+ throw new IllegalArgumentException(
+ "No appropriate constructor for exception of type "
+ + exceptionClass
+ + " in response to chained exception",
+ cause);
+ }
+
+ private static <X extends Exception> List<Constructor<X>> preferringStrings(
+ List<Constructor<X>> constructors) {
+ return WITH_STRING_PARAM_FIRST.sortedCopy(constructors);
+ }
+
+ private static final Ordering<Constructor<?>> WITH_STRING_PARAM_FIRST =
+ Ordering.natural()
+ .onResultOf(
+ new Function<Constructor<?>, Boolean>() {
+ @Override
+ public Boolean apply(Constructor<?> input) {
+ return asList(input.getParameterTypes()).contains(String.class);
+ }
+ })
+ .reverse();
+
+ @Nullable
+ private static <X> X newFromConstructor(Constructor<X> constructor, Throwable cause) {
+ Class<?>[] paramTypes = constructor.getParameterTypes();
+ Object[] params = new Object[paramTypes.length];
+ for (int i = 0; i < paramTypes.length; i++) {
+ Class<?> paramType = paramTypes[i];
+ if (paramType.equals(String.class)) {
+ params[i] = cause.toString();
+ } else if (paramType.equals(Throwable.class)) {
+ params[i] = cause;
+ } else {
+ return null;
+ }
+ }
+ try {
+ return constructor.newInstance(params);
+ } catch (IllegalArgumentException e) {
+ return null;
+ } catch (InstantiationException e) {
+ return null;
+ } catch (IllegalAccessException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ return null;
+ }
+ }
+
+ @VisibleForTesting
+ static boolean isCheckedException(Class<? extends Exception> type) {
+ return !RuntimeException.class.isAssignableFrom(type);
+ }
+
+ @VisibleForTesting
+ static void checkExceptionClassValidity(Class<? extends Exception> exceptionClass) {
+ checkArgument(
+ isCheckedException(exceptionClass),
+ "Futures.getChecked exception type (%s) must not be a RuntimeException",
+ exceptionClass);
+ checkArgument(
+ hasConstructorUsableByGetChecked(exceptionClass),
+ "Futures.getChecked exception type (%s) must be an accessible class with an accessible "
+ + "constructor whose parameters (if any) must be of type String and/or Throwable",
+ exceptionClass);
+ }
+
+ private FuturesGetChecked() {}
+}
diff --git a/guava/src/com/google/common/util/concurrent/GwtFuturesCatchingSpecialization.java b/guava/src/com/google/common/util/concurrent/GwtFuturesCatchingSpecialization.java
new file mode 100644
index 0000000..7b08339
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/GwtFuturesCatchingSpecialization.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2006 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * Hidden superclass of {@link Futures} that provides us a place to declare special GWT versions of
+ * the {@link Futures#catching(ListenableFuture, Class, com.google.common.base.Function)
+ * Futures.catching} family of methods. Those versions have slightly different signatures.
+ */
+ at GwtCompatible(emulated = true)
+abstract class GwtFuturesCatchingSpecialization {
+ /*
+ * This server copy of the class is empty. The corresponding GWT copy contains alternative
+ * versions of catching() and catchingAsync() with slightly different signatures from the ones
+ * found in Futures.java.
+ */
+}
diff --git a/guava/src/com/google/common/util/concurrent/InterruptibleTask.java b/guava/src/com/google/common/util/concurrent/InterruptibleTask.java
new file mode 100644
index 0000000..36c7167
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/InterruptibleTask.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater;
+
+import com.google.common.annotations.GwtCompatible;
+
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+ at GwtCompatible(emulated = true)
+abstract class InterruptibleTask implements Runnable {
+ private static final AtomicReferenceFieldUpdater<InterruptibleTask, Thread> RUNNER =
+ newUpdater(InterruptibleTask.class, Thread.class, "runner");
+
+ // These two fields are used to interrupt running tasks. The thread executing the task
+ // publishes itself to the 'runner' field and the thread interrupting sets 'doneInterrupting'
+ // when it has finished interrupting.
+ private volatile Thread runner;
+ private volatile boolean doneInterrupting;
+
+ @Override public final void run() {
+ if (!RUNNER.compareAndSet(this, null, Thread.currentThread())) {
+ return; // someone else has run or is running.
+ }
+ try {
+ runInterruptibly();
+ } finally {
+ if (wasInterrupted()) {
+ // We were interrupted, it is possible that the interrupted bit hasn't been set yet. Wait
+ // for the interrupting thread to set 'doneInterrupting' to true. See interruptTask().
+ // We want to wait so that we don't interrupt the _next_ thing run on the thread.
+ // Note. We don't reset the interrupted bit, just wait for it to be set.
+ // If this is a thread pool thread, the thread pool will reset it for us. Otherwise, the
+ // interrupted bit may have been intended for something else, so don't clear it.
+ while (!doneInterrupting) {
+ Thread.yield();
+ }
+ }
+ }
+ }
+
+ abstract void runInterruptibly();
+
+ abstract boolean wasInterrupted();
+
+ final void interruptTask() {
+ // interruptTask is guaranteed to be called at most once and if runner is non-null when that
+ // happens then it must have been the first thread that entered run(). So there is no risk
+ // that we are interrupting the wrong thread.
+ Thread currentRunner = runner;
+ if (currentRunner != null) {
+ currentRunner.interrupt();
+ }
+ doneInterrupting = true;
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java b/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java
index 099d0b7..00612d1 100644
--- a/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java
+++ b/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java
@@ -157,6 +157,7 @@ public final class JdkFutureAdapters {
return;
}
+ // TODO(lukes): handle RejectedExecutionException
adapterExecutor.execute(new Runnable() {
@Override
public void run() {
@@ -168,11 +169,9 @@ public final class JdkFutureAdapters {
* instead of using listenInPoolThread.
*/
getUninterruptibly(delegate);
- } catch (Error e) {
- throw e;
} catch (Throwable e) {
- // ExecutionException / CancellationException / RuntimeException
- // The task is done, run the listeners.
+ // ExecutionException / CancellationException / RuntimeException / Error
+ // The task is presumably done, run the listeners.
}
executionList.execute();
}
diff --git a/guava/src/com/google/common/util/concurrent/ListenableFuture.java b/guava/src/com/google/common/util/concurrent/ListenableFuture.java
index 7d169ec..9f839a1 100644
--- a/guava/src/com/google/common/util/concurrent/ListenableFuture.java
+++ b/guava/src/com/google/common/util/concurrent/ListenableFuture.java
@@ -16,6 +16,8 @@
package com.google.common.util.concurrent;
+import com.google.common.annotations.GwtCompatible;
+
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
@@ -30,7 +32,7 @@ import java.util.concurrent.RejectedExecutionException;
* immediately.
*
* <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained">
+ * "https://github.com/google/guava/wiki/ListenableFutureExplained">
* {@code ListenableFuture}</a>.
*
* <h3>Purpose</h3>
@@ -60,9 +62,10 @@ import java.util.concurrent.RejectedExecutionException;
* <h3>How to get an instance</h3>
*
* <p>Developers are encouraged to return {@code ListenableFuture} from their
- * methods so that users can take advantages of the utilities built atop the
- * class. The way that they will create {@code ListenableFuture} instances
- * depends on how they currently create {@code Future} instances:
+ * methods so that users can take advantages of the {@linkplain Futures
+ * utilities built atop the class}. The way that they will create {@code
+ * ListenableFuture} instances depends on how they currently create {@code
+ * Future} instances:
* <ul>
* <li>If they are returned from an {@code ExecutorService}, convert that
* service to a {@link ListeningExecutorService}, usually by calling {@link
@@ -83,6 +86,7 @@ import java.util.concurrent.RejectedExecutionException;
* @author Nishant Thakkar
* @since 1.0
*/
+ at GwtCompatible
public interface ListenableFuture<V> extends Future<V> {
/**
* Registers a listener to be {@linkplain Executor#execute(Runnable) run} on
@@ -101,29 +105,30 @@ public interface ListenableFuture<V> extends Future<V> {
* logged.
*
* <p>Note: For fast, lightweight listeners that would be safe to execute in
- * any thread, consider {@link MoreExecutors#directExecutor}. For heavier
- * listeners, {@code directExecutor()} carries some caveats. For
- * example, the listener may run on an unpredictable or undesirable thread:
+ * any thread, consider {@link MoreExecutors#directExecutor}. Otherwise, avoid
+ * it. Heavyweight {@code directExecutor} listeners can cause problems, and
+ * these problems can be difficult to reproduce because they depend on timing.
+ * For example:
*
* <ul>
- * <li>If this {@code Future} is done at the time {@code addListener} is
- * called, {@code addListener} will execute the listener inline.
- * <li>If this {@code Future} is not yet done, {@code addListener} will
- * schedule the listener to be run by the thread that completes this {@code
- * Future}, which may be an internal system thread such as an RPC network
- * thread.
+ * <li>The listener may be executed by the caller of {@code addListener}. That
+ * caller may be a UI thread or other latency-sensitive thread. This can harm
+ * UI responsiveness.
+ * <li>The listener may be executed by the thread that completes this {@code
+ * Future}. That thread may be an internal system thread such as an RPC
+ * network thread. Blocking that thread may stall progress of the whole
+ * system. It may even cause a deadlock.
+ * <li>The listener may delay other listeners, even listeners that are not
+ * themselves {@code directExecutor} listeners.
* </ul>
*
- * <p>Also note that, regardless of which thread executes the
- * {@code directExecutor()} listener, all other registered but unexecuted
- * listeners are prevented from running during its execution, even if those
- * listeners are to run in other executors.
- *
* <p>This is the most general listener interface. For common operations
- * performed using listeners, see {@link
- * com.google.common.util.concurrent.Futures}. For a simplified but general
- * listener interface, see {@link
- * com.google.common.util.concurrent.Futures#addCallback addCallback()}.
+ * performed using listeners, see {@link Futures}. For a simplified but
+ * general listener interface, see {@link Futures#addCallback addCallback()}.
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to adding a listener
+ * <a href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5">
+ * <i>happen-before</i></a> its execution begins, perhaps in another thread.
*
* @param listener the listener to run when the computation is complete
* @param executor the executor to run the listener in
diff --git a/guava/src/com/google/common/util/concurrent/Monitor.java b/guava/src/com/google/common/util/concurrent/Monitor.java
index 2e15ea8..b242725 100644
--- a/guava/src/com/google/common/util/concurrent/Monitor.java
+++ b/guava/src/com/google/common/util/concurrent/Monitor.java
@@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.base.Throwables;
+import com.google.j2objc.annotations.Weak;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
@@ -276,6 +277,19 @@ public final class Monitor {
* participating in the signal-passing game.
*/
+ /*
+ * Timeout handling is intricate, especially given our ambitious goals:
+ * - Avoid underflow and overflow of timeout values when specified timeouts are close to
+ * Long.MIN_VALUE or Long.MAX_VALUE.
+ * - Favor responding to interrupts over timeouts.
+ * - System.nanoTime() is expensive enough that we want to call it the minimum required number of
+ * times, typically once before invoking a blocking method. This often requires keeping track
+ * of the first time in a method that nanoTime() has been invoked, for which the special value
+ * 0L is reserved to mean "uninitialized". If timeout is non-positive, then nanoTime need
+ * never be called.
+ * - Keep behavior of fair and non-fair instances consistent.
+ */
+
/**
* A boolean condition for which a thread may wait. A {@code Guard} is associated with a single
* {@code Monitor}. The monitor may check the guard at arbitrary times from any thread occupying
@@ -290,7 +304,7 @@ public final class Monitor {
@Beta
public abstract static class Guard {
- final Monitor monitor;
+ @Weak final Monitor monitor;
final Condition condition;
@GuardedBy("monitor.lock")
@@ -359,6 +373,8 @@ public final class Monitor {
/**
* Enters this monitor. Blocks indefinitely, but may be interrupted.
+ *
+ * @throws InterruptedException if interrupted while waiting
*/
public void enterInterruptibly() throws InterruptedException {
lock.lockInterruptibly();
@@ -370,20 +386,20 @@ public final class Monitor {
* @return whether the monitor was entered
*/
public boolean enter(long time, TimeUnit unit) {
- long timeoutNanos = unit.toNanos(time);
+ final long timeoutNanos = toSafeNanos(time, unit);
final ReentrantLock lock = this.lock;
if (!fair && lock.tryLock()) {
return true;
}
- long deadline = System.nanoTime() + timeoutNanos;
boolean interrupted = Thread.interrupted();
try {
- while (true) {
+ final long startTime = System.nanoTime();
+ for (long remainingNanos = timeoutNanos;;) {
try {
- return lock.tryLock(timeoutNanos, TimeUnit.NANOSECONDS);
+ return lock.tryLock(remainingNanos, TimeUnit.NANOSECONDS);
} catch (InterruptedException interrupt) {
interrupted = true;
- timeoutNanos = deadline - System.nanoTime();
+ remainingNanos = remainingNanos(startTime, timeoutNanos);
}
}
} finally {
@@ -397,6 +413,7 @@ public final class Monitor {
* Enters this monitor. Blocks at most the given time, and may be interrupted.
*
* @return whether the monitor was entered
+ * @throws InterruptedException if interrupted while waiting
*/
public boolean enterInterruptibly(long time, TimeUnit unit) throws InterruptedException {
return lock.tryLock(time, unit);
@@ -415,6 +432,8 @@ public final class Monitor {
/**
* Enters this monitor when the guard is satisfied. Blocks indefinitely, but may be interrupted.
+ *
+ * @throws InterruptedException if interrupted while waiting
*/
public void enterWhen(Guard guard) throws InterruptedException {
if (guard.monitor != this) {
@@ -466,27 +485,43 @@ public final class Monitor {
* the time to acquire the lock and the time to wait for the guard to be satisfied, and may be
* interrupted.
*
- * @return whether the monitor was entered with the guard satisfied
+ * @return whether the monitor was entered, which guarantees that the guard is now satisfied
+ * @throws InterruptedException if interrupted while waiting
*/
public boolean enterWhen(Guard guard, long time, TimeUnit unit) throws InterruptedException {
- long timeoutNanos = unit.toNanos(time);
+ final long timeoutNanos = toSafeNanos(time, unit);
if (guard.monitor != this) {
throw new IllegalMonitorStateException();
}
final ReentrantLock lock = this.lock;
boolean reentrant = lock.isHeldByCurrentThread();
- if (fair || !lock.tryLock()) {
- long deadline = System.nanoTime() + timeoutNanos;
+ long startTime = 0L;
+
+ locked: {
+ if (!fair) {
+ // Check interrupt status to get behavior consistent with fair case.
+ if (Thread.interrupted()) {
+ throw new InterruptedException();
+ }
+ if (lock.tryLock()) {
+ break locked;
+ }
+ }
+ startTime = initNanoTime(timeoutNanos);
if (!lock.tryLock(time, unit)) {
return false;
}
- timeoutNanos = deadline - System.nanoTime();
}
boolean satisfied = false;
boolean threw = true;
try {
- satisfied = guard.isSatisfied() || awaitNanos(guard, timeoutNanos, reentrant);
+ satisfied = guard.isSatisfied()
+ || awaitNanos(guard,
+ (startTime == 0L)
+ ? timeoutNanos
+ : remainingNanos(startTime, timeoutNanos),
+ reentrant);
threw = false;
return satisfied;
} finally {
@@ -507,43 +542,54 @@ public final class Monitor {
* Enters this monitor when the guard is satisfied. Blocks at most the given time, including
* both the time to acquire the lock and the time to wait for the guard to be satisfied.
*
- * @return whether the monitor was entered with the guard satisfied
+ * @return whether the monitor was entered, which guarantees that the guard is now satisfied
*/
public boolean enterWhenUninterruptibly(Guard guard, long time, TimeUnit unit) {
- long timeoutNanos = unit.toNanos(time);
+ final long timeoutNanos = toSafeNanos(time, unit);
if (guard.monitor != this) {
throw new IllegalMonitorStateException();
}
final ReentrantLock lock = this.lock;
- long deadline = System.nanoTime() + timeoutNanos;
+ long startTime = 0L;
boolean signalBeforeWaiting = lock.isHeldByCurrentThread();
boolean interrupted = Thread.interrupted();
try {
if (fair || !lock.tryLock()) {
- boolean locked = false;
- do {
+ startTime = initNanoTime(timeoutNanos);
+ for (long remainingNanos = timeoutNanos;;) {
try {
- locked = lock.tryLock(timeoutNanos, TimeUnit.NANOSECONDS);
- if (!locked) {
+ if (lock.tryLock(remainingNanos, TimeUnit.NANOSECONDS)) {
+ break;
+ } else {
return false;
}
} catch (InterruptedException interrupt) {
interrupted = true;
+ remainingNanos = remainingNanos(startTime, timeoutNanos);
}
- timeoutNanos = deadline - System.nanoTime();
- } while (!locked);
+ }
}
boolean satisfied = false;
try {
while (true) {
try {
- return satisfied = guard.isSatisfied()
- || awaitNanos(guard, timeoutNanos, signalBeforeWaiting);
+ if (guard.isSatisfied()) {
+ satisfied = true;
+ } else {
+ final long remainingNanos;
+ if (startTime == 0L) {
+ startTime = initNanoTime(timeoutNanos);
+ remainingNanos = timeoutNanos;
+ } else {
+ remainingNanos = remainingNanos(startTime, timeoutNanos);
+ }
+ satisfied = awaitNanos(guard, remainingNanos, signalBeforeWaiting);
+ }
+ return satisfied;
} catch (InterruptedException interrupt) {
interrupted = true;
signalBeforeWaiting = false;
- timeoutNanos = deadline - System.nanoTime();
}
}
} finally {
@@ -562,7 +608,7 @@ public final class Monitor {
* Enters this monitor if the guard is satisfied. Blocks indefinitely acquiring the lock, but
* does not wait for the guard to be satisfied.
*
- * @return whether the monitor was entered with the guard satisfied
+ * @return whether the monitor was entered, which guarantees that the guard is now satisfied
*/
public boolean enterIf(Guard guard) {
if (guard.monitor != this) {
@@ -585,7 +631,8 @@ public final class Monitor {
* Enters this monitor if the guard is satisfied. Blocks indefinitely acquiring the lock, but does
* not wait for the guard to be satisfied, and may be interrupted.
*
- * @return whether the monitor was entered with the guard satisfied
+ * @return whether the monitor was entered, which guarantees that the guard is now satisfied
+ * @throws InterruptedException if interrupted while waiting
*/
public boolean enterIfInterruptibly(Guard guard) throws InterruptedException {
if (guard.monitor != this) {
@@ -608,7 +655,7 @@ public final class Monitor {
* Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
* lock, but does not wait for the guard to be satisfied.
*
- * @return whether the monitor was entered with the guard satisfied
+ * @return whether the monitor was entered, which guarantees that the guard is now satisfied
*/
public boolean enterIf(Guard guard, long time, TimeUnit unit) {
if (guard.monitor != this) {
@@ -632,7 +679,7 @@ public final class Monitor {
* Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
* lock, but does not wait for the guard to be satisfied, and may be interrupted.
*
- * @return whether the monitor was entered with the guard satisfied
+ * @return whether the monitor was entered, which guarantees that the guard is now satisfied
*/
public boolean enterIfInterruptibly(Guard guard, long time, TimeUnit unit)
throws InterruptedException {
@@ -660,7 +707,7 @@ public final class Monitor {
*
* <p><b>Note:</b> This method disregards the fairness setting of this monitor.
*
- * @return whether the monitor was entered with the guard satisfied
+ * @return whether the monitor was entered, which guarantees that the guard is now satisfied
*/
public boolean tryEnterIf(Guard guard) {
if (guard.monitor != this) {
@@ -684,6 +731,8 @@ public final class Monitor {
/**
* Waits for the guard to be satisfied. Waits indefinitely, but may be interrupted. May be
* called only by a thread currently occupying this monitor.
+ *
+ * @throws InterruptedException if interrupted while waiting
*/
public void waitFor(Guard guard) throws InterruptedException {
if (!((guard.monitor == this) & lock.isHeldByCurrentThread())) {
@@ -712,13 +761,20 @@ public final class Monitor {
* May be called only by a thread currently occupying this monitor.
*
* @return whether the guard is now satisfied
+ * @throws InterruptedException if interrupted while waiting
*/
public boolean waitFor(Guard guard, long time, TimeUnit unit) throws InterruptedException {
- long timeoutNanos = unit.toNanos(time);
+ final long timeoutNanos = toSafeNanos(time, unit);
if (!((guard.monitor == this) & lock.isHeldByCurrentThread())) {
throw new IllegalMonitorStateException();
}
- return guard.isSatisfied() || awaitNanos(guard, timeoutNanos, true);
+ if (guard.isSatisfied()) {
+ return true;
+ }
+ if (Thread.interrupted()) {
+ throw new InterruptedException();
+ }
+ return awaitNanos(guard, timeoutNanos, true);
}
/**
@@ -728,7 +784,7 @@ public final class Monitor {
* @return whether the guard is now satisfied
*/
public boolean waitForUninterruptibly(Guard guard, long time, TimeUnit unit) {
- long timeoutNanos = unit.toNanos(time);
+ final long timeoutNanos = toSafeNanos(time, unit);
if (!((guard.monitor == this) & lock.isHeldByCurrentThread())) {
throw new IllegalMonitorStateException();
}
@@ -736,19 +792,19 @@ public final class Monitor {
return true;
}
boolean signalBeforeWaiting = true;
- long deadline = System.nanoTime() + timeoutNanos;
+ final long startTime = initNanoTime(timeoutNanos);
boolean interrupted = Thread.interrupted();
try {
- while (true) {
+ for (long remainingNanos = timeoutNanos;;) {
try {
- return awaitNanos(guard, timeoutNanos, signalBeforeWaiting);
+ return awaitNanos(guard, remainingNanos, signalBeforeWaiting);
} catch (InterruptedException interrupt) {
interrupted = true;
if (guard.isSatisfied()) {
return true;
}
signalBeforeWaiting = false;
- timeoutNanos = deadline - System.nanoTime();
+ remainingNanos = remainingNanos(startTime, timeoutNanos);
}
}
} finally {
@@ -863,6 +919,46 @@ public final class Monitor {
}
/**
+ * Returns unit.toNanos(time), additionally ensuring the returned value is not at risk of
+ * overflowing or underflowing, by bounding the value between 0 and (Long.MAX_VALUE / 4) * 3.
+ * Actually waiting for more than 219 years is not supported!
+ */
+ private static long toSafeNanos(long time, TimeUnit unit) {
+ long timeoutNanos = unit.toNanos(time);
+ return (timeoutNanos <= 0L) ? 0L
+ : (timeoutNanos > (Long.MAX_VALUE / 4) * 3) ? (Long.MAX_VALUE / 4) * 3
+ : timeoutNanos;
+ }
+
+ /**
+ * Returns System.nanoTime() unless the timeout has already elapsed.
+ * Returns 0L if and only if the timeout has already elapsed.
+ */
+ private static long initNanoTime(long timeoutNanos) {
+ if (timeoutNanos <= 0L) {
+ return 0L;
+ } else {
+ long startTime = System.nanoTime();
+ return (startTime == 0L) ? 1L : startTime;
+ }
+ }
+
+ /**
+ * Returns the remaining nanos until the given timeout, or 0L if the timeout has already elapsed.
+ * Caller must have previously sanitized timeoutNanos using toSafeNanos.
+ */
+ private static long remainingNanos(long startTime, long timeoutNanos) {
+ // assert timeoutNanos == 0L || startTime != 0L;
+
+ // TODO : NOT CORRECT, BUT TESTS PASS ANYWAYS!
+ // if (true) return timeoutNanos;
+ // ONLY 2 TESTS FAIL IF WE DO:
+ // if (true) return 0;
+
+ return (timeoutNanos <= 0L) ? 0L : timeoutNanos - (System.nanoTime() - startTime);
+ }
+
+ /**
* Signals some other thread waiting on a satisfied guard, if one exists.
*
* We manage calls to this method carefully, to signal only when necessary, but never losing a
@@ -980,7 +1076,7 @@ public final class Monitor {
*/
@GuardedBy("lock")
- private void await(Guard guard, boolean signalBeforeWaiting)
+ private void await(Guard guard, boolean signalBeforeWaiting)
throws InterruptedException {
if (signalBeforeWaiting) {
signalNextWaiter();
@@ -1010,23 +1106,32 @@ public final class Monitor {
}
}
+ /**
+ * Caller should check before calling that guard is not satisfied.
+ */
@GuardedBy("lock")
private boolean awaitNanos(Guard guard, long nanos, boolean signalBeforeWaiting)
throws InterruptedException {
- if (signalBeforeWaiting) {
- signalNextWaiter();
- }
- beginWaitingFor(guard);
+ boolean firstTime = true;
try {
do {
- if (nanos < 0L) {
+ if (nanos <= 0L) {
return false;
}
+ if (firstTime) {
+ if (signalBeforeWaiting) {
+ signalNextWaiter();
+ }
+ beginWaitingFor(guard);
+ firstTime = false;
+ }
nanos = guard.condition.awaitNanos(nanos);
} while (!guard.isSatisfied());
return true;
} finally {
- endWaitingFor(guard);
+ if (!firstTime) {
+ endWaitingFor(guard);
+ }
}
}
diff --git a/guava/src/com/google/common/util/concurrent/MoreExecutors.java b/guava/src/com/google/common/util/concurrent/MoreExecutors.java
index e0b1045..6549e57 100644
--- a/guava/src/com/google/common/util/concurrent/MoreExecutors.java
+++ b/guava/src/com/google/common/util/concurrent/MoreExecutors.java
@@ -20,6 +20,8 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
@@ -49,9 +51,8 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
+
+import javax.annotation.concurrent.GuardedBy;
/**
* Factory and utility methods for {@link java.util.concurrent.Executor}, {@link
@@ -62,6 +63,7 @@ import java.util.concurrent.locks.ReentrantLock;
* @author Justin Mahoney
* @since 3.0
*/
+ at GwtCompatible(emulated = true)
public final class MoreExecutors {
private MoreExecutors() {}
@@ -81,6 +83,7 @@ public final class MoreExecutors {
* @return an unmodifiable version of the input which will not hang the JVM
*/
@Beta
+ @GwtIncompatible("TODO")
public static ExecutorService getExitingExecutorService(
ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) {
return new Application()
@@ -104,6 +107,7 @@ public final class MoreExecutors {
* @return an unmodifiable version of the input which will not hang the JVM
*/
@Beta
+ @GwtIncompatible("TODO")
public static ScheduledExecutorService getExitingScheduledExecutorService(
ScheduledThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) {
return new Application()
@@ -122,6 +126,7 @@ public final class MoreExecutors {
* @param timeUnit unit of time for the time parameter
*/
@Beta
+ @GwtIncompatible("TODO")
public static void addDelayedShutdownHook(
ExecutorService service, long terminationTimeout, TimeUnit timeUnit) {
new Application()
@@ -144,6 +149,7 @@ public final class MoreExecutors {
* @return an unmodifiable version of the input which will not hang the JVM
*/
@Beta
+ @GwtIncompatible("concurrency")
public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor) {
return new Application().getExitingExecutorService(executor);
}
@@ -164,13 +170,16 @@ public final class MoreExecutors {
* @return an unmodifiable version of the input which will not hang the JVM
*/
@Beta
+ @GwtIncompatible("TODO")
public static ScheduledExecutorService getExitingScheduledExecutorService(
ScheduledThreadPoolExecutor executor) {
return new Application().getExitingScheduledExecutorService(executor);
}
/** Represents the current application to register shutdown hooks. */
- @VisibleForTesting static class Application {
+ @GwtIncompatible("TODO")
+ @VisibleForTesting
+ static class Application {
final ExecutorService getExitingExecutorService(
ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) {
@@ -224,6 +233,7 @@ public final class MoreExecutors {
}
}
+ @GwtIncompatible("TODO")
private static void useDaemonThreadFactory(ThreadPoolExecutor executor) {
executor.setThreadFactory(new ThreadFactoryBuilder()
.setDaemon(true)
@@ -233,7 +243,7 @@ public final class MoreExecutors {
/**
* Creates an executor service that runs each task in the thread
- * that invokes {@code execute/submit}, as in {@link CallerRunsPolicy} This
+ * that invokes {@code execute/submit}, as in {@link CallerRunsPolicy}. This
* applies both to individually submitted tasks and to collections of tasks
* submitted via {@code invokeAll} or {@code invokeAny}. In the latter case,
* tasks will run serially on the calling thread. Tasks are run to
@@ -261,26 +271,27 @@ public final class MoreExecutors {
* RejectedExecutionException, although a subset of the tasks may already
* have been executed.
*
- * @since 10.0 (<a href="http://code.google.com/p/guava-libraries/wiki/Compatibility"
+ * @since 10.0 (<a href="https://github.com/google/guava/wiki/Compatibility"
* >mostly source-compatible</a> since 3.0)
* @deprecated Use {@link #directExecutor()} if you only require an {@link Executor} and
- * {@link #newDirectExecutorService()} if you need a {@link ListeningExecutorService}.
+ * {@link #newDirectExecutorService()} if you need a {@link ListeningExecutorService}. This
+ * method will be removed in August 2016.
*/
- @Deprecated public static ListeningExecutorService sameThreadExecutor() {
+ @Deprecated
+ @GwtIncompatible("TODO")
+ public static ListeningExecutorService sameThreadExecutor() {
return new DirectExecutorService();
}
// See sameThreadExecutor javadoc for behavioral notes.
- private static class DirectExecutorService
+ @GwtIncompatible("TODO")
+ private static final class DirectExecutorService
extends AbstractListeningExecutorService {
/**
* Lock used whenever accessing the state variables
- * (runningTasks, shutdown, terminationCondition) of the executor
+ * (runningTasks, shutdown) of the executor
*/
- private final Lock lock = new ReentrantLock();
-
- /** Signaled after the executor is shutdown and running tasks are done */
- private final Condition termination = lock.newCondition();
+ private final Object lock = new Object();
/*
* Conceptually, these two variables describe the executor being in
@@ -289,8 +300,8 @@ public final class MoreExecutors {
* - Shutdown: runningTasks > 0 and shutdown == true
* - Terminated: runningTasks == 0 and shutdown == true
*/
- private int runningTasks = 0;
- private boolean shutdown = false;
+ @GuardedBy("lock") private int runningTasks = 0;
+ @GuardedBy("lock") private boolean shutdown = false;
@Override
public void execute(Runnable command) {
@@ -304,21 +315,18 @@ public final class MoreExecutors {
@Override
public boolean isShutdown() {
- lock.lock();
- try {
+ synchronized (lock) {
return shutdown;
- } finally {
- lock.unlock();
}
}
@Override
public void shutdown() {
- lock.lock();
- try {
+ synchronized (lock) {
shutdown = true;
- } finally {
- lock.unlock();
+ if (runningTasks == 0) {
+ lock.notifyAll();
+ }
}
}
@@ -331,11 +339,8 @@ public final class MoreExecutors {
@Override
public boolean isTerminated() {
- lock.lock();
- try {
+ synchronized (lock) {
return shutdown && runningTasks == 0;
- } finally {
- lock.unlock();
}
}
@@ -343,19 +348,18 @@ public final class MoreExecutors {
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
- lock.lock();
- try {
+ synchronized (lock) {
for (;;) {
- if (isTerminated()) {
+ if (shutdown && runningTasks == 0) {
return true;
} else if (nanos <= 0) {
return false;
} else {
- nanos = termination.awaitNanos(nanos);
+ long now = System.nanoTime();
+ TimeUnit.NANOSECONDS.timedWait(lock, nanos);
+ nanos -= System.nanoTime() - now; // subtract the actual time we waited
}
}
- } finally {
- lock.unlock();
}
}
@@ -367,14 +371,11 @@ public final class MoreExecutors {
* shutdown
*/
private void startTask() {
- lock.lock();
- try {
- if (isShutdown()) {
+ synchronized (lock) {
+ if (shutdown) {
throw new RejectedExecutionException("Executor already shutdown");
}
runningTasks++;
- } finally {
- lock.unlock();
}
}
@@ -382,14 +383,11 @@ public final class MoreExecutors {
* Decrements the running task count.
*/
private void endTask() {
- lock.lock();
- try {
- runningTasks--;
- if (isTerminated()) {
- termination.signalAll();
+ synchronized (lock) {
+ int numRunning = --runningTasks;
+ if (numRunning == 0) {
+ lock.notifyAll();
}
- } finally {
- lock.unlock();
}
}
}
@@ -426,6 +424,7 @@ public final class MoreExecutors {
*
* @since 18.0 (present as MoreExecutors.sameThreadExecutor() since 10.0)
*/
+ @GwtIncompatible("TODO")
public static ListeningExecutorService newDirectExecutorService() {
return new DirectExecutorService();
}
@@ -456,6 +455,10 @@ public final class MoreExecutors {
@Override public void execute(Runnable command) {
command.run();
}
+
+ @Override public String toString() {
+ return "MoreExecutors.directExecutor()";
+ }
}
/**
@@ -476,6 +479,7 @@ public final class MoreExecutors {
*
* @since 10.0
*/
+ @GwtIncompatible("TODO")
public static ListeningExecutorService listeningDecorator(
ExecutorService delegate) {
return (delegate instanceof ListeningExecutorService)
@@ -504,6 +508,7 @@ public final class MoreExecutors {
*
* @since 10.0
*/
+ @GwtIncompatible("TODO")
public static ListeningScheduledExecutorService listeningDecorator(
ScheduledExecutorService delegate) {
return (delegate instanceof ListeningScheduledExecutorService)
@@ -511,6 +516,7 @@ public final class MoreExecutors {
: new ScheduledListeningDecorator(delegate);
}
+ @GwtIncompatible("TODO")
private static class ListeningDecorator
extends AbstractListeningExecutorService {
private final ExecutorService delegate;
@@ -520,38 +526,39 @@ public final class MoreExecutors {
}
@Override
- public boolean awaitTermination(long timeout, TimeUnit unit)
+ public final boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
return delegate.awaitTermination(timeout, unit);
}
@Override
- public boolean isShutdown() {
+ public final boolean isShutdown() {
return delegate.isShutdown();
}
@Override
- public boolean isTerminated() {
+ public final boolean isTerminated() {
return delegate.isTerminated();
}
@Override
- public void shutdown() {
+ public final void shutdown() {
delegate.shutdown();
}
@Override
- public List<Runnable> shutdownNow() {
+ public final List<Runnable> shutdownNow() {
return delegate.shutdownNow();
}
@Override
- public void execute(Runnable command) {
+ public final void execute(Runnable command) {
delegate.execute(command);
}
}
- private static class ScheduledListeningDecorator
+ @GwtIncompatible("TODO")
+ private static final class ScheduledListeningDecorator
extends ListeningDecorator implements ListeningScheduledExecutorService {
@SuppressWarnings("hiding")
final ScheduledExecutorService delegate;
@@ -564,8 +571,8 @@ public final class MoreExecutors {
@Override
public ListenableScheduledFuture<?> schedule(
Runnable command, long delay, TimeUnit unit) {
- ListenableFutureTask<Void> task =
- ListenableFutureTask.create(command, null);
+ TrustedListenableFutureTask<Void> task =
+ TrustedListenableFutureTask.create(command, null);
ScheduledFuture<?> scheduled = delegate.schedule(task, delay, unit);
return new ListenableScheduledTask<Void>(task, scheduled);
}
@@ -573,7 +580,7 @@ public final class MoreExecutors {
@Override
public <V> ListenableScheduledFuture<V> schedule(
Callable<V> callable, long delay, TimeUnit unit) {
- ListenableFutureTask<V> task = ListenableFutureTask.create(callable);
+ TrustedListenableFutureTask<V> task = TrustedListenableFutureTask.create(callable);
ScheduledFuture<?> scheduled = delegate.schedule(task, delay, unit);
return new ListenableScheduledTask<V>(task, scheduled);
}
@@ -634,6 +641,7 @@ public final class MoreExecutors {
}
}
+ @GwtIncompatible("TODO")
private static final class NeverSuccessfulListenableFutureTask
extends AbstractFuture<Void>
implements Runnable {
@@ -742,6 +750,7 @@ public final class MoreExecutors {
/**
* Submits the task and adds a listener that adds the future to {@code queue} when it completes.
*/
+ @GwtIncompatible("TODO")
private static <T> ListenableFuture<T> submitAndAddQueueListener(
ListeningExecutorService executorService, Callable<T> task,
final BlockingQueue<Future<T>> queue) {
@@ -763,6 +772,7 @@ public final class MoreExecutors {
* @since 14.0
*/
@Beta
+ @GwtIncompatible("concurrency")
public static ThreadFactory platformThreadFactory() {
if (!isAppEngine()) {
return Executors.defaultThreadFactory();
@@ -782,6 +792,7 @@ public final class MoreExecutors {
}
}
+ @GwtIncompatible("TODO")
private static boolean isAppEngine() {
if (System.getProperty("com.google.appengine.runtime.environment") == null) {
return false;
@@ -810,6 +821,7 @@ public final class MoreExecutors {
* Creates a thread using {@link #platformThreadFactory}, and sets its name to {@code name}
* unless changing the name is forbidden by the security manager.
*/
+ @GwtIncompatible("concurrency")
static Thread newThread(String name, Runnable runnable) {
checkNotNull(name);
checkNotNull(runnable);
@@ -822,8 +834,8 @@ public final class MoreExecutors {
return result;
}
- // TODO(user): provide overloads for ListeningExecutorService? ListeningScheduledExecutorService?
- // TODO(user): provide overloads that take constant strings? Function<Runnable, String>s to
+ // TODO(lukes): provide overloads for ListeningExecutorService? ListeningScheduledExecutorService?
+ // TODO(lukes): provide overloads that take constant strings? Function<Runnable, String>s to
// calculate names?
/**
@@ -837,6 +849,7 @@ public final class MoreExecutors {
* @param executor The executor to decorate
* @param nameSupplier The source of names for each task
*/
+ @GwtIncompatible("concurrency")
static Executor renamingDecorator(final Executor executor, final Supplier<String> nameSupplier) {
checkNotNull(executor);
checkNotNull(nameSupplier);
@@ -863,6 +876,7 @@ public final class MoreExecutors {
* @param service The executor to decorate
* @param nameSupplier The source of names for each task
*/
+ @GwtIncompatible("concurrency")
static ExecutorService renamingDecorator(final ExecutorService service,
final Supplier<String> nameSupplier) {
checkNotNull(service);
@@ -893,6 +907,7 @@ public final class MoreExecutors {
* @param service The executor to decorate
* @param nameSupplier The source of names for each task
*/
+ @GwtIncompatible("concurrency")
static ScheduledExecutorService renamingDecorator(final ScheduledExecutorService service,
final Supplier<String> nameSupplier) {
checkNotNull(service);
@@ -924,19 +939,18 @@ public final class MoreExecutors {
* <li>waits for the other half of the specified timeout.
* </ol>
*
- * <p>If, at any step of the process, the given executor is terminated or the calling thread is
- * interrupted, the method calls {@link ExecutorService#shutdownNow()}, cancelling
- * pending tasks and interrupting running tasks.
+ * <p>If, at any step of the process, the calling thread is interrupted, the method calls {@link
+ * ExecutorService#shutdownNow()} and returns.
*
* @param service the {@code ExecutorService} to shut down
* @param timeout the maximum time to wait for the {@code ExecutorService} to terminate
* @param unit the time unit of the timeout argument
- * @return {@code true} if the pool was terminated successfully, {@code false} if the
- * {@code ExecutorService} could not terminate <b>or</b> the thread running this method
- * is interrupted while waiting for the {@code ExecutorService} to terminate
+ * @return {@code true} if the {@code ExecutorService} was terminated successfully, {@code false}
+ * the call timed out or was interrupted
* @since 17.0
*/
@Beta
+ @GwtIncompatible("concurrency")
public static boolean shutdownAndAwaitTermination(
ExecutorService service, long timeout, TimeUnit unit) {
checkNotNull(unit);
diff --git a/guava/src/com/google/common/collect/FilteredMultimap.java b/guava/src/com/google/common/util/concurrent/Platform.java
similarity index 59%
copy from guava/src/com/google/common/collect/FilteredMultimap.java
copy to guava/src/com/google/common/util/concurrent/Platform.java
index e97cfdb..017a08a 100644
--- a/guava/src/com/google/common/collect/FilteredMultimap.java
+++ b/guava/src/com/google/common/util/concurrent/Platform.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Guava Authors
+ * Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,21 +14,21 @@
* limitations under the License.
*/
-package com.google.common.collect;
+package com.google.common.util.concurrent;
import com.google.common.annotations.GwtCompatible;
-import com.google.common.base.Predicate;
-import java.util.Map.Entry;
+import javax.annotation.Nullable;
/**
- * An interface for all filtered multimap types.
- *
- * @author Louis Wasserman
+ * Methods factored out so that they can be emulated differently in GWT.
*/
- at GwtCompatible
-interface FilteredMultimap<K, V> extends Multimap<K, V> {
- Multimap<K, V> unfiltered();
+ at GwtCompatible(emulated = true)
+final class Platform {
+ static boolean isInstanceOfThrowableClass(
+ @Nullable Throwable t, Class<? extends Throwable> expectedClass) {
+ return expectedClass.isInstance(t);
+ }
- Predicate<? super Entry<K, V>> entryPredicate();
+ private Platform() {}
}
diff --git a/guava/src/com/google/common/util/concurrent/RateLimiter.java b/guava/src/com/google/common/util/concurrent/RateLimiter.java
index 74290b0..76b7e73 100644
--- a/guava/src/com/google/common/util/concurrent/RateLimiter.java
+++ b/guava/src/com/google/common/util/concurrent/RateLimiter.java
@@ -28,6 +28,7 @@ import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.SmoothRateLimiter.SmoothBursty;
import com.google.common.util.concurrent.SmoothRateLimiter.SmoothWarmingUp;
+import java.util.Locale;
import java.util.concurrent.TimeUnit;
import javax.annotation.concurrent.ThreadSafe;
@@ -41,7 +42,7 @@ import javax.annotation.concurrent.ThreadSafe;
* physical or logical resource is accessed. This is in contrast to {@link
* java.util.concurrent.Semaphore} which restricts the number of concurrent
* accesses instead of the rate (note though that concurrency and rate are closely related,
- * e.g. see <a href="http://en.wikipedia.org/wiki/Little's_law">Little's Law</a>).
+ * e.g. see <a href="http://en.wikipedia.org/wiki/Little%27s_law">Little's Law</a>).
*
* <p>A {@code RateLimiter} is defined primarily by the rate at which permits
* are issued. Absent additional configuration, permits will be distributed at a
@@ -77,7 +78,7 @@ import javax.annotation.concurrent.ThreadSafe;
*}</pre>
*
* <p>It is important to note that the number of permits requested <i>never</i>
- * affect the throttling of the request itself (an invocation to {@code acquire(1)}
+ * affects the throttling of the request itself (an invocation to {@code acquire(1)}
* and an invocation to {@code acquire(1000)} will result in exactly the same throttling, if any),
* but it affects the throttling of the <i>next</i> request. I.e., if an expensive task
* arrives at an idle RateLimiter, it will be granted immediately, but it is the <i>next</i>
@@ -166,13 +167,15 @@ public abstract class RateLimiter {
*/
public static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit) {
checkArgument(warmupPeriod >= 0, "warmupPeriod must not be negative: %s", warmupPeriod);
- return create(SleepingStopwatch.createFromSystemTimer(), permitsPerSecond, warmupPeriod, unit);
+ return create(SleepingStopwatch.createFromSystemTimer(), permitsPerSecond, warmupPeriod, unit,
+ 3.0);
}
@VisibleForTesting
static RateLimiter create(
- SleepingStopwatch stopwatch, double permitsPerSecond, long warmupPeriod, TimeUnit unit) {
- RateLimiter rateLimiter = new SmoothWarmingUp(stopwatch, warmupPeriod, unit);
+ SleepingStopwatch stopwatch, double permitsPerSecond, long warmupPeriod, TimeUnit unit,
+ double coldFactor) {
+ RateLimiter rateLimiter = new SmoothWarmingUp(stopwatch, warmupPeriod, unit, coldFactor);
rateLimiter.setRate(permitsPerSecond);
return rateLimiter;
}
@@ -395,7 +398,7 @@ public abstract class RateLimiter {
@Override
public String toString() {
- return String.format("RateLimiter[stableRate=%3.1fqps]", getRate());
+ return String.format(Locale.ROOT, "RateLimiter[stableRate=%3.1fqps]", getRate());
}
@VisibleForTesting
diff --git a/guava/src/com/google/common/util/concurrent/SerializingExecutor.java b/guava/src/com/google/common/util/concurrent/SerializingExecutor.java
index 47524eb..5407edf 100644
--- a/guava/src/com/google/common/util/concurrent/SerializingExecutor.java
+++ b/guava/src/com/google/common/util/concurrent/SerializingExecutor.java
@@ -19,7 +19,7 @@ package com.google.common.util.concurrent;
import com.google.common.base.Preconditions;
import java.util.ArrayDeque;
-import java.util.Queue;
+import java.util.Deque;
import java.util.concurrent.Executor;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -31,17 +31,20 @@ import javax.annotation.concurrent.GuardedBy;
* using the provided Executor, and serially such that no two will ever
* be running at the same time.
*
- * TODO(user): The tasks are given to the underlying executor as a single
- * task, which means the semantics of the executor may be changed, e.g. the
- * executor may have an afterExecute method that runs after every task
+ * <p>Tasks submitted to {@link #execute(Runnable)} are executed in FIFO order.
*
- * TODO(user): What happens in case of shutdown or shutdownNow? Should
- * TaskRunner check for interruption?
+ * <p>Tasks can also be prepended to the queue to be executed in LIFO order before any other
+ * submitted tasks. Primarily intended for the currently executing task to be able to schedule a
+ * continuation task.
*
- * TODO(user): It would be nice to provide a handle to individual task
- * results using Future. Maybe SerializingExecutorService?
+ * <p>Execution on the queue can be {@linkplain #suspend suspended}, e.g. while waiting for an RPC,
+ * and execution can be {@linkplain #resume resumed} later.
*
- * @author JJ Furman
+ * <p>The execution of tasks is done by one thread as long as there are tasks left in the queue and
+ * execution has not been suspended. (Even if one task is {@linkplain Thread#interrupt interrupted},
+ * execution of subsequent tasks continues.) {@code RuntimeException}s thrown by tasks are simply
+ * logged and the executor keeps trucking. If an {@code Error} is thrown, the error will propagate
+ * and execution will stop until it is restarted by external calls.
*/
final class SerializingExecutor implements Executor {
private static final Logger log =
@@ -50,117 +53,144 @@ final class SerializingExecutor implements Executor {
/** Underlying executor that all submitted Runnable objects are run on. */
private final Executor executor;
- /** A list of Runnables to be run in order. */
@GuardedBy("internalLock")
- private final Queue<Runnable> waitQueue = new ArrayDeque<Runnable>();
-
- /**
- * We explicitly keep track of if the TaskRunner is currently scheduled to
- * run. If it isn't, we start it. We can't just use
- * waitQueue.isEmpty() as a proxy because we need to ensure that only one
- * Runnable submitted is running at a time so even if waitQueue is empty
- * the isThreadScheduled isn't set to false until after the Runnable is
- * finished.
- */
+ private final Deque<Runnable> queue = new ArrayDeque<Runnable>();
@GuardedBy("internalLock")
- private boolean isThreadScheduled = false;
+ private boolean isWorkerRunning = false;
+ @GuardedBy("internalLock")
+ private int suspensions = 0;
- /** The object that actually runs the Runnables submitted, reused. */
- private final TaskRunner taskRunner = new TaskRunner();
+ private final Object internalLock = new Object();
+
+ public SerializingExecutor(Executor executor) {
+ this.executor = Preconditions.checkNotNull(executor);
+ }
/**
- * Creates a SerializingExecutor, running tasks using {@code executor}.
+ * Adds a task to the queue and makes sure a worker thread is running, unless the queue has been
+ * suspended.
*
- * @param executor Executor in which tasks should be run. Must not be null.
+ * <p>If this method throws, e.g. a {@code RejectedExecutionException} from the delegate executor,
+ * execution of tasks will stop until a call to this method or to {@link #resume()} is
+ * made.
*/
- public SerializingExecutor(Executor executor) {
- Preconditions.checkNotNull(executor, "'executor' must not be null.");
- this.executor = executor;
+ public void execute(Runnable task) {
+ synchronized (internalLock) {
+ queue.add(task);
+ }
+ startQueueWorker();
}
- private final Object internalLock = new Object() {
- @Override public String toString() {
- return "SerializingExecutor lock: " + super.toString();
+ /**
+ * Prepends a task to the front of the queue and makes sure a worker thread is running, unless the
+ * queue has been suspended.
+ */
+ public void executeFirst(Runnable task) {
+ synchronized (internalLock) {
+ queue.addFirst(task);
+ }
+ startQueueWorker();
+ }
+
+ /**
+ * Suspends the running of tasks until {@link #resume()} is called. This can be called multiple
+ * times to increase the suspensions count and execution will not continue until {@link #resume}
+ * has been called the same number of times as {@code suspend} has been.
+ *
+ * <p>Any task that has already been pulled off the queue for execution will be completed
+ * before execution is suspended.
+ */
+ public void suspend() {
+ synchronized (internalLock) {
+ suspensions++;
}
- };
+ }
/**
- * Runs the given runnable strictly after all Runnables that were submitted
- * before it, and using the {@code executor} passed to the constructor. .
+ * Continue execution of tasks after a call to {@link #suspend()}. More accurately, decreases the
+ * suspension counter, as has been incremented by calls to {@link #suspend}, and resumes execution
+ * if the suspension counter is zero.
+ *
+ * <p>If this method throws, e.g. a {@code RejectedExecutionException} from the delegate executor,
+ * execution of tasks will stop until a call to this method or to {@link #execute(Runnable)} or
+ * {@link #executeFirst(Runnable)} is made.
+ *
+ * @throws java.lang.IllegalStateException if this executor is not suspended.
*/
- @Override
- public void execute(Runnable r) {
- Preconditions.checkNotNull(r, "'r' must not be null.");
- boolean scheduleTaskRunner = false;
+ public void resume() {
synchronized (internalLock) {
- waitQueue.add(r);
+ Preconditions.checkState(suspensions > 0);
+ suspensions--;
+ }
+ startQueueWorker();
+ }
- if (!isThreadScheduled) {
- isThreadScheduled = true;
- scheduleTaskRunner = true;
+ private void startQueueWorker() {
+ synchronized (internalLock) {
+ // We sometimes try to start a queue worker without knowing if there is any work to do.
+ if (queue.peek() == null) {
+ return;
+ }
+ if (suspensions > 0) {
+ return;
}
+ if (isWorkerRunning) {
+ return;
+ }
+ isWorkerRunning = true;
}
- if (scheduleTaskRunner) {
- boolean threw = true;
- try {
- executor.execute(taskRunner);
- threw = false;
- } finally {
- if (threw) {
- synchronized (internalLock) {
- // It is possible that at this point that there are still tasks in
- // the queue, it would be nice to keep trying but the error may not
- // be recoverable. So we update our state and propogate so that if
- // our caller deems it recoverable we won't be stuck.
- isThreadScheduled = false;
- }
+ boolean executionRejected = true;
+ try {
+ executor.execute(new QueueWorker());
+ executionRejected = false;
+ } finally {
+ if (executionRejected) {
+ // The best we can do is to stop executing the queue, but reset the state so that
+ // execution can be resumed later if the caller so wishes.
+ synchronized (internalLock) {
+ isWorkerRunning = false;
}
}
}
}
/**
- * Task that actually runs the Runnables. It takes the Runnables off of the
- * queue one by one and runs them. After it is done with all Runnables and
- * there are no more to run, puts the SerializingExecutor in the state where
- * isThreadScheduled = false and returns. This allows the current worker
- * thread to return to the original pool.
+ * Worker that runs tasks off the queue until it is empty or the queue is suspended.
*/
- private class TaskRunner implements Runnable {
+ private final class QueueWorker implements Runnable {
@Override
public void run() {
- boolean stillRunning = true;
try {
- while (true) {
- Preconditions.checkState(isThreadScheduled);
- Runnable nextToRun;
- synchronized (internalLock) {
- nextToRun = waitQueue.poll();
- if (nextToRun == null) {
- isThreadScheduled = false;
- stillRunning = false;
- break;
- }
- }
+ workOnQueue();
+ } catch (Error e) {
+ synchronized (internalLock) {
+ isWorkerRunning = false;
+ }
+ throw e;
+ // The execution of a task has ended abnormally.
+ // We could have tasks left in the queue, so should perhaps try to restart a worker,
+ // but then the Error will get delayed if we are using a direct (same thread) executor.
+ }
+ }
- // Always run while not holding the lock, to avoid deadlocks.
- try {
- nextToRun.run();
- } catch (RuntimeException e) {
- // Log it and keep going.
- log.log(Level.SEVERE, "Exception while executing runnable "
- + nextToRun, e);
+ private void workOnQueue() {
+ while (true) {
+ Runnable task = null;
+ synchronized (internalLock) {
+ // TODO(user): How should we handle interrupts and shutdowns?
+ if (suspensions == 0) {
+ task = queue.poll();
}
- }
- } finally {
- if (stillRunning) {
- // An Error is bubbling up, we should mark ourselves as no longer
- // running, that way if anyone tries to keep using us we won't be
- // corrupted.
- synchronized (internalLock) {
- isThreadScheduled = false;
+ if (task == null) {
+ isWorkerRunning = false;
+ return;
}
}
+ try {
+ task.run();
+ } catch (RuntimeException e) {
+ log.log(Level.SEVERE, "Exception while executing runnable " + task, e);
+ }
}
}
}
diff --git a/guava/src/com/google/common/util/concurrent/ServiceManager.java b/guava/src/com/google/common/util/concurrent/ServiceManager.java
index 4f7d1d7..f72f199 100644
--- a/guava/src/com/google/common/util/concurrent/ServiceManager.java
+++ b/guava/src/com/google/common/util/concurrent/ServiceManager.java
@@ -35,7 +35,6 @@ import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.base.Stopwatch;
-import com.google.common.base.Supplier;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
@@ -45,23 +44,22 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Ordering;
import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenerCallQueue.Callback;
import com.google.common.util.concurrent.Service.State;
+import com.google.j2objc.annotations.WeakOuter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
-import java.util.EnumMap;
+import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -402,12 +400,7 @@ public final class ServiceManager {
@GuardedBy("monitor")
final SetMultimap<State, Service> servicesByState =
- Multimaps.newSetMultimap(new EnumMap<State, Collection<Service>>(State.class),
- new Supplier<Set<Service>>() {
- @Override public Set<Service> get() {
- return Sets.newLinkedHashSet();
- }
- });
+ MultimapBuilder.enumKeys(State.class).linkedHashSetValues().build();
@GuardedBy("monitor")
final Multiset<State> states = servicesByState.keys();
@@ -438,7 +431,14 @@ public final class ServiceManager {
* Controls how long to wait for all the services to either become healthy or reach a
* state from which it is guaranteed that it can never become healthy.
*/
- final Monitor.Guard awaitHealthGuard = new Monitor.Guard(monitor) {
+ final Monitor.Guard awaitHealthGuard = new AwaitHealthGuard();
+
+ @WeakOuter
+ final class AwaitHealthGuard extends Monitor.Guard {
+ AwaitHealthGuard() {
+ super(ServiceManagerState.this.monitor);
+ }
+
@Override public boolean isSatisfied() {
// All services have started or some service has terminated/failed.
return states.count(RUNNING) == numberOfServices
@@ -446,16 +446,23 @@ public final class ServiceManager {
|| states.contains(TERMINATED)
|| states.contains(FAILED);
}
- };
+ }
/**
* Controls how long to wait for all services to reach a terminal state.
*/
- final Monitor.Guard stoppedGuard = new Monitor.Guard(monitor) {
+ final Monitor.Guard stoppedGuard = new StoppedGuard();
+
+ @WeakOuter
+ final class StoppedGuard extends Monitor.Guard {
+ StoppedGuard() {
+ super(ServiceManagerState.this.monitor);
+ }
+
@Override public boolean isSatisfied() {
return states.count(TERMINATED) + states.count(FAILED) == numberOfServices;
}
- };
+ }
/** The listeners to notify during a state transition. */
@GuardedBy("monitor")
@@ -564,7 +571,7 @@ public final class ServiceManager {
throw new TimeoutException("Timeout waiting for the services to stop. The following "
+ "services have not stopped: "
+ Multimaps.filterKeys(servicesByState,
- not(in(ImmutableSet.of(TERMINATED, FAILED)))));
+ not(in(EnumSet.of(TERMINATED, FAILED)))));
}
} finally {
monitor.leave();
@@ -577,7 +584,7 @@ public final class ServiceManager {
try {
for (Entry<State, Service> entry : servicesByState.entries()) {
if (!(entry.getValue() instanceof NoOpService)) {
- builder.put(entry.getKey(), entry.getValue());
+ builder.put(entry);
}
}
} finally {
@@ -602,17 +609,13 @@ public final class ServiceManager {
} finally {
monitor.leave();
}
- Collections.sort(loadTimes, Ordering.<Long>natural()
+ Collections.sort(loadTimes, Ordering.natural()
.onResultOf(new Function<Entry<Service, Long>, Long>() {
@Override public Long apply(Map.Entry<Service, Long> input) {
return input.getValue();
}
}));
- ImmutableMap.Builder<Service, Long> builder = ImmutableMap.builder();
- for (Entry<Service, Long> entry : loadTimes) {
- builder.put(entry);
- }
- return builder.build();
+ return ImmutableMap.copyOf(loadTimes);
}
/**
@@ -771,7 +774,7 @@ public final class ServiceManager {
if (state != null) {
// Log before the transition, so that if the process exits in response to server failure,
// there is a higher likelihood that the cause will be in the logs.
- if (!(service instanceof NoOpService)) {
+ if (!(service instanceof NoOpService) ) {
logger.log(Level.SEVERE, "Service " + service + " has failed in the " + from + " state.",
failure);
}
diff --git a/guava/src/com/google/common/util/concurrent/SettableFuture.java b/guava/src/com/google/common/util/concurrent/SettableFuture.java
index 23e14f9..bc3f905 100644
--- a/guava/src/com/google/common/util/concurrent/SettableFuture.java
+++ b/guava/src/com/google/common/util/concurrent/SettableFuture.java
@@ -16,16 +16,21 @@
package com.google.common.util.concurrent;
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+
import javax.annotation.Nullable;
/**
- * A {@link ListenableFuture} whose result may be set by a {@link #set(Object)}
- * or {@link #setException(Throwable)} call. It may also be cancelled.
+ * A {@link ListenableFuture} whose result may be set by a {@link #set(Object)},
+ * {@link #setException(Throwable)} or {@link #setFuture(ListenableFuture)} call.
+ * It may also be cancelled.
*
* @author Sven Mawson
* @since 9.0 (in 1.0 as {@code ValueFuture})
*/
-public final class SettableFuture<V> extends AbstractFuture<V> {
+ at GwtCompatible
+public final class SettableFuture<V> extends AbstractFuture.TrustedFuture<V> {
/**
* Creates a new {@code SettableFuture} in the default state.
@@ -40,31 +45,17 @@ public final class SettableFuture<V> extends AbstractFuture<V> {
*/
private SettableFuture() {}
- /**
- * Sets the value of this future. This method will return {@code true} if
- * the value was successfully set, or {@code false} if the future has already
- * been set or cancelled.
- *
- * @param value the value the future should hold.
- * @return true if the value was successfully set.
- */
- @Override
- public boolean set(@Nullable V value) {
+ @Override public boolean set(@Nullable V value) {
return super.set(value);
}
- /**
- * Sets the future to having failed with the given exception. This exception
- * will be wrapped in an {@code ExecutionException} and thrown from the {@code
- * get} methods. This method will return {@code true} if the exception was
- * successfully set, or {@code false} if the future has already been set or
- * cancelled.
- *
- * @param throwable the exception the future should hold.
- * @return true if the exception was successfully set.
- */
- @Override
- public boolean setException(Throwable throwable) {
+ @Override public boolean setException(Throwable throwable) {
return super.setException(throwable);
}
+
+ @Beta
+ @Override
+ public boolean setFuture(ListenableFuture<? extends V> future) {
+ return super.setFuture(future);
+ }
}
diff --git a/guava/src/com/google/common/util/concurrent/SmoothRateLimiter.java b/guava/src/com/google/common/util/concurrent/SmoothRateLimiter.java
index 0d426cf..d934c78 100644
--- a/guava/src/com/google/common/util/concurrent/SmoothRateLimiter.java
+++ b/guava/src/com/google/common/util/concurrent/SmoothRateLimiter.java
@@ -19,6 +19,8 @@ package com.google.common.util.concurrent;
import static java.lang.Math.min;
import static java.util.concurrent.TimeUnit.SECONDS;
+import com.google.common.math.LongMath;
+
import java.util.concurrent.TimeUnit;
abstract class SmoothRateLimiter extends RateLimiter {
@@ -144,79 +146,58 @@ abstract class SmoothRateLimiter extends RateLimiter {
*/
/**
- * This implements the following function:
+ * This implements the following function where coldInterval = coldFactor * stableInterval.
*
* ^ throttling
* |
- * 3*stable + /
+ * cold + /
* interval | /.
- * (cold) | / .
+ * | / .
* | / . <-- "warmup period" is the area of the trapezoid between
- * 2*stable + / . halfPermits and maxPermits
- * interval | / .
+ * | / . thresholdPermits and maxPermits
+ * | / .
* | / .
* | / .
- * stable +----------/ WARM . }
- * interval | . UP . } <-- this rectangle (from 0 to maxPermits, and
- * | . PERIOD. } height == stableInterval) defines the cooldown period,
- * | . . } and we want cooldownPeriod == warmupPeriod
- * |---------------------------------> storedPermits
- * (halfPermits) (maxPermits)
- *
+ * stable +----------/ WARM .
+ * interval | . UP .
+ * | . PERIOD.
+ * | . .
+ * 0 +----------+-------+--------------> storedPermits
+ * 0 thresholdPermits maxPermits
* Before going into the details of this particular function, let's keep in mind the basics:
* 1) The state of the RateLimiter (storedPermits) is a vertical line in this figure.
* 2) When the RateLimiter is not used, this goes right (up to maxPermits)
* 3) When the RateLimiter is used, this goes left (down to zero), since if we have storedPermits,
* we serve from those first
- * 4) When _unused_, we go right at the same speed (rate)! I.e., if our rate is
- * 2 permits per second, and 3 unused seconds pass, we will always save 6 permits
- * (no matter what our initial position was), up to maxPermits.
- * If we invert the rate, we get the "stableInterval" (interval between two requests
- * in a perfectly spaced out sequence of requests of the given rate). Thus, if you
- * want to see "how much time it will take to go from X storedPermits to X+K storedPermits?",
- * the answer is always stableInterval * K. In the same example, for 2 permits per second,
- * stableInterval is 500ms. Thus to go from X storedPermits to X+6 storedPermits, we
- * require 6 * 500ms = 3 seconds.
- *
- * In short, the time it takes to move to the right (save K permits) is equal to the
- * rectangle of width == K and height == stableInterval.
- * 4) When _used_, the time it takes, as explained in the introductory class note, is
+ * 4) When _unused_, we go right at a constant rate! The rate at which we move to
+ * the right is chosen as maxPermits / warmupPeriod. This ensures that the time it takes to
+ * go from 0 to maxPermits is equal to warmupPeriod.
+ * 5) When _used_, the time it takes, as explained in the introductory class note, is
* equal to the integral of our function, between X permits and X-K permits, assuming
* we want to spend K saved permits.
*
* In summary, the time it takes to move to the left (spend K permits), is equal to the
* area of the function of width == K.
*
- * Let's dive into this function now:
+ * Assuming we have saturated demand, the time to go from maxPermits to thresholdPermits is
+ * equal to warmupPeriod. And the time to go from thresholdPermits to 0 is
+ * warmupPeriod/2. (The reason that this is warmupPeriod/2 is to maintain the behavior of
+ * the original implementation where coldFactor was hard coded as 3.)
*
- * When we have storedPermits <= halfPermits (the left portion of the function), then
- * we spend them at the exact same rate that
- * fresh permits would be generated anyway (that rate is 1/stableInterval). We size
- * this area to be equal to _half_ the specified warmup period. Why we need this?
- * And why half? We'll explain shortly below (after explaining the second part).
+ * It remains to calculate thresholdsPermits and maxPermits.
*
- * Stored permits that are beyond halfPermits, are mapped to an ascending line, that goes
- * from stableInterval to 3 * stableInterval. The average height for that part is
- * 2 * stableInterval, and is sized appropriately to have an area _equal_ to the
- * specified warmup period. Thus, by point (4) above, it takes "warmupPeriod" amount of time
- * to go from maxPermits to halfPermits.
+ * - The time to go from thresholdPermits to 0 is equal to the integral of the function between
+ * 0 and thresholdPermits. This is thresholdPermits * stableIntervals. By (5) it is also
+ * equal to warmupPeriod/2. Therefore
*
- * BUT, by point (3) above, it only takes "warmupPeriod / 2" amount of time to return back
- * to maxPermits, from halfPermits! (Because the trapezoid has double the area of the rectangle
- * of height stableInterval and equivalent width). We decided that the "cooldown period"
- * time should be equivalent to "warmup period", thus a fully saturated RateLimiter
- * (with zero stored permits, serving only fresh ones) can go to a fully unsaturated
- * (with storedPermits == maxPermits) in the same amount of time it takes for a fully
- * unsaturated RateLimiter to return to the stableInterval -- which happens in halfPermits,
- * since beyond that point, we use a horizontal line of "stableInterval" height, simulating
- * the regular rate.
+ * thresholdPermits = 0.5 * warmupPeriod / stableInterval.
*
- * Thus, we have figured all dimensions of this shape, to give all the desired
- * properties:
- * - the width is warmupPeriod / stableInterval, to make cooldownPeriod == warmupPeriod
- * - the slope starts at the middle, and goes from stableInterval to 3*stableInterval so
- * to have halfPermits being spend in double the usual time (half the rate), while their
- * respective rate is steadily ramping up
+ * - The time to go from maxPermits to thresholdPermits is equal to the integral of the function
+ * between thresholdPermits and maxPermits. This is the area of the pictured trapezoid, and it
+ * is equal to 0.5 * (stableInterval + coldInterval) * (maxPermits - thresholdPermits). It is
+ * also equal to warmupPeriod, so
+ *
+ * maxPermits = thresholdPermits + 2 * warmupPeriod / (stableInterval + coldInterval).
*/
static final class SmoothWarmingUp extends SmoothRateLimiter {
private final long warmupPeriodMicros;
@@ -225,21 +206,24 @@ abstract class SmoothRateLimiter extends RateLimiter {
* (when permits == maxPermits)
*/
private double slope;
- private double halfPermits;
-
- SmoothWarmingUp(SleepingStopwatch stopwatch, long warmupPeriod, TimeUnit timeUnit) {
+ private double thresholdPermits;
+ private double coldFactor;
+
+ SmoothWarmingUp(
+ SleepingStopwatch stopwatch, long warmupPeriod, TimeUnit timeUnit, double coldFactor) {
super(stopwatch);
this.warmupPeriodMicros = timeUnit.toMicros(warmupPeriod);
+ this.coldFactor = coldFactor;
}
-
+
@Override
void doSetRate(double permitsPerSecond, double stableIntervalMicros) {
double oldMaxPermits = maxPermits;
- maxPermits = warmupPeriodMicros / stableIntervalMicros;
- halfPermits = maxPermits / 2.0;
- // Stable interval is x, cold is 3x, so on average it's 2x. Double the time -> halve the rate
- double coldIntervalMicros = stableIntervalMicros * 3.0;
- slope = (coldIntervalMicros - stableIntervalMicros) / halfPermits;
+ double coldIntervalMicros = stableIntervalMicros * coldFactor;
+ thresholdPermits = 0.5 * warmupPeriodMicros / stableIntervalMicros;
+ maxPermits = thresholdPermits
+ + 2.0 * warmupPeriodMicros / (stableIntervalMicros + coldIntervalMicros);
+ slope = (coldIntervalMicros - stableIntervalMicros) / (maxPermits - thresholdPermits);
if (oldMaxPermits == Double.POSITIVE_INFINITY) {
// if we don't special-case this, we would get storedPermits == NaN, below
storedPermits = 0.0;
@@ -249,43 +233,49 @@ abstract class SmoothRateLimiter extends RateLimiter {
: storedPermits * maxPermits / oldMaxPermits;
}
}
-
+
@Override
long storedPermitsToWaitTime(double storedPermits, double permitsToTake) {
- double availablePermitsAboveHalf = storedPermits - halfPermits;
+ double availablePermitsAboveThreshold = storedPermits - thresholdPermits;
long micros = 0;
// measuring the integral on the right part of the function (the climbing line)
- if (availablePermitsAboveHalf > 0.0) {
- double permitsAboveHalfToTake = min(availablePermitsAboveHalf, permitsToTake);
- micros = (long) (permitsAboveHalfToTake * (permitsToTime(availablePermitsAboveHalf)
- + permitsToTime(availablePermitsAboveHalf - permitsAboveHalfToTake)) / 2.0);
- permitsToTake -= permitsAboveHalfToTake;
+ if (availablePermitsAboveThreshold > 0.0) {
+ double permitsAboveThresholdToTake = min(availablePermitsAboveThreshold, permitsToTake);
+ micros = (long) (permitsAboveThresholdToTake
+ * (permitsToTime(availablePermitsAboveThreshold)
+ + permitsToTime(availablePermitsAboveThreshold - permitsAboveThresholdToTake)) / 2.0);
+ permitsToTake -= permitsAboveThresholdToTake;
}
// measuring the integral on the left part of the function (the horizontal line)
micros += (stableIntervalMicros * permitsToTake);
return micros;
}
-
+
private double permitsToTime(double permits) {
return stableIntervalMicros + permits * slope;
}
+
+ @Override
+ double coolDownIntervalMicros() {
+ return warmupPeriodMicros / maxPermits;
+ }
}
/**
* This implements a "bursty" RateLimiter, where storedPermits are translated to
* zero throttling. The maximum number of permits that can be saved (when the RateLimiter is
* unused) is defined in terms of time, in this sense: if a RateLimiter is 2qps, and this
- * time is specified as 10 seconds, we can save up to 2 * 10 = 20 permits.
+ * time is specified as 10 seconds, we can save up to 2 * 10 = 20 permits.
*/
static final class SmoothBursty extends SmoothRateLimiter {
/** The work (permits) of how many seconds can be saved up if this RateLimiter is unused? */
- final double maxBurstSeconds;
-
+ final double maxBurstSeconds;
+
SmoothBursty(SleepingStopwatch stopwatch, double maxBurstSeconds) {
super(stopwatch);
this.maxBurstSeconds = maxBurstSeconds;
}
-
+
@Override
void doSetRate(double permitsPerSecond, double stableIntervalMicros) {
double oldMaxPermits = this.maxPermits;
@@ -299,11 +289,16 @@ abstract class SmoothRateLimiter extends RateLimiter {
: storedPermits * maxPermits / oldMaxPermits;
}
}
-
+
@Override
long storedPermitsToWaitTime(double storedPermits, double permitsToTake) {
return 0L;
}
+
+ @Override
+ double coolDownIntervalMicros() {
+ return stableIntervalMicros;
+ }
}
/**
@@ -359,11 +354,14 @@ abstract class SmoothRateLimiter extends RateLimiter {
long returnValue = nextFreeTicketMicros;
double storedPermitsToSpend = min(requiredPermits, this.storedPermits);
double freshPermits = requiredPermits - storedPermitsToSpend;
-
long waitMicros = storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend)
+ (long) (freshPermits * stableIntervalMicros);
- this.nextFreeTicketMicros = nextFreeTicketMicros + waitMicros;
+ try {
+ this.nextFreeTicketMicros = LongMath.checkedAdd(nextFreeTicketMicros, waitMicros);
+ } catch (ArithmeticException e) {
+ this.nextFreeTicketMicros = Long.MAX_VALUE;
+ }
this.storedPermits -= storedPermitsToSpend;
return returnValue;
}
@@ -378,11 +376,20 @@ abstract class SmoothRateLimiter extends RateLimiter {
*/
abstract long storedPermitsToWaitTime(double storedPermits, double permitsToTake);
- private void resync(long nowMicros) {
+ /**
+ * Returns the number of microseconds during cool down that we have to wait to get a new permit.
+ */
+ abstract double coolDownIntervalMicros();
+
+ /**
+ * Updates {@code storedPermits} and {@code nextFreeTicketMicros} based on the current time.
+ */
+ void resync(long nowMicros) {
// if nextFreeTicket is in the past, resync to now
if (nowMicros > nextFreeTicketMicros) {
storedPermits = min(maxPermits,
- storedPermits + (nowMicros - nextFreeTicketMicros) / stableIntervalMicros);
+ storedPermits
+ + (nowMicros - nextFreeTicketMicros) / coolDownIntervalMicros());
nextFreeTicketMicros = nowMicros;
}
}
diff --git a/guava/src/com/google/common/util/concurrent/Striped.java b/guava/src/com/google/common/util/concurrent/Striped.java
index a8bc379..1ca01b5 100644
--- a/guava/src/com/google/common/util/concurrent/Striped.java
+++ b/guava/src/com/google/common/util/concurrent/Striped.java
@@ -466,8 +466,9 @@ public abstract class Striped<L> {
* a fourth long here, to minimize chance of interference between consecutive locks,
* but I couldn't observe any benefit from that.
*/
- @SuppressWarnings("unused")
- long q1, q2, q3;
+ long unused1;
+ long unused2;
+ long unused3;
PaddedLock() {
super(false);
@@ -476,8 +477,9 @@ public abstract class Striped<L> {
private static class PaddedSemaphore extends Semaphore {
// See PaddedReentrantLock comment
- @SuppressWarnings("unused")
- long q1, q2, q3;
+ long unused1;
+ long unused2;
+ long unused3;
PaddedSemaphore(int permits) {
super(permits, false);
diff --git a/guava/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java b/guava/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java
index 47f20cc..5fc283c 100644
--- a/guava/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java
+++ b/guava/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java
@@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.Locale;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;
@@ -66,9 +67,8 @@ public final class ThreadFactoryBuilder {
* {@code "rpc-pool-0"}, {@code "rpc-pool-1"}, {@code "rpc-pool-2"}, etc.
* @return this for the builder pattern
*/
- @SuppressWarnings("ReturnValueIgnored")
public ThreadFactoryBuilder setNameFormat(String nameFormat) {
- String.format(nameFormat, 0); // fail fast if the format is bad or null
+ String unused = format(nameFormat, 0); // fail fast if the format is bad or null
this.nameFormat = nameFormat;
return this;
}
@@ -161,7 +161,7 @@ public final class ThreadFactoryBuilder {
@Override public Thread newThread(Runnable runnable) {
Thread thread = backingThreadFactory.newThread(runnable);
if (nameFormat != null) {
- thread.setName(String.format(nameFormat, count.getAndIncrement()));
+ thread.setName(format(nameFormat, count.getAndIncrement()));
}
if (daemon != null) {
thread.setDaemon(daemon);
@@ -176,4 +176,8 @@ public final class ThreadFactoryBuilder {
}
};
}
+
+ private static String format(String format, Object... args) {
+ return String.format(Locale.ROOT, format, args);
+ }
}
diff --git a/guava/src/com/google/common/util/concurrent/TrustedListenableFutureTask.java b/guava/src/com/google/common/util/concurrent/TrustedListenableFutureTask.java
new file mode 100644
index 0000000..07b93bc
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/TrustedListenableFutureTask.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
+import com.google.j2objc.annotations.WeakOuter;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RunnableFuture;
+
+import javax.annotation.Nullable;
+
+/**
+ * A {@link RunnableFuture} that also implements the {@link ListenableFuture}
+ * interface.
+ *
+ * <p>This should be used in preference to {@link ListenableFutureTask} when possible for
+ * performance reasons.
+ */
+ at GwtCompatible
+class TrustedListenableFutureTask<V> extends AbstractFuture.TrustedFuture<V>
+ implements RunnableFuture<V> {
+
+ /**
+ * Creates a {@code ListenableFutureTask} that will upon running, execute the
+ * given {@code Callable}.
+ *
+ * @param callable the callable task
+ */
+ static <V> TrustedListenableFutureTask<V> create(Callable<V> callable) {
+ return new TrustedListenableFutureTask<V>(callable);
+ }
+
+ /**
+ * Creates a {@code ListenableFutureTask} that will upon running, execute the
+ * given {@code Runnable}, and arrange that {@code get} will return the
+ * given result on successful completion.
+ *
+ * @param runnable the runnable task
+ * @param result the result to return on successful completion. If you don't
+ * need a particular result, consider using constructions of the form:
+ * {@code ListenableFuture<?> f = ListenableFutureTask.create(runnable,
+ * null)}
+ */
+ static <V> TrustedListenableFutureTask<V> create(
+ Runnable runnable, @Nullable V result) {
+ return new TrustedListenableFutureTask<V>(Executors.callable(runnable, result));
+ }
+
+ private TrustedFutureInterruptibleTask task;
+
+ TrustedListenableFutureTask(Callable<V> callable) {
+ this.task = new TrustedFutureInterruptibleTask(callable);
+ }
+
+ @Override public void run() {
+ TrustedFutureInterruptibleTask localTask = task;
+ if (localTask != null) {
+ localTask.run();
+ }
+ }
+
+ @Override final void done() {
+ super.done();
+
+ // Free all resources associated with the running task
+ this.task = null;
+ }
+
+ @GwtIncompatible("Interruption not supported")
+ @Override protected final void interruptTask() {
+ TrustedFutureInterruptibleTask localTask = task;
+ if (localTask != null) {
+ localTask.interruptTask();
+ }
+ }
+
+ @WeakOuter
+ private final class TrustedFutureInterruptibleTask extends InterruptibleTask {
+ private final Callable<V> callable;
+
+ TrustedFutureInterruptibleTask(Callable<V> callable) {
+ this.callable = checkNotNull(callable);
+ }
+
+ @Override void runInterruptibly() {
+ // Ensure we haven't been cancelled or already run.
+ if (!isDone()) {
+ try {
+ set(callable.call());
+ } catch (Throwable t) {
+ setException(t);
+ }
+ }
+ }
+
+ @Override boolean wasInterrupted() {
+ return TrustedListenableFutureTask.this.wasInterrupted();
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java b/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java
index 19b91f2..3d19c4c 100644
--- a/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java
+++ b/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java
@@ -21,6 +21,7 @@ import static java.util.logging.Level.SEVERE;
import com.google.common.annotations.VisibleForTesting;
import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.Locale;
import java.util.logging.Logger;
/**
@@ -62,7 +63,8 @@ public final class UncaughtExceptionHandlers {
@Override public void uncaughtException(Thread t, Throwable e) {
try {
// cannot use FormattingLogger due to a dependency loop
- logger.log(SEVERE, String.format("Caught an exception in %s. Shutting down.", t), e);
+ logger.log(SEVERE,
+ String.format(Locale.ROOT, "Caught an exception in %s. Shutting down.", t), e);
} catch (Throwable errorInLogging) {
// If logging fails, e.g. due to missing memory, at least try to log the
// message and the cause for the failed logging.
diff --git a/guava/src/com/google/common/util/concurrent/Uninterruptibles.java b/guava/src/com/google/common/util/concurrent/Uninterruptibles.java
index d0f80d7..521a655 100644
--- a/guava/src/com/google/common/util/concurrent/Uninterruptibles.java
+++ b/guava/src/com/google/common/util/concurrent/Uninterruptibles.java
@@ -19,6 +19,8 @@ package com.google.common.util.concurrent;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Preconditions;
import java.util.concurrent.BlockingQueue;
@@ -40,6 +42,7 @@ import java.util.concurrent.TimeoutException;
* @since 10.0
*/
@Beta
+ at GwtCompatible(emulated = true)
public final class Uninterruptibles {
// Implementation Note: As of 3-7-11, the logic for each blocking/timeout
@@ -49,6 +52,7 @@ public final class Uninterruptibles {
* Invokes {@code latch.}{@link CountDownLatch#await() await()}
* uninterruptibly.
*/
+ @GwtIncompatible("concurrency")
public static void awaitUninterruptibly(CountDownLatch latch) {
boolean interrupted = false;
try {
@@ -72,6 +76,7 @@ public final class Uninterruptibles {
* {@code latch.}{@link CountDownLatch#await(long, TimeUnit)
* await(timeout, unit)} uninterruptibly.
*/
+ @GwtIncompatible("concurrency")
public static boolean awaitUninterruptibly(CountDownLatch latch,
long timeout, TimeUnit unit) {
boolean interrupted = false;
@@ -98,6 +103,7 @@ public final class Uninterruptibles {
/**
* Invokes {@code toJoin.}{@link Thread#join() join()} uninterruptibly.
*/
+ @GwtIncompatible("concurrency")
public static void joinUninterruptibly(Thread toJoin) {
boolean interrupted = false;
try {
@@ -122,8 +128,8 @@ public final class Uninterruptibles {
* {@link Futures#getUnchecked}.
*
* <p>If instead, you wish to treat {@link InterruptedException} uniformly
- * with other exceptions, see {@link Futures#get(Future, Class) Futures.get}
- * or {@link Futures#makeChecked}.
+ * with other exceptions, see {@link Futures#getChecked(Future, Class)
+ * Futures.getChecked}.
*
* @throws ExecutionException if the computation threw an exception
* @throws CancellationException if the computation was cancelled
@@ -152,15 +158,16 @@ public final class Uninterruptibles {
* uninterruptibly.
*
* <p>If instead, you wish to treat {@link InterruptedException} uniformly
- * with other exceptions, see {@link Futures#get(Future, Class) Futures.get}
- * or {@link Futures#makeChecked}.
+ * with other exceptions, see {@link Futures#getChecked(Future, Class)
+ * Futures.getChecked}.
*
* @throws ExecutionException if the computation threw an exception
* @throws CancellationException if the computation was cancelled
* @throws TimeoutException if the wait timed out
*/
+ @GwtIncompatible("TODO")
public static <V> V getUninterruptibly(
- Future<V> future, long timeout, TimeUnit unit)
+ Future<V> future, long timeout, TimeUnit unit)
throws ExecutionException, TimeoutException {
boolean interrupted = false;
try {
@@ -188,6 +195,7 @@ public final class Uninterruptibles {
* {@code unit.}{@link TimeUnit#timedJoin(Thread, long)
* timedJoin(toJoin, timeout)} uninterruptibly.
*/
+ @GwtIncompatible("concurrency")
public static void joinUninterruptibly(Thread toJoin,
long timeout, TimeUnit unit) {
Preconditions.checkNotNull(toJoin);
@@ -215,6 +223,7 @@ public final class Uninterruptibles {
/**
* Invokes {@code queue.}{@link BlockingQueue#take() take()} uninterruptibly.
*/
+ @GwtIncompatible("concurrency")
public static <E> E takeUninterruptibly(BlockingQueue<E> queue) {
boolean interrupted = false;
try {
@@ -241,6 +250,7 @@ public final class Uninterruptibles {
* @throws IllegalArgumentException if some property of the specified element
* prevents it from being added to the given queue
*/
+ @GwtIncompatible("concurrency")
public static <E> void putUninterruptibly(BlockingQueue<E> queue, E element) {
boolean interrupted = false;
try {
@@ -264,6 +274,7 @@ public final class Uninterruptibles {
* Invokes {@code unit.}{@link TimeUnit#sleep(long) sleep(sleepFor)}
* uninterruptibly.
*/
+ @GwtIncompatible("concurrency")
public static void sleepUninterruptibly(long sleepFor, TimeUnit unit) {
boolean interrupted = false;
try {
@@ -292,6 +303,7 @@ public final class Uninterruptibles {
*
* @since 18.0
*/
+ @GwtIncompatible("concurrency")
public static boolean tryAcquireUninterruptibly(
Semaphore semaphore, long timeout, TimeUnit unit) {
return tryAcquireUninterruptibly(semaphore, 1, timeout, unit);
@@ -303,6 +315,7 @@ public final class Uninterruptibles {
*
* @since 18.0
*/
+ @GwtIncompatible("concurrency")
public static boolean tryAcquireUninterruptibly(
Semaphore semaphore, int permits, long timeout, TimeUnit unit) {
boolean interrupted = false;
diff --git a/guava/src/com/google/common/util/concurrent/WrappingExecutorService.java b/guava/src/com/google/common/util/concurrent/WrappingExecutorService.java
index 9417c69..e6a324b 100644
--- a/guava/src/com/google/common/util/concurrent/WrappingExecutorService.java
+++ b/guava/src/com/google/common/util/concurrent/WrappingExecutorService.java
@@ -53,7 +53,7 @@ abstract class WrappingExecutorService implements ExecutorService {
/**
* Wraps a {@code Callable} for submission to the underlying executor. This
* method is also applied to any {@code Runnable} passed to the default
- * implementation of {@link #wrapTest(Runnable)}.
+ * implementation of {@link #wrapTask(Runnable)}.
*/
protected abstract <T> Callable<T> wrapTask(Callable<T> callable);
diff --git a/guava/src/com/google/thirdparty/publicsuffix/PublicSuffixPatterns.java b/guava/src/com/google/thirdparty/publicsuffix/PublicSuffixPatterns.java
index b12c150..f218158 100644
--- a/guava/src/com/google/thirdparty/publicsuffix/PublicSuffixPatterns.java
+++ b/guava/src/com/google/thirdparty/publicsuffix/PublicSuffixPatterns.java
@@ -42,7 +42,7 @@ public final class PublicSuffixPatterns {
/** If a hostname is contained as a key in this map, it is a public suffix. */
public static final ImmutableMap<String, PublicSuffixType> EXACT =
- TrieParser.parseTrie("a&027qjf--nx?12oa08--nx?2eyh3la2ckx--nx?32wqq1--nx?6&1f4a3abgm--nx?lbgw--nx??883xnn--nx?b!.&asnu?gro?ibnu?lim?moc?oc?sr?ten?ude?vog??ihsot??c!.&b&a?m?n??c&b?g?q??ep?fn?k&s?y??ln?no?oc,sn?t&n?opsgolb,?un??irfa?s??d&neit?om?tl??g!oy??hskihs?i&dem?sa??jnin?k&dov?usto??l!.&c,gro?moc?ofni?rep?t&en?ni??ude?vog??lenisiuc??m!.&ca?gro?oc?sserp?ten?vog??ahokoy?e00sf7vqn--nx??n!.&ac?cc?eman?gro?ibom?loohcs?moc?ni?o&c?fni?rp??r&d?o??s&u?w??vt?xm???p!.&bog?ca?d&em?ls??g&ni [...]
+ TrieParser.parseTrie("a&0&0trk9--nx?27qjf--nx?e9ebgn--nx?nbb0c7abgm--nx??12oa08--nx?2&eyh3la2ckx--nx?qbd9--nx??3&2wqq1--nx?60a0y8--nx??4x1d77xrck--nx?6&1f4a3abgm--nx?2yqyn--nx?3np8lv81qo3--nx?5b06t--nx?lbgw--nx??883xnn--nx?9d2c24--nx?a&a?it??b!.&asnu?gro?ibnu?lim?moc?oc?sr?t&en?opsgolb,?ude?vog??abila?c?ihsot?m?n??c!.&b&a?m?n??c&b?g?q??ep?fn?k&s?y??ln?no?oc,sn?t&n?opsgolb,?un??i&ma?nofelet?r&emarp?fa??sroc??naiva?s??d&ats?n&eit?oh??om?sa?tl??eg?f&c?ob??g!emo?naripi?oy??h&od?skihs?? [...]
/**
* If a hostname is not a key in the EXCLUDE map, and if removing its
@@ -50,7 +50,7 @@ public final class PublicSuffixPatterns {
* public suffix.
*/
public static final ImmutableMap<String, PublicSuffixType> UNDER =
- TrieParser.parseTrie("az?db?e&k?y??gp?hk?in?jf?k&c?f?u.hcs??li?m&j?m?z??nb?p&j.&a&mahokoy?yogan??ebok?i&adnes?kasawak??oroppas?uhsuykatik??n??r&e?t??ug?w&k?z??yc?zm??");
+ TrieParser.parseTrie("db?e&k?y??gp?h&k?s.mroftalp,?in?jf?k&c?f?u.hcs??li?m&j?m?z??nb?p&j.&a&mahokoy?yogan??ebok?i&adnes?kasawak??oroppas?uhsuykatik??n??r&b.mon?e??ug?w&k?z??zm??");
/**
* The elements in this map would pass the UNDER test, but are known not to
@@ -59,5 +59,5 @@ public final class PublicSuffixPatterns {
* important here. The map is simply used for consistency reasons.
*/
public static final ImmutableMap<String, PublicSuffixType> EXCLUDED =
- TrieParser.parseTrie("kc.www?pj.&a&mahokoy.ytic?yogan.ytic??ebok.ytic?i&adnes.ytic?kasawak.ytic??oroppas.ytic?uhsuykatik.ytic??rt.cin?zm.atadelet??");
+ TrieParser.parseTrie("kc.www?pj.&a&mahokoy.ytic?yogan.ytic??ebok.ytic?i&adnes.ytic?kasawak.ytic??oroppas.ytic?uhsuykatik.ytic??zm.atadelet??");
}
diff --git a/mvn-deploy.sh b/mvn-deploy.sh
deleted file mode 100644
index 4c8a5f7..0000000
--- a/mvn-deploy.sh
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-#
-# This script checks the java version and bails if it's less
-# than Java6 (because we use @Override annotations on interface
-# overriding methods. It then proceeds to do a maven build that
-# first cleans, then builds the normal lifecycle through compilation
-# unit testing (if available) up to packaging. It then packages
-# the source, javadocs, and maven site. It then signs the
-# artifacts with whatever pgp signature is the default of the
-# user executing it, and then deploys to the repository contained
-# in the distributionManagement section of the pom.
-#
-# author: cgruber at google.com (Christian Edward Gruber)
-#
-if [[ -n ${JAVA_HOME} ]] ; then
- JAVA_CMD=${JAVA_HOME}/bin/java
-else
- JAVA_CMD=java
-fi
-java_version="$(${JAVA_CMD} -version 2>&1 | grep -e 'java version' | awk '{ print $3 }')"
-
-# This test sucks, but it's short term
-# TODO(cgruber) strip the quotes and patch version and do version comparison.
-greater_than_java5="$(echo ${java_version} | grep -e '^"1.[67]')"
-
-if [[ -z ${greater_than_java5} ]] ; then
- echo "Your java version is ${java_version}."
- echo "You must use at least a java 6 JVM to build and deploy this software."
- exit 1
-else
- echo "Building with java ${java_version}"
-fi
-
-if [[ $# > 0 ]]; then
- params+=" -Dgpg.keyname=${1}"
- gpg_sign_plugin=" gpg:sign"
-fi
-cmd="mvn clean package source:jar site:jar javadoc:jar ${gpg_sign_plugin} deploy ${params}"
-echo "Executing ${cmd}"
-${cmd}
diff --git a/pom.xml b/pom.xml
index dac208f..8c7a2d6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,19 +11,20 @@
</parent>
<groupId>com.google.guava</groupId>
<artifactId>guava-parent</artifactId>
- <version>18.0</version>
+ <version>19.0</version>
<packaging>pom</packaging>
<name>Guava Maven Parent</name>
- <url>http://code.google.com/p/guava-libraries</url>
+ <url>https://github.com/google/guava</url>
<properties>
<gpg.skip>true</gpg.skip>
<!-- Override this with -Dtest.include="**/SomeTest.java" on the CLI -->
<test.include>**/*Test.java</test.include>
- <truth.version>0.23</truth.version>
+ <truth.version>0.25</truth.version>
+ <animal.sniffer.version>1.14</animal.sniffer.version>
</properties>
<issueManagement>
- <system>code.google.com</system>
- <url>http://code.google.com/p/guava-libraries/issues</url>
+ <system>GitHub Issues</system>
+ <url>https://github.com/google/guava/issues</url>
</issueManagement>
<inceptionYear>2010</inceptionYear>
<licenses>
@@ -37,9 +38,9 @@
<maven>3.0.3</maven>
</prerequisites>
<scm>
- <connection>scm:git:https://code.google.com/p/guava-libraries/</connection>
- <developerConnection>scm:git:https://code.google.com/p/guava-libraries/</developerConnection>
- <url>http://code.google.com/p/guava-libraries/source/browse</url>
+ <connection>scm:git:https://github.com/google/guava.git</connection>
+ <developerConnection>scm:git:git at github.com:google/guava.git</developerConnection>
+ <url>https://github.com/google/guava</url>
</scm>
<developers>
<developer>
@@ -55,6 +56,10 @@
<timezone>-8</timezone>
</developer>
</developers>
+ <ciManagement>
+ <system>Travis CI</system>
+ <url>https://travis-ci.org/google/guava</url>
+ </ciManagement>
<modules>
<module>guava</module>
<module>guava-gwt</module>
@@ -133,12 +138,12 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
- <version>1.7</version>
+ <version>${animal.sniffer.version}</version>
<configuration>
<signature>
<groupId>org.codehaus.mojo.signature</groupId>
<artifactId>java16-sun</artifactId>
- <version>1.0</version>
+ <version>1.10</version>
</signature>
</configuration>
<executions>
@@ -155,7 +160,7 @@
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
<configuration>
- <stylesheetfile>javadoc-stylesheet.css</stylesheetfile>
+ <notimestamp>true</notimestamp>
</configuration>
<executions>
<execution>
@@ -200,6 +205,16 @@
<version>1.3.9</version>
</dependency>
<dependency>
+ <groupId>com.google.errorprone</groupId>
+ <artifactId>error_prone_annotations</artifactId>
+ <version>2.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.j2objc</groupId>
+ <artifactId>j2objc-annotations</artifactId>
+ <version>0.1</version>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
@@ -233,7 +248,7 @@
<dependency>
<groupId>com.google.caliper</groupId>
<artifactId>caliper</artifactId>
- <version>0.5-rc1</version>
+ <version>1.0-beta-2</version>
<scope>test</scope>
<exclusions>
<exclusion>
@@ -245,4 +260,64 @@
</dependency>
</dependencies>
</dependencyManagement>
+ <profiles>
+ <profile>
+ <id>jdk7</id>
+ <activation>
+ <jdk>1.7</jdk>
+ </activation>
+ <!-- Set custom stylesheet under JDK7 -->
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <stylesheetfile>javadoc-stylesheet.css</stylesheetfile>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <stylesheetfile>javadoc-stylesheet.css</stylesheetfile>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>jdk8</id>
+ <activation>
+ <jdk>[1.8,)</jdk>
+ </activation>
+ <!-- Disable doclint under JDK 8 -->
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <additionalparam>-Xdoclint:none</additionalparam>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <additionalparam>-Xdoclint:none</additionalparam>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
</project>
diff --git a/util/deploy_snapshot.sh b/util/deploy_snapshot.sh
new file mode 100755
index 0000000..0883b76
--- /dev/null
+++ b/util/deploy_snapshot.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# see https://coderwall.com/p/9b_lfq
+
+set -e -u
+
+if [ "$TRAVIS_REPO_SLUG" == "google/guava" ] && \
+ [ "$TRAVIS_JDK_VERSION" == "oraclejdk7" ] && \
+ [ "$TRAVIS_PULL_REQUEST" == "false" ] && \
+ [ "$TRAVIS_BRANCH" == "master" ]; then
+ echo "Publishing Maven snapshot..."
+
+ mvn clean source:jar javadoc:jar deploy --settings="util/settings.xml" -DskipTests=true
+
+ echo "Maven snapshot published."
+fi
diff --git a/util/settings.xml b/util/settings.xml
new file mode 100644
index 0000000..306d14a
--- /dev/null
+++ b/util/settings.xml
@@ -0,0 +1,11 @@
+<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
+ <servers>
+ <server>
+ <id>sonatype-nexus-snapshots</id>
+ <username>${env.CI_DEPLOY_USERNAME}</username>
+ <password>${env.CI_DEPLOY_PASSWORD}</password>
+ </server>
+ </servers>
+</settings>
diff --git a/util/update_snapshot_docs.sh b/util/update_snapshot_docs.sh
new file mode 100755
index 0000000..99e8210
--- /dev/null
+++ b/util/update_snapshot_docs.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# see http://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/ for details
+
+set -e -u
+
+if [ "$TRAVIS_REPO_SLUG" == "google/guava" ] && \
+ [ "$TRAVIS_JDK_VERSION" == "oraclejdk7" ] && \
+ [ "$TRAVIS_PULL_REQUEST" == "false" ] && \
+ [ "$TRAVIS_BRANCH" == "master" ]; then
+ echo "Publishing Javadoc and JDiff..."
+
+ cd $HOME
+ git clone -q -b gh-pages https://${GH_TOKEN}@github.com/google/guava gh-pages > /dev/null
+ cd gh-pages
+
+ git config --global user.email "travis at travis-ci.org"
+ git config --global user.name "travis-ci"
+
+ ./updaterelease.sh snapshot
+
+ git push -fq origin gh-pages > /dev/null
+
+ echo "Javadoc and JDiff published to gh-pages."
+fi
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/guava-libraries.git
More information about the pkg-java-commits
mailing list