14e11457f34addf5d10fe0c31cefd54c75c37b540sberlin/** 24e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Copyright (C) 2010 Google Inc. 34e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * 44e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Licensed under the Apache License, Version 2.0 (the "License"); 54e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * you may not use this file except in compliance with the License. 64e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * You may obtain a copy of the License at 74e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * 84e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * http://www.apache.org/licenses/LICENSE-2.0 94e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * 104e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Unless required by applicable law or agreed to in writing, software 114e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * distributed under the License is distributed on an "AS IS" BASIS, 124e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * See the License for the specific language governing permissions and 144e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * limitations under the License. 154e11457f34addf5d10fe0c31cefd54c75c37b540sberlin */ 164e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 174e11457f34addf5d10fe0c31cefd54c75c37b540sberlinpackage com.google.inject.multibindings; 184e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 194e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static com.google.inject.multibindings.MapBinder.entryOfProviderOf; 204e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static com.google.inject.multibindings.MapBinder.mapOf; 213338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlinimport static com.google.inject.multibindings.MapBinder.mapOfJavaxProviderOf; 224e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static com.google.inject.multibindings.MapBinder.mapOfProviderOf; 234e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static com.google.inject.multibindings.MapBinder.mapOfSetOfProviderOf; 24bed1413751f54dc6804dcb2a4c28300081788603flanimport static com.google.inject.multibindings.Multibinder.collectionOfJavaxProvidersOf; 254faa20e3081448792933834aedfe972add806292Sam Berlinimport static com.google.inject.multibindings.Multibinder.collectionOfProvidersOf; 264e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static com.google.inject.multibindings.Multibinder.setOf; 271d3f8cd0a163c7439589d80e6377edbf2ca4b43dsamebimport static com.google.inject.multibindings.OptionalBinder.javaOptionalOfJavaxProvider; 281d3f8cd0a163c7439589d80e6377edbf2ca4b43dsamebimport static com.google.inject.multibindings.OptionalBinder.javaOptionalOfProvider; 29af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport static com.google.inject.multibindings.OptionalBinder.optionalOfJavaxProvider; 30af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport static com.google.inject.multibindings.OptionalBinder.optionalOfProvider; 314e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static com.google.inject.multibindings.SpiUtils.BindType.INSTANCE; 324e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static com.google.inject.multibindings.SpiUtils.BindType.LINKED; 334e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static com.google.inject.multibindings.SpiUtils.BindType.PROVIDER_INSTANCE; 34af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport static com.google.inject.multibindings.SpiUtils.BindType.PROVIDER_KEY; 354e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static com.google.inject.multibindings.SpiUtils.VisitType.BOTH; 364e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static com.google.inject.multibindings.SpiUtils.VisitType.INJECTOR; 374e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static com.google.inject.multibindings.SpiUtils.VisitType.MODULE; 384e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static junit.framework.Assert.assertEquals; 394faa20e3081448792933834aedfe972add806292Sam Berlinimport static junit.framework.Assert.assertFalse; 404e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static junit.framework.Assert.assertNotNull; 41af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport static junit.framework.Assert.assertNull; 424e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static junit.framework.Assert.assertTrue; 434e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport static junit.framework.Assert.fail; 444e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 45af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.common.base.Objects; 46af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.common.base.Optional; 47af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.common.collect.ImmutableMap; 486c69bcf53d4122b0f05f44783c0d8a61afd83911Christian Edward Gruberimport com.google.common.collect.ImmutableSet; 49b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.collect.Lists; 50c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlinimport com.google.common.collect.Maps; 51c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlinimport com.google.common.collect.Multimap; 52c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlinimport com.google.common.collect.MultimapBuilder; 53c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlinimport com.google.common.collect.Sets; 544e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Binding; 554e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Guice; 564e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Injector; 574e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Key; 584e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Module; 59af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Provider; 604e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.TypeLiteral; 61c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlinimport com.google.inject.multibindings.Indexer.IndexedBinding; 62c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlinimport com.google.inject.multibindings.MapBinder.RealMapBinder.ProviderMapEntry; 63af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.multibindings.OptionalBinder.Source; 644e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.spi.DefaultBindingTargetVisitor; 654e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.spi.Element; 664e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.spi.Elements; 674e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.spi.InstanceBinding; 684e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.spi.LinkedKeyBinding; 694e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.spi.ProviderInstanceBinding; 70af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.ProviderKeyBinding; 714e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.spi.ProviderLookup; 724e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 73b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport java.util.HashSet; 74b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport java.util.List; 75b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport java.util.Map; 76b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport java.util.Set; 77b7a02b02d81c830d148355c90bc309bcd66fb592sberlin 784e11457f34addf5d10fe0c31cefd54c75c37b540sberlin/** 794e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Utilities for testing the Multibinder & MapBinder extension SPI. 804e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * 814e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @author sameb@google.com (Sam Berlin) 824e11457f34addf5d10fe0c31cefd54c75c37b540sberlin */ 834e11457f34addf5d10fe0c31cefd54c75c37b540sberlinpublic class SpiUtils { 844e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 851d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private static final boolean HAS_JAVA_OPTIONAL; 861d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb static { 871d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Class<?> optional = null; 881d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb try { 891d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb optional = Class.forName("java.util.Optional"); 901d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } catch (ClassNotFoundException ignored) {} 911d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb HAS_JAVA_OPTIONAL = optional != null; 921d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 931d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 944e11457f34addf5d10fe0c31cefd54c75c37b540sberlin /** The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both. */ 954e11457f34addf5d10fe0c31cefd54c75c37b540sberlin enum VisitType { INJECTOR, MODULE, BOTH } 964e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 974e11457f34addf5d10fe0c31cefd54c75c37b540sberlin /** 984e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Asserts that MapBinderBinding visitors for work correctly. 994e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * 1004e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param <T> The type of the binding 1014e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param mapKey The key the map belongs to. 1024e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param keyType the TypeLiteral of the key of the map 1034e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param valueType the TypeLiteral of the value of the map 1044e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param modules The modules that define the mapbindings 1054e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both. 1064e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param allowDuplicates If duplicates are allowed. 1074e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param expectedMapBindings The number of other mapbinders we expect to see. 1084e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param results The kind of bindings contained in the mapbinder. 1094e11457f34addf5d10fe0c31cefd54c75c37b540sberlin */ 1104e11457f34addf5d10fe0c31cefd54c75c37b540sberlin static <T> void assertMapVisitor(Key<T> mapKey, TypeLiteral<?> keyType, TypeLiteral<?> valueType, 1114e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Iterable<? extends Module> modules, VisitType visitType, boolean allowDuplicates, 1124e11457f34addf5d10fe0c31cefd54c75c37b540sberlin int expectedMapBindings, MapResult... results) { 1134e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(visitType == null) { 1144e11457f34addf5d10fe0c31cefd54c75c37b540sberlin fail("must test something"); 1154e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1164e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1174e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if (visitType == BOTH || visitType == INJECTOR) { 1184e11457f34addf5d10fe0c31cefd54c75c37b540sberlin mapInjectorTest(mapKey, keyType, valueType, modules, allowDuplicates, expectedMapBindings, 1194e11457f34addf5d10fe0c31cefd54c75c37b540sberlin results); 1204e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1214e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1224e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if (visitType == BOTH || visitType == MODULE) { 1234e11457f34addf5d10fe0c31cefd54c75c37b540sberlin mapModuleTest(mapKey, keyType, valueType, modules, allowDuplicates, expectedMapBindings, 1244e11457f34addf5d10fe0c31cefd54c75c37b540sberlin results); 1254e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1264e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1274e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1284e11457f34addf5d10fe0c31cefd54c75c37b540sberlin @SuppressWarnings("unchecked") 1294e11457f34addf5d10fe0c31cefd54c75c37b540sberlin private static <T> void mapInjectorTest(Key<T> mapKey, TypeLiteral<?> keyType, 1304e11457f34addf5d10fe0c31cefd54c75c37b540sberlin TypeLiteral<?> valueType, Iterable<? extends Module> modules, boolean allowDuplicates, 1314e11457f34addf5d10fe0c31cefd54c75c37b540sberlin int expectedMapBindings, MapResult... results) { 1324e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Injector injector = Guice.createInjector(modules); 1334e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Visitor<T> visitor = new Visitor<T>(); 1344e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Binding<T> mapBinding = injector.getBinding(mapKey); 1354e11457f34addf5d10fe0c31cefd54c75c37b540sberlin MapBinderBinding<T> mapbinder = (MapBinderBinding<T>)mapBinding.acceptTargetVisitor(visitor); 1364e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertNotNull(mapbinder); 1374e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals(keyType, mapbinder.getKeyTypeLiteral()); 1384e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals(valueType, mapbinder.getValueTypeLiteral()); 1394e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals(allowDuplicates, mapbinder.permitsDuplicates()); 1404e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<Map.Entry<?, Binding<?>>> entries = Lists.newArrayList(mapbinder.getEntries()); 1414e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<MapResult> mapResults = Lists.newArrayList(results); 1424e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals("wrong entries, expected: " + mapResults + ", but was: " + entries, 1434e11457f34addf5d10fe0c31cefd54c75c37b540sberlin mapResults.size(), entries.size()); 1444e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1454e11457f34addf5d10fe0c31cefd54c75c37b540sberlin for(MapResult result : mapResults) { 1464e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Map.Entry<?, Binding<?>> found = null; 1474e11457f34addf5d10fe0c31cefd54c75c37b540sberlin for(Map.Entry<?, Binding<?>> entry : entries) { 1484e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Object key = entry.getKey(); 1494e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Binding<?> value = entry.getValue(); 150af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if(key.equals(result.k) && matches(value, result.v)) { 151af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber found = entry; 1524e11457f34addf5d10fe0c31cefd54c75c37b540sberlin break; 1534e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1544e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1554e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(found == null) { 1564e11457f34addf5d10fe0c31cefd54c75c37b540sberlin fail("Could not find entry: " + result + " in remaining entries: " + entries); 1574e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else { 158af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue("mapBinder doesn't contain: " + found.getValue(), 159af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber mapbinder.containsElement(found.getValue())); 1604e11457f34addf5d10fe0c31cefd54c75c37b540sberlin entries.remove(found); 1614e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1624e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1634e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1644e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(!entries.isEmpty()) { 1654e11457f34addf5d10fe0c31cefd54c75c37b540sberlin fail("Found all entries of: " + mapResults + ", but more were left over: " + entries); 1664e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1674e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1683338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin Key<?> mapOfJavaxProvider = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType)); 1693338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin Key<?> mapOfProvider = mapKey.ofType(mapOfProviderOf(keyType, valueType)); 1703338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin Key<?> mapOfSetOfProvider = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType)); 1713338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin Key<?> mapOfSet = mapKey.ofType(mapOf(keyType, setOf(valueType))); 1723338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin Key<?> setOfEntry = mapKey.ofType(setOf(entryOfProviderOf(keyType, valueType))); 173615fd2bc2397e2966d682759aae2aad7e8a3db1eflan Key<?> collectionOfProvidersOfEntryOfProvider = 174615fd2bc2397e2966d682759aae2aad7e8a3db1eflan mapKey.ofType(collectionOfProvidersOf(entryOfProviderOf(keyType, valueType))); 175bed1413751f54dc6804dcb2a4c28300081788603flan Key<?> collectionOfJavaxProvidersOfEntryOfProvider = 176bed1413751f54dc6804dcb2a4c28300081788603flan mapKey.ofType(collectionOfJavaxProvidersOf(entryOfProviderOf(keyType, valueType))); 1774e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean entrySetMatch = false; 1783338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin boolean mapJavaxProviderMatch = false; 1794e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean mapProviderMatch = false; 1804e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean mapSetMatch = false; 1814e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean mapSetProviderMatch = false; 182615fd2bc2397e2966d682759aae2aad7e8a3db1eflan boolean collectionOfProvidersOfEntryOfProviderMatch = false; 183bed1413751f54dc6804dcb2a4c28300081788603flan boolean collectionOfJavaxProvidersOfEntryOfProviderMatch = false; 1844e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<Object> otherMapBindings = Lists.newArrayList(); 1854e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<Binding> otherMatches = Lists.newArrayList(); 186c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin Multimap<Object, IndexedBinding> indexedEntries = 187c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin MultimapBuilder.hashKeys().hashSetValues().build(); 188c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin Indexer indexer = new Indexer(injector); 189c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin int duplicates = 0; 1904e11457f34addf5d10fe0c31cefd54c75c37b540sberlin for(Binding b : injector.getAllBindings().values()) { 1914e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean contains = mapbinder.containsElement(b); 1924e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Object visited = b.acceptTargetVisitor(visitor); 1934e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(visited instanceof MapBinderBinding) { 1944e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(visited.equals(mapbinder)) { 1954e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 1964e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else { 1974e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherMapBindings.add(visited); 1984e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1994e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else if(b.getKey().equals(mapOfProvider)) { 2004e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 2014e11457f34addf5d10fe0c31cefd54c75c37b540sberlin mapProviderMatch = true; 2023338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin } else if (b.getKey().equals(mapOfJavaxProvider)) { 2033338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin assertTrue(contains); 2043338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin mapJavaxProviderMatch = true; 2054e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else if(b.getKey().equals(mapOfSet)) { 2064e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 2074e11457f34addf5d10fe0c31cefd54c75c37b540sberlin mapSetMatch = true; 2084e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else if(b.getKey().equals(mapOfSetOfProvider)) { 2094e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 2104e11457f34addf5d10fe0c31cefd54c75c37b540sberlin mapSetProviderMatch = true; 2114e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else if(b.getKey().equals(setOfEntry)) { 2124e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 2134e11457f34addf5d10fe0c31cefd54c75c37b540sberlin entrySetMatch = true; 2144e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // Validate that this binding is also a MultibinderBinding. 2154e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding); 216615fd2bc2397e2966d682759aae2aad7e8a3db1eflan } else if(b.getKey().equals(collectionOfProvidersOfEntryOfProvider)) { 217615fd2bc2397e2966d682759aae2aad7e8a3db1eflan assertTrue(contains); 218615fd2bc2397e2966d682759aae2aad7e8a3db1eflan collectionOfProvidersOfEntryOfProviderMatch = true; 219bed1413751f54dc6804dcb2a4c28300081788603flan } else if(b.getKey().equals(collectionOfJavaxProvidersOfEntryOfProvider)) { 220bed1413751f54dc6804dcb2a4c28300081788603flan assertTrue(contains); 221bed1413751f54dc6804dcb2a4c28300081788603flan collectionOfJavaxProvidersOfEntryOfProviderMatch = true; 2224e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else if (contains) { 223c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin if (b instanceof ProviderInstanceBinding) { 224c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin ProviderInstanceBinding<?> pib = (ProviderInstanceBinding<?>)b; 225c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin if (pib.getUserSuppliedProvider() instanceof ProviderMapEntry) { 226e5abfb2c1e4ff087bafa5d925fe0598d968b803bSam Berlin // weird casting required to workaround compilation issues with jdk6 227e5abfb2c1e4ff087bafa5d925fe0598d968b803bSam Berlin ProviderMapEntry<?, ?> pme = 228e5abfb2c1e4ff087bafa5d925fe0598d968b803bSam Berlin (ProviderMapEntry<?, ?>) (Provider) pib.getUserSuppliedProvider(); 229c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin Binding<?> valueBinding = injector.getBinding(pme.getValueKey()); 230c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin if (indexer.isIndexable(valueBinding) 231c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin && !indexedEntries.put(pme.getKey(), valueBinding.acceptTargetVisitor(indexer))) { 232c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin duplicates++; 233c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin } 234c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin } 235c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin } 2364e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherMatches.add(b); 2374e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 2384e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 2394e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 2404e11457f34addf5d10fe0c31cefd54c75c37b540sberlin int sizeOfOther = otherMatches.size(); 2414e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(allowDuplicates) { 2424e11457f34addf5d10fe0c31cefd54c75c37b540sberlin sizeOfOther--; // account for 1 duplicate binding 2434e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 244615fd2bc2397e2966d682759aae2aad7e8a3db1eflan // Multiply by two because each has a value and Map.Entry. 245615fd2bc2397e2966d682759aae2aad7e8a3db1eflan int expectedSize = 2 * (mapResults.size() + duplicates); 246615fd2bc2397e2966d682759aae2aad7e8a3db1eflan assertEquals("Incorrect other matches: " + otherMatches, expectedSize, sizeOfOther); 2474e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(entrySetMatch); 2484e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(mapProviderMatch); 2493338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin assertTrue(mapJavaxProviderMatch); 250615fd2bc2397e2966d682759aae2aad7e8a3db1eflan assertTrue(collectionOfProvidersOfEntryOfProviderMatch); 251bed1413751f54dc6804dcb2a4c28300081788603flan assertTrue(collectionOfJavaxProvidersOfEntryOfProviderMatch); 2524e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals(allowDuplicates, mapSetMatch); 2534e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals(allowDuplicates, mapSetProviderMatch); 2544e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals("other MapBindings found: " + otherMapBindings, expectedMapBindings, 2554e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherMapBindings.size()); 2564e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 2574e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 2584e11457f34addf5d10fe0c31cefd54c75c37b540sberlin @SuppressWarnings("unchecked") 2594e11457f34addf5d10fe0c31cefd54c75c37b540sberlin private static <T> void mapModuleTest(Key<T> mapKey, TypeLiteral<?> keyType, 2604e11457f34addf5d10fe0c31cefd54c75c37b540sberlin TypeLiteral<?> valueType, Iterable<? extends Module> modules, boolean allowDuplicates, 2614e11457f34addf5d10fe0c31cefd54c75c37b540sberlin int expectedMapBindings, MapResult... results) { 2626c69bcf53d4122b0f05f44783c0d8a61afd83911Christian Edward Gruber Set<Element> elements = ImmutableSet.copyOf(Elements.getElements(modules)); 2634e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Visitor<T> visitor = new Visitor<T>(); 2644e11457f34addf5d10fe0c31cefd54c75c37b540sberlin MapBinderBinding<T> mapbinder = null; 265c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin Map<Key<?>, Binding<?>> keyMap = Maps.newHashMap(); 2664e11457f34addf5d10fe0c31cefd54c75c37b540sberlin for(Element element : elements) { 267c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin if(element instanceof Binding) { 268c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin Binding<?> binding = (Binding<?>)element; 269c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin keyMap.put(binding.getKey(), binding); 270c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin if (binding.getKey().equals(mapKey)) { 271c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin mapbinder = (MapBinderBinding<T>)((Binding<T>)binding).acceptTargetVisitor(visitor); 272c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin } 2734e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 2744e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 2754e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertNotNull(mapbinder); 2764e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 2774e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals(keyType, mapbinder.getKeyTypeLiteral()); 2784e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals(valueType, mapbinder.getValueTypeLiteral()); 2794e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<MapResult> mapResults = Lists.newArrayList(results); 2804e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 2813338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin Key<?> mapOfProvider = mapKey.ofType(mapOfProviderOf(keyType, valueType)); 282615fd2bc2397e2966d682759aae2aad7e8a3db1eflan Key<?> mapOfJavaxProvider = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType)); 2833338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin Key<?> mapOfSetOfProvider = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType)); 2843338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin Key<?> mapOfSet = mapKey.ofType(mapOf(keyType, setOf(valueType))); 2853338a48b6abb9a0641dc3c2c169bb59b9960dc15Sam Berlin Key<?> setOfEntry = mapKey.ofType(setOf(entryOfProviderOf(keyType, valueType))); 2864faa20e3081448792933834aedfe972add806292Sam Berlin Key<?> collectionOfProvidersOfEntry = 2874faa20e3081448792933834aedfe972add806292Sam Berlin mapKey.ofType(collectionOfProvidersOf(entryOfProviderOf(keyType, valueType))); 288bed1413751f54dc6804dcb2a4c28300081788603flan Key<?> collectionOfJavaxProvidersOfEntry = 289bed1413751f54dc6804dcb2a4c28300081788603flan mapKey.ofType(collectionOfJavaxProvidersOf(entryOfProviderOf(keyType, valueType))); 2904e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean entrySetMatch = false; 2914e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean mapProviderMatch = false; 292615fd2bc2397e2966d682759aae2aad7e8a3db1eflan boolean mapJavaxProviderMatch = false; 293615fd2bc2397e2966d682759aae2aad7e8a3db1eflan boolean mapSetMatch = false; 2944e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean mapSetProviderMatch = false; 295bed1413751f54dc6804dcb2a4c28300081788603flan boolean collectionOfProvidersOfEntryMatch = false; 296bed1413751f54dc6804dcb2a4c28300081788603flan boolean collectionOfJavaxProvidersOfEntryMatch = false; 2974e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<Object> otherMapBindings = Lists.newArrayList(); 2984e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<Element> otherMatches = Lists.newArrayList(); 2994e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<Element> otherElements = Lists.newArrayList(); 300c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin Indexer indexer = new Indexer(null); 301c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin Multimap<Object, IndexedBinding> indexedEntries = 302c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin MultimapBuilder.hashKeys().hashSetValues().build(); 303c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin int duplicates = 0; 3044e11457f34addf5d10fe0c31cefd54c75c37b540sberlin for(Element element : elements) { 3054e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean contains = mapbinder.containsElement(element); 3064e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(!contains) { 3074e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherElements.add(element); 3084e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 3094e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean matched = false; 3104e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Key key = null; 3114e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Binding b = null; 3124e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(element instanceof Binding) { 3134e11457f34addf5d10fe0c31cefd54c75c37b540sberlin b = (Binding)element; 314c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin if (b instanceof ProviderInstanceBinding) { 315c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin ProviderInstanceBinding<?> pb = (ProviderInstanceBinding<?>) b; 316c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin if (pb.getUserSuppliedProvider() instanceof ProviderMapEntry) { 317e5abfb2c1e4ff087bafa5d925fe0598d968b803bSam Berlin // weird casting required to workaround jdk6 compilation problems 318e5abfb2c1e4ff087bafa5d925fe0598d968b803bSam Berlin ProviderMapEntry<?, ?> pme = 319e5abfb2c1e4ff087bafa5d925fe0598d968b803bSam Berlin (ProviderMapEntry<?, ?>) (Provider) pb.getUserSuppliedProvider(); 320c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin Binding<?> valueBinding = keyMap.get(pme.getValueKey()); 321c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin if (indexer.isIndexable(valueBinding) 322c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin && !indexedEntries.put(pme.getKey(), valueBinding.acceptTargetVisitor(indexer))) { 323c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin duplicates++; 324c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin } 325c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin } 326c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin } 327c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin 3284e11457f34addf5d10fe0c31cefd54c75c37b540sberlin key = b.getKey(); 3294e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Object visited = b.acceptTargetVisitor(visitor); 3304e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(visited instanceof MapBinderBinding) { 3314e11457f34addf5d10fe0c31cefd54c75c37b540sberlin matched = true; 3324e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(visited.equals(mapbinder)) { 3334e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 3344e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else { 3354e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherMapBindings.add(visited); 3364e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 3374e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 3384e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else if(element instanceof ProviderLookup) { 3394e11457f34addf5d10fe0c31cefd54c75c37b540sberlin key = ((ProviderLookup)element).getKey(); 3404e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 3414e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 3424e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(!matched && key != null) { 3434e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(key.equals(mapOfProvider)) { 3444e11457f34addf5d10fe0c31cefd54c75c37b540sberlin matched = true; 3454e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 3464e11457f34addf5d10fe0c31cefd54c75c37b540sberlin mapProviderMatch = true; 347615fd2bc2397e2966d682759aae2aad7e8a3db1eflan } else if(key.equals(mapOfJavaxProvider)) { 348615fd2bc2397e2966d682759aae2aad7e8a3db1eflan matched = true; 349615fd2bc2397e2966d682759aae2aad7e8a3db1eflan assertTrue(contains); 350615fd2bc2397e2966d682759aae2aad7e8a3db1eflan mapJavaxProviderMatch = true; 3514e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else if(key.equals(mapOfSet)) { 3524e11457f34addf5d10fe0c31cefd54c75c37b540sberlin matched = true; 3534e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 3544e11457f34addf5d10fe0c31cefd54c75c37b540sberlin mapSetMatch = true; 3554e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else if(key.equals(mapOfSetOfProvider)) { 3564e11457f34addf5d10fe0c31cefd54c75c37b540sberlin matched = true; 3574e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 3584e11457f34addf5d10fe0c31cefd54c75c37b540sberlin mapSetProviderMatch = true; 3594e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else if(key.equals(setOfEntry)) { 3604e11457f34addf5d10fe0c31cefd54c75c37b540sberlin matched = true; 3614e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 3624e11457f34addf5d10fe0c31cefd54c75c37b540sberlin entrySetMatch = true; 3634e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // Validate that this binding is also a MultibinderBinding. 3644e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(b != null) { 3654e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding); 3664e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 3674faa20e3081448792933834aedfe972add806292Sam Berlin } else if(key.equals(collectionOfProvidersOfEntry)) { 3684faa20e3081448792933834aedfe972add806292Sam Berlin matched = true; 3694faa20e3081448792933834aedfe972add806292Sam Berlin assertTrue(contains); 370bed1413751f54dc6804dcb2a4c28300081788603flan collectionOfProvidersOfEntryMatch = true; 371bed1413751f54dc6804dcb2a4c28300081788603flan } else if(key.equals(collectionOfJavaxProvidersOfEntry)) { 372bed1413751f54dc6804dcb2a4c28300081788603flan matched = true; 373bed1413751f54dc6804dcb2a4c28300081788603flan assertTrue(contains); 374bed1413751f54dc6804dcb2a4c28300081788603flan collectionOfJavaxProvidersOfEntryMatch = true; 3754e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 3764e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 3774e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 3784faa20e3081448792933834aedfe972add806292Sam Berlin if (!matched && contains) { 3794e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherMatches.add(element); 3804e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 3814e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 3824e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 3834e11457f34addf5d10fe0c31cefd54c75c37b540sberlin int otherMatchesSize = otherMatches.size(); 3844faa20e3081448792933834aedfe972add806292Sam Berlin if (allowDuplicates) { 3854e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherMatchesSize--; // allow for 1 duplicate binding 3864e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 387615fd2bc2397e2966d682759aae2aad7e8a3db1eflan // Multiply by 3 because each has a value, ProviderLookup, and Map.Entry 388615fd2bc2397e2966d682759aae2aad7e8a3db1eflan int expectedSize = (mapResults.size() + duplicates) * 3; 389615fd2bc2397e2966d682759aae2aad7e8a3db1eflan assertEquals("incorrect number of contains, leftover matches: " + otherMatches, 390615fd2bc2397e2966d682759aae2aad7e8a3db1eflan expectedSize, otherMatchesSize); 3914e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 3924e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(entrySetMatch); 3934e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(mapProviderMatch); 394615fd2bc2397e2966d682759aae2aad7e8a3db1eflan assertTrue(mapJavaxProviderMatch); 395bed1413751f54dc6804dcb2a4c28300081788603flan assertTrue(collectionOfProvidersOfEntryMatch); 396bed1413751f54dc6804dcb2a4c28300081788603flan assertTrue(collectionOfJavaxProvidersOfEntryMatch); 3974e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals(allowDuplicates, mapSetMatch); 3984e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals(allowDuplicates, mapSetProviderMatch); 3994e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals("other MapBindings found: " + otherMapBindings, expectedMapBindings, 4004e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherMapBindings.size()); 4014e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 4024e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // Validate that we can construct an injector out of the remaining bindings. 4034e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Guice.createInjector(Elements.getModule(otherElements)); 4044e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 4054e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 4064e11457f34addf5d10fe0c31cefd54c75c37b540sberlin /** 4074e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Asserts that MultibinderBinding visitors work correctly. 4084e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * 4094e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param <T> The type of the binding 4104e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param setKey The key the set belongs to. 4114e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param elementType the TypeLiteral of the element 4124e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param modules The modules that define the multibindings 4134e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both. 4144e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param allowDuplicates If duplicates are allowed. 4154e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param expectedMultibindings The number of other multibinders we expect to see. 4164e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param results The kind of bindings contained in the multibinder. 4174e11457f34addf5d10fe0c31cefd54c75c37b540sberlin */ 4189c8b61815fa15ee3457b9c816afe24a6fdaf7014flan static <T> void assertSetVisitor(Key<Set<T>> setKey, TypeLiteral<?> elementType, 4194e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Iterable<? extends Module> modules, VisitType visitType, boolean allowDuplicates, 4204e11457f34addf5d10fe0c31cefd54c75c37b540sberlin int expectedMultibindings, BindResult... results) { 4214e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(visitType == null) { 4224e11457f34addf5d10fe0c31cefd54c75c37b540sberlin fail("must test something"); 4234e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 4244e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 4254e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(visitType == BOTH || visitType == INJECTOR) { 4269c8b61815fa15ee3457b9c816afe24a6fdaf7014flan setInjectorTest(setKey, elementType, modules, allowDuplicates, 4274faa20e3081448792933834aedfe972add806292Sam Berlin expectedMultibindings, results); 4284e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 4294e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 4304e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(visitType == BOTH || visitType == MODULE) { 4319c8b61815fa15ee3457b9c816afe24a6fdaf7014flan setModuleTest(setKey, elementType, modules, allowDuplicates, 4324faa20e3081448792933834aedfe972add806292Sam Berlin expectedMultibindings, results); 4334e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 4344e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 4354e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 4364e11457f34addf5d10fe0c31cefd54c75c37b540sberlin @SuppressWarnings("unchecked") 4379c8b61815fa15ee3457b9c816afe24a6fdaf7014flan private static <T> void setInjectorTest(Key<Set<T>> setKey, TypeLiteral<?> elementType, 4384e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Iterable<? extends Module> modules, boolean allowDuplicates, int otherMultibindings, 4394e11457f34addf5d10fe0c31cefd54c75c37b540sberlin BindResult... results) { 4409c8b61815fa15ee3457b9c816afe24a6fdaf7014flan Key<?> collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType)); 441bed1413751f54dc6804dcb2a4c28300081788603flan Key<?> collectionOfJavaxProvidersKey = 442bed1413751f54dc6804dcb2a4c28300081788603flan setKey.ofType(collectionOfJavaxProvidersOf(elementType)); 4434e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Injector injector = Guice.createInjector(modules); 4444faa20e3081448792933834aedfe972add806292Sam Berlin Visitor<Set<T>> visitor = new Visitor<Set<T>>(); 4454faa20e3081448792933834aedfe972add806292Sam Berlin Binding<Set<T>> binding = injector.getBinding(setKey); 4464faa20e3081448792933834aedfe972add806292Sam Berlin MultibinderBinding<Set<T>> multibinder = 4474faa20e3081448792933834aedfe972add806292Sam Berlin (MultibinderBinding<Set<T>>)binding.acceptTargetVisitor(visitor); 4484e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertNotNull(multibinder); 4494e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals(elementType, multibinder.getElementTypeLiteral()); 4504e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals(allowDuplicates, multibinder.permitsDuplicates()); 4514e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<Binding<?>> elements = Lists.newArrayList(multibinder.getElements()); 4524e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<BindResult> bindResults = Lists.newArrayList(results); 453c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin assertEquals("wrong bind elements, expected: " + bindResults 454c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin + ", but was: " + multibinder.getElements(), 4554e11457f34addf5d10fe0c31cefd54c75c37b540sberlin bindResults.size(), elements.size()); 4564faa20e3081448792933834aedfe972add806292Sam Berlin 4574e11457f34addf5d10fe0c31cefd54c75c37b540sberlin for(BindResult result : bindResults) { 4584e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Binding found = null; 4594e11457f34addf5d10fe0c31cefd54c75c37b540sberlin for(Binding item : elements) { 460af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (matches(item, result)) { 461af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber found = item; 4624e11457f34addf5d10fe0c31cefd54c75c37b540sberlin break; 4634e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 4644e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 4654e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(found == null) { 4664e11457f34addf5d10fe0c31cefd54c75c37b540sberlin fail("Could not find element: " + result + " in remaining elements: " + elements); 4674e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else { 4684e11457f34addf5d10fe0c31cefd54c75c37b540sberlin elements.remove(found); 4694e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 4704e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 4714e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 4724e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(!elements.isEmpty()) { 4734e11457f34addf5d10fe0c31cefd54c75c37b540sberlin fail("Found all elements of: " + bindResults + ", but more were left over: " + elements); 4744e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 475c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin 4764e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Set<Binding> setOfElements = new HashSet<Binding>(multibinder.getElements()); 477c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin Set<IndexedBinding> setOfIndexed = Sets.newHashSet(); 478c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin Indexer indexer = new Indexer(injector); 479c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin for (Binding<?> oneBinding : setOfElements) { 480c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin setOfIndexed.add(oneBinding.acceptTargetVisitor(indexer)); 481c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin } 482c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin 4834e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<Object> otherMultibinders = Lists.newArrayList(); 4844e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<Binding> otherContains = Lists.newArrayList(); 4854faa20e3081448792933834aedfe972add806292Sam Berlin boolean collectionOfProvidersMatch = false; 486bed1413751f54dc6804dcb2a4c28300081788603flan boolean collectionOfJavaxProvidersMatch = false; 4874e11457f34addf5d10fe0c31cefd54c75c37b540sberlin for(Binding b : injector.getAllBindings().values()) { 4884e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean contains = multibinder.containsElement(b); 4894faa20e3081448792933834aedfe972add806292Sam Berlin Key key = b.getKey(); 4904e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Object visited = b.acceptTargetVisitor(visitor); 4914e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(visited != null) { 4924e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(visited.equals(multibinder)) { 4934e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 4944e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else { 4954e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherMultibinders.add(visited); 4964e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 4974e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else if(setOfElements.contains(b)) { 4984e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 4994faa20e3081448792933834aedfe972add806292Sam Berlin } else if (key.equals(collectionOfProvidersKey)) { 5004faa20e3081448792933834aedfe972add806292Sam Berlin assertTrue(contains); 5014faa20e3081448792933834aedfe972add806292Sam Berlin collectionOfProvidersMatch = true; 502bed1413751f54dc6804dcb2a4c28300081788603flan } else if (key.equals(collectionOfJavaxProvidersKey)) { 503bed1413751f54dc6804dcb2a4c28300081788603flan assertTrue(contains); 504bed1413751f54dc6804dcb2a4c28300081788603flan collectionOfJavaxProvidersMatch = true; 5054faa20e3081448792933834aedfe972add806292Sam Berlin } else if (contains) { 506c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin if (!indexer.isIndexable(b) || !setOfIndexed.contains(b.acceptTargetVisitor(indexer))) { 507c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin otherContains.add(b); 508c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin } 5094e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5104e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5114faa20e3081448792933834aedfe972add806292Sam Berlin 5124faa20e3081448792933834aedfe972add806292Sam Berlin assertTrue(collectionOfProvidersMatch); 513bed1413751f54dc6804dcb2a4c28300081788603flan assertTrue(collectionOfJavaxProvidersMatch); 5144faa20e3081448792933834aedfe972add806292Sam Berlin 5154e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(allowDuplicates) { 5164e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals("contained more than it should: " + otherContains, 1, otherContains.size()); 5174e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else { 5184e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue("contained more than it should: " + otherContains, otherContains.isEmpty()); 5194e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5204e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals("other multibindings found: " + otherMultibinders, otherMultibindings, 5214e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherMultibinders.size()); 5224e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 5234e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5244e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 5254e11457f34addf5d10fe0c31cefd54c75c37b540sberlin @SuppressWarnings("unchecked") 5269c8b61815fa15ee3457b9c816afe24a6fdaf7014flan private static <T> void setModuleTest(Key<Set<T>> setKey, TypeLiteral<?> elementType, 5274e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Iterable<? extends Module> modules, boolean allowDuplicates, int otherMultibindings, 5284e11457f34addf5d10fe0c31cefd54c75c37b540sberlin BindResult... results) { 5299c8b61815fa15ee3457b9c816afe24a6fdaf7014flan Key<?> collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType)); 530bed1413751f54dc6804dcb2a4c28300081788603flan Key<?> collectionOfJavaxProvidersKey = 531bed1413751f54dc6804dcb2a4c28300081788603flan setKey.ofType(collectionOfJavaxProvidersOf(elementType)); 5324e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<BindResult> bindResults = Lists.newArrayList(results); 5334e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<Element> elements = Elements.getElements(modules); 5344e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Visitor<T> visitor = new Visitor<T>(); 5354faa20e3081448792933834aedfe972add806292Sam Berlin MultibinderBinding<Set<T>> multibinder = null; 5364e11457f34addf5d10fe0c31cefd54c75c37b540sberlin for(Element element : elements) { 5374e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(element instanceof Binding && ((Binding)element).getKey().equals(setKey)) { 5384faa20e3081448792933834aedfe972add806292Sam Berlin multibinder = (MultibinderBinding<Set<T>>)((Binding)element).acceptTargetVisitor(visitor); 5394e11457f34addf5d10fe0c31cefd54c75c37b540sberlin break; 5404e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5414e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5424e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertNotNull(multibinder); 5434e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 5444e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals(elementType, multibinder.getElementTypeLiteral()); 5454e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<Object> otherMultibinders = Lists.newArrayList(); 5464e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Set<Element> otherContains = new HashSet<Element>(); 5474e11457f34addf5d10fe0c31cefd54c75c37b540sberlin List<Element> otherElements = Lists.newArrayList(); 548c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin int duplicates = 0; 549c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin Set<IndexedBinding> setOfIndexed = Sets.newHashSet(); 550c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin Indexer indexer = new Indexer(null); 5514faa20e3081448792933834aedfe972add806292Sam Berlin boolean collectionOfProvidersMatch = false; 552bed1413751f54dc6804dcb2a4c28300081788603flan boolean collectionOfJavaxProvidersMatch = false; 5534e11457f34addf5d10fe0c31cefd54c75c37b540sberlin for(Element element : elements) { 5544e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean contains = multibinder.containsElement(element); 5554e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(!contains) { 5564e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherElements.add(element); 5574e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5584e11457f34addf5d10fe0c31cefd54c75c37b540sberlin boolean matched = false; 5594faa20e3081448792933834aedfe972add806292Sam Berlin Key key = null; 5604e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(element instanceof Binding) { 5614e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Binding binding = (Binding)element; 562c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin if (indexer.isIndexable(binding) 563c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin && !setOfIndexed.add((IndexedBinding) binding.acceptTargetVisitor(indexer))) { 564c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin duplicates++; 565c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin } 5664faa20e3081448792933834aedfe972add806292Sam Berlin key = binding.getKey(); 5674e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Object visited = binding.acceptTargetVisitor(visitor); 5684e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(visited != null) { 5694e11457f34addf5d10fe0c31cefd54c75c37b540sberlin matched = true; 5704e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(visited.equals(multibinder)) { 5714e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertTrue(contains); 5724e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else { 5734e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherMultibinders.add(visited); 5744e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5754e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5764e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5774faa20e3081448792933834aedfe972add806292Sam Berlin 5784faa20e3081448792933834aedfe972add806292Sam Berlin if (collectionOfProvidersKey.equals(key)) { 5794faa20e3081448792933834aedfe972add806292Sam Berlin assertTrue(contains); 5804faa20e3081448792933834aedfe972add806292Sam Berlin assertFalse(matched); 5814faa20e3081448792933834aedfe972add806292Sam Berlin collectionOfProvidersMatch = true; 582bed1413751f54dc6804dcb2a4c28300081788603flan } else if (collectionOfJavaxProvidersKey.equals(key)) { 583bed1413751f54dc6804dcb2a4c28300081788603flan assertTrue(contains); 584bed1413751f54dc6804dcb2a4c28300081788603flan assertFalse(matched); 585bed1413751f54dc6804dcb2a4c28300081788603flan collectionOfJavaxProvidersMatch = true; 5864faa20e3081448792933834aedfe972add806292Sam Berlin } else if (!matched && contains) { 5874e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherContains.add(element); 5884e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5894e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5904faa20e3081448792933834aedfe972add806292Sam Berlin 5914e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(allowDuplicates) { 592c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin assertEquals("wrong contained elements: " + otherContains, 593c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin bindResults.size() + 1 + duplicates, otherContains.size()); 5944e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else { 595c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin assertEquals("wrong contained elements: " + otherContains, 596c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin bindResults.size() + duplicates, otherContains.size()); 5974e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 5984faa20e3081448792933834aedfe972add806292Sam Berlin 5994e11457f34addf5d10fe0c31cefd54c75c37b540sberlin assertEquals("other multibindings found: " + otherMultibinders, otherMultibindings, 6004e11457f34addf5d10fe0c31cefd54c75c37b540sberlin otherMultibinders.size()); 6014faa20e3081448792933834aedfe972add806292Sam Berlin assertTrue(collectionOfProvidersMatch); 602bed1413751f54dc6804dcb2a4c28300081788603flan assertTrue(collectionOfJavaxProvidersMatch); 6034faa20e3081448792933834aedfe972add806292Sam Berlin 6044e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // Validate that we can construct an injector out of the remaining bindings. 6054e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Guice.createInjector(Elements.getModule(otherElements)); 6064e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 607af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 608af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** 609af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * Asserts that OptionalBinderBinding visitors for work correctly. 610af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 611af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * @param <T> The type of the binding 612af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * @param keyType The key OptionalBinder is binding 613af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * @param modules The modules that define the bindings 614af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) 615af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * test, or both. 616af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * @param expectedOtherOptionalBindings the # of other optional bindings we expect to see. 617af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * @param expectedDefault the expected default binding, or null if none 618af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * @param expectedActual the expected actual binding, or null if none 619842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * @param expectedUserLinkedActual the user binding that is the actual binding, used if 620842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * neither the default nor actual are set and a user binding existed for the type. 621af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 622af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static <T> void assertOptionalVisitor(Key<T> keyType, 623af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Iterable<? extends Module> modules, 624af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber VisitType visitType, 625af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber int expectedOtherOptionalBindings, 626af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber BindResult<?> expectedDefault, 627842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin BindResult<?> expectedActual, 628842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin BindResult<?> expectedUserLinkedActual) { 629af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (visitType == null) { 630af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber fail("must test something"); 631af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 632af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 6331d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb // if java.util.Optional is bound, there'll be twice as many as we expect. 6341d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (HAS_JAVA_OPTIONAL) { 6351d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb expectedOtherOptionalBindings *= 2; 6361d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 6371d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 638af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (visitType == BOTH || visitType == INJECTOR) { 639af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber optionalInjectorTest(keyType, modules, expectedOtherOptionalBindings, expectedDefault, 640842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin expectedActual, expectedUserLinkedActual); 641af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 642af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 643af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (visitType == BOTH || visitType == MODULE) { 644af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber optionalModuleTest(keyType, modules, expectedOtherOptionalBindings, expectedDefault, 645842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin expectedActual, expectedUserLinkedActual); 646af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 647af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 648af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 6491d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @SuppressWarnings({ "unchecked", "rawtypes" }) 650842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin private static <T> void optionalInjectorTest(Key<T> keyType, 651842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin Iterable<? extends Module> modules, 652842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin int expectedOtherOptionalBindings, 653842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin BindResult<?> expectedDefault, 654842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin BindResult<?> expectedActual, 655842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin BindResult<?> expectedUserLinkedActual) { 656842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin if (expectedUserLinkedActual != null) { 657842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin assertNull("cannot have actual if expecting user binding", expectedActual); 658842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin assertNull("cannot have default if expecting user binding", expectedDefault); 659842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin } 6601d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 661af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Key<Optional<T>> optionalKey = 662af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber keyType.ofType(OptionalBinder.optionalOf(keyType.getTypeLiteral())); 6631d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Key<?> javaOptionalKey = HAS_JAVA_OPTIONAL ? 6641d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb keyType.ofType(OptionalBinder.javaOptionalOf(keyType.getTypeLiteral())) : null; 665af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Injector injector = Guice.createInjector(modules); 666af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Binding<Optional<T>> optionalBinding = injector.getBinding(optionalKey); 6671d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Visitor visitor = new Visitor(); 6681d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb OptionalBinderBinding<Optional<T>> optionalBinder = 6691d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb (OptionalBinderBinding<Optional<T>>) optionalBinding.acceptTargetVisitor(visitor); 670af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertNotNull(optionalBinder); 671af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(optionalKey, optionalBinder.getKey()); 672af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 6731d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Binding<?> javaOptionalBinding = null; 6741d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb OptionalBinderBinding<?> javaOptionalBinder = null; 6751d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (HAS_JAVA_OPTIONAL) { 6761d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb javaOptionalBinding = injector.getBinding(javaOptionalKey); 6771d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb javaOptionalBinder = (OptionalBinderBinding<?>) javaOptionalBinding.acceptTargetVisitor(visitor); 6781d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertNotNull(javaOptionalBinder); 6791d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertEquals(javaOptionalKey, javaOptionalBinder.getKey()); 6801d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 6811d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 682af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (expectedDefault == null) { 683af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertNull("did not expect a default binding", optionalBinder.getDefaultBinding()); 6841d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (HAS_JAVA_OPTIONAL) { 6851d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertNull("did not expect a default binding", javaOptionalBinder.getDefaultBinding()); 6861d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 687af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else { 688af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue("expectedDefault: " + expectedDefault + ", actualDefault: " 6891d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb + optionalBinder.getDefaultBinding(), 690af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber matches(optionalBinder.getDefaultBinding(), expectedDefault)); 6911d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (HAS_JAVA_OPTIONAL) { 6921d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertTrue("expectedDefault: " + expectedDefault + ", actualDefault: " 6931d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb + javaOptionalBinder.getDefaultBinding(), 6941d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb matches(javaOptionalBinder.getDefaultBinding(), expectedDefault)); 6951d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 696af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 697af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 698842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin if (expectedActual == null && expectedUserLinkedActual == null) { 699af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertNull(optionalBinder.getActualBinding()); 7001d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (HAS_JAVA_OPTIONAL) { 7011d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertNull(javaOptionalBinder.getActualBinding()); 7021d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 703842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin } else if (expectedActual != null) { 704af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue("expectedActual: " + expectedActual + ", actualActual: " 7051d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb + optionalBinder.getActualBinding(), 706af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber matches(optionalBinder.getActualBinding(), expectedActual)); 7071d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (HAS_JAVA_OPTIONAL) { 7081d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertTrue("expectedActual: " + expectedActual + ", actualActual: " 7091d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb + javaOptionalBinder.getActualBinding(), 7101d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb matches(javaOptionalBinder.getActualBinding(), expectedActual)); 7111d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 712842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin } else if (expectedUserLinkedActual != null) { 713842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin assertTrue("expectedUserLinkedActual: " + expectedUserLinkedActual + ", actualActual: " 7141d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb + optionalBinder.getActualBinding(), 715842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin matches(optionalBinder.getActualBinding(), expectedUserLinkedActual)); 7161d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (HAS_JAVA_OPTIONAL) { 7171d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertTrue("expectedUserLinkedActual: " + expectedUserLinkedActual + ", actualActual: " 7181d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb + javaOptionalBinder.getActualBinding(), 7191d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb matches(javaOptionalBinder.getActualBinding(), expectedUserLinkedActual)); 7201d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 721af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 722af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 723af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 724af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Key<Optional<javax.inject.Provider<T>>> optionalJavaxProviderKey = 725af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber keyType.ofType(optionalOfJavaxProvider(keyType.getTypeLiteral())); 7261d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Key<?> javaOptionalJavaxProviderKey = HAS_JAVA_OPTIONAL ? 7271d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb keyType.ofType(javaOptionalOfJavaxProvider(keyType.getTypeLiteral())) : null; 728af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Key<Optional<Provider<T>>> optionalProviderKey = 729af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber keyType.ofType(optionalOfProvider(keyType.getTypeLiteral())); 7301d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Key<?> javaOptionalProviderKey = HAS_JAVA_OPTIONAL ? 7311d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb keyType.ofType(javaOptionalOfProvider(keyType.getTypeLiteral())) : null; 732af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 733af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean keyMatch = false; 734af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean optionalKeyMatch = false; 7351d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb boolean javaOptionalKeyMatch = false; 736af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean optionalJavaxProviderKeyMatch = false; 7371d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb boolean javaOptionalJavaxProviderKeyMatch = false; 738af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean optionalProviderKeyMatch = false; 7391d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb boolean javaOptionalProviderKeyMatch = false; 740af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean defaultMatch = false; 741af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean actualMatch = false; 742af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber List<Object> otherOptionalBindings = Lists.newArrayList(); 743af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber List<Binding> otherMatches = Lists.newArrayList(); 744af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber for (Binding b : injector.getAllBindings().values()) { 745af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean contains = optionalBinder.containsElement(b); 7461d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (HAS_JAVA_OPTIONAL) { 7471d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertEquals(contains, javaOptionalBinder.containsElement(b)); 7481d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 749af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Object visited = b.acceptTargetVisitor(visitor); 750af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (visited instanceof OptionalBinderBinding) { 751af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (visited.equals(optionalBinder)) { 752af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(contains); 7531d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else if (HAS_JAVA_OPTIONAL && visited.equals(javaOptionalBinder)) { 7541d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertTrue(contains); 755af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else { 756af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber otherOptionalBindings.add(visited); 757af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 758af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 759af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (b.getKey().equals(keyType)) { 760af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // keyType might match because a user bound it 761af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // (which is possible in a purely absent OptionalBinder) 762af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(expectedDefault != null || expectedActual != null, contains); 763af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (contains) { 764af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber keyMatch = true; 765af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 766af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (b.getKey().equals(optionalKey)) { 767af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(contains); 768af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber optionalKeyMatch = true; 7691d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else if (b.getKey().equals(javaOptionalKey)) { 7701d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertTrue(contains); 7711d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb javaOptionalKeyMatch = true; 772af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (b.getKey().equals(optionalJavaxProviderKey)) { 773af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(contains); 774af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber optionalJavaxProviderKeyMatch = true; 7751d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else if (b.getKey().equals(javaOptionalJavaxProviderKey)) { 7761d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertTrue(contains); 7771d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb javaOptionalJavaxProviderKeyMatch = true; 778af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (b.getKey().equals(optionalProviderKey)) { 779af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(contains); 780af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber optionalProviderKeyMatch = true; 7811d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else if (b.getKey().equals(javaOptionalProviderKey)) { 7821d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertTrue(contains); 7831d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb javaOptionalProviderKeyMatch = true; 784af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (expectedDefault != null && matches(b, expectedDefault)) { 785af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(contains); 786af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber defaultMatch = true; 787af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (expectedActual != null && matches(b, expectedActual)) { 788af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(contains); 789af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber actualMatch = true; 790af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (contains) { 791af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber otherMatches.add(b); 792af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 793af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 794af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 795af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(otherMatches.toString(), 0, otherMatches.size()); 796af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // only expect a keymatch if either default or actual are set 797af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(expectedDefault != null || expectedActual != null, keyMatch); 798af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(optionalKeyMatch); 799af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(optionalJavaxProviderKeyMatch); 800af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(optionalProviderKeyMatch); 8011d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertEquals(HAS_JAVA_OPTIONAL, javaOptionalKeyMatch); 8021d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertEquals(HAS_JAVA_OPTIONAL, javaOptionalJavaxProviderKeyMatch); 8031d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertEquals(HAS_JAVA_OPTIONAL, javaOptionalProviderKeyMatch); 804af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(expectedDefault != null, defaultMatch); 805af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(expectedActual != null, actualMatch); 806af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals("other OptionalBindings found: " + otherOptionalBindings, 807af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber expectedOtherOptionalBindings, otherOptionalBindings.size()); 808af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 809af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 8101d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @SuppressWarnings({ "unchecked", "rawtypes" }) 811842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin private static <T> void optionalModuleTest(Key<T> keyType, 812842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin Iterable<? extends Module> modules, 813842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin int expectedOtherOptionalBindings, 814842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin BindResult<?> expectedDefault, 815842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin BindResult<?> expectedActual, 816842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin BindResult<?> expectedUserLinkedActual) { 817842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin if (expectedUserLinkedActual != null) { 818842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin assertNull("cannot have actual if expecting user binding", expectedActual); 819842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin assertNull("cannot have default if expecting user binding", expectedDefault); 820842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin } 821af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Set<Element> elements = ImmutableSet.copyOf(Elements.getElements(modules)); 822af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Map<Key<?>, Binding<?>> indexed = index(elements); 823af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Key<Optional<T>> optionalKey = 824af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber keyType.ofType(OptionalBinder.optionalOf(keyType.getTypeLiteral())); 8251d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Key<?> javaOptionalKey = HAS_JAVA_OPTIONAL ? 8261d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb keyType.ofType(OptionalBinder.javaOptionalOf(keyType.getTypeLiteral())) : null; 8271d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Visitor visitor = new Visitor(); 8281d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb OptionalBinderBinding<Optional<T>> optionalBinder = null; 8291d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb OptionalBinderBinding<?> javaOptionalBinder = null; 830af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Key<?> defaultKey = null; 831af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Key<?> actualKey = null; 832af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 833af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Binding optionalBinding = indexed.get(optionalKey); 8341d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb optionalBinder = 8351d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb (OptionalBinderBinding<Optional<T>>) optionalBinding.acceptTargetVisitor(visitor); 8361d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 8371d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (HAS_JAVA_OPTIONAL) { 8381d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Binding javaOptionalBinding = indexed.get(javaOptionalKey); 8391d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb javaOptionalBinder = (OptionalBinderBinding) javaOptionalBinding.acceptTargetVisitor(visitor); 8401d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 841af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 842af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // Locate the defaultKey & actualKey 843af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber for (Element element : elements) { 844af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (optionalBinder.containsElement(element) && element instanceof Binding) { 845af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Binding binding = (Binding) element; 846af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (isSourceEntry(binding, Source.DEFAULT)) { 847c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin defaultKey = binding.getKey(); 848af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (isSourceEntry(binding, Source.ACTUAL)) { 849c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin actualKey = binding.getKey(); 850af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 851af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 852af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 853af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertNotNull(optionalBinder); 8541d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (HAS_JAVA_OPTIONAL) { 8551d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertNotNull(javaOptionalBinder); 8561d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 857af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(expectedDefault == null, defaultKey == null); 858af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(expectedActual == null, actualKey == null); 859af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 860af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Key<Optional<javax.inject.Provider<T>>> optionalJavaxProviderKey = 861af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber keyType.ofType(optionalOfJavaxProvider(keyType.getTypeLiteral())); 8621d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Key<?> javaOptionalJavaxProviderKey = HAS_JAVA_OPTIONAL ? 8631d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb keyType.ofType(javaOptionalOfJavaxProvider(keyType.getTypeLiteral())) : null; 864af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Key<Optional<Provider<T>>> optionalProviderKey = 865af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber keyType.ofType(optionalOfProvider(keyType.getTypeLiteral())); 8661d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Key<?> javaOptionalProviderKey = HAS_JAVA_OPTIONAL ? 8671d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb keyType.ofType(javaOptionalOfProvider(keyType.getTypeLiteral())) : null; 868af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean keyMatch = false; 869af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean optionalKeyMatch = false; 8701d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb boolean javaOptionalKeyMatch = false; 871af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean optionalJavaxProviderKeyMatch = false; 8721d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb boolean javaOptionalJavaxProviderKeyMatch = false; 873af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean optionalProviderKeyMatch = false; 8741d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb boolean javaOptionalProviderKeyMatch = false; 875af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean defaultMatch = false; 876af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean actualMatch = false; 877af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber List<Object> otherOptionalElements = Lists.newArrayList(); 878af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber List<Element> otherContains = Lists.newArrayList(); 879af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber List<Element> nonContainedElements = Lists.newArrayList(); 880af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber for (Element element : elements) { 881af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber boolean contains = optionalBinder.containsElement(element); 8821d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (HAS_JAVA_OPTIONAL) { 8831d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertEquals(contains, javaOptionalBinder.containsElement(element)); 8841d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 885af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (!contains) { 886af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber nonContainedElements.add(element); 887af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 888af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Key key = null; 889af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Binding b = null; 890af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (element instanceof Binding) { 891af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber b = (Binding) element; 892af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber key = b.getKey(); 893af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Object visited = b.acceptTargetVisitor(visitor); 894af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (visited instanceof OptionalBinderBinding) { 895af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (visited.equals(optionalBinder)) { 896af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(contains); 8971d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else if (HAS_JAVA_OPTIONAL && visited.equals(javaOptionalBinder)) { 8981d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertTrue(contains); 899af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else { 900af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber otherOptionalElements.add(visited); 901af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 902af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 903af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (element instanceof ProviderLookup) { 904af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber key = ((ProviderLookup) element).getKey(); 905af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 906af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 907af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (key != null && key.equals(keyType)) { 908af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // keyType might match because a user bound it 909af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // (which is possible in a purely absent OptionalBinder) 910af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(expectedDefault != null || expectedActual != null, contains); 911af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (contains) { 912af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber keyMatch = true; 913af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 914af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (key != null && key.equals(optionalKey)) { 915af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(contains); 916af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber optionalKeyMatch = true; 9171d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else if (key != null && key.equals(javaOptionalKey)) { 9181d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertTrue(contains); 9191d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb javaOptionalKeyMatch = true; 920af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (key != null && key.equals(optionalJavaxProviderKey)) { 921af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(contains); 922af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber optionalJavaxProviderKeyMatch = true; 9231d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else if (key != null && key.equals(javaOptionalJavaxProviderKey)) { 9241d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertTrue(contains); 9251d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb javaOptionalJavaxProviderKeyMatch = true; 926af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (key != null && key.equals(optionalProviderKey)) { 927af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(contains); 928af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber optionalProviderKeyMatch = true; 9291d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else if (key != null && key.equals(javaOptionalProviderKey)) { 9301d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertTrue(contains); 9311d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb javaOptionalProviderKeyMatch = true; 932af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (key != null && key.equals(defaultKey)) { 933af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(contains); 934af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (b != null) { // otherwise it might just be a ProviderLookup into it 935af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue("expected: " + expectedDefault + ", but was: " + b, 936af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber matches(b, expectedDefault)); 937af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber defaultMatch = true; 938af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 939af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (key != null && key.equals(actualKey)) { 940af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(contains); 941af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (b != null) { // otherwise it might just be a ProviderLookup into it 942af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue("expected: " + expectedActual + ", but was: " + b, matches(b, expectedActual)); 943af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber actualMatch = true; 944af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 945af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else if (contains) { 946af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber otherContains.add(element); 947af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 948af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 949af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 950af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // only expect a keymatch if either default or actual are set 951af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(expectedDefault != null || expectedActual != null, keyMatch); 952af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(optionalKeyMatch); 953af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(optionalJavaxProviderKeyMatch); 954af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertTrue(optionalProviderKeyMatch); 9551d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertEquals(HAS_JAVA_OPTIONAL, javaOptionalKeyMatch); 9561d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertEquals(HAS_JAVA_OPTIONAL, javaOptionalJavaxProviderKeyMatch); 9571d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb assertEquals(HAS_JAVA_OPTIONAL, javaOptionalProviderKeyMatch); 958af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(expectedDefault != null, defaultMatch); 959af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(expectedActual != null, actualMatch); 960af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals(otherContains.toString(), 0, otherContains.size()); 961af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber assertEquals("other OptionalBindings found: " + otherOptionalElements, 962af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber expectedOtherOptionalBindings, otherOptionalElements.size()); 963af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 964af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // Validate that we can construct an injector out of the remaining bindings. 965af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Guice.createInjector(Elements.getModule(nonContainedElements)); 966af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 967af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 968af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private static boolean isSourceEntry(Binding b, Source type) { 969c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin switch(type) { 970c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin case ACTUAL: 971c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return b.getKey().getAnnotation() instanceof OptionalBinder.Actual; 972c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin case DEFAULT: 973c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return b.getKey().getAnnotation() instanceof OptionalBinder.Default; 974c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin default: 975c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin throw new IllegalStateException("invalid type: " + type); 976af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 977af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 978af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 979af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** Returns the subset of elements that have keys, indexed by them. */ 980af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private static Map<Key<?>, Binding<?>> index(Iterable<Element> elements) { 981af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber ImmutableMap.Builder<Key<?>, Binding<?>> builder = ImmutableMap.builder(); 982af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber for (Element element : elements) { 983af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (element instanceof Binding) { 984af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber builder.put(((Binding) element).getKey(), (Binding) element); 985af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 986af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 987af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return builder.build(); 988af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 9894e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 9904e11457f34addf5d10fe0c31cefd54c75c37b540sberlin static <K, V> MapResult instance(K k, V v) { 9914e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return new MapResult<K, V>(k, new BindResult<V>(INSTANCE, v, null)); 9924e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 9934e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 9944e11457f34addf5d10fe0c31cefd54c75c37b540sberlin static <K, V> MapResult linked(K k, Class<? extends V> clazz) { 9954e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return new MapResult<K, V>(k, new BindResult<V>(LINKED, null, Key.get(clazz))); 9964e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 9974e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 9984e11457f34addf5d10fe0c31cefd54c75c37b540sberlin static <K, V> MapResult linked(K k, Key<? extends V> key) { 9994e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return new MapResult<K, V>(k, new BindResult<V>(LINKED, null, key)); 10004e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 10014e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 10024e11457f34addf5d10fe0c31cefd54c75c37b540sberlin static <K, V> MapResult providerInstance(K k, V v) { 10034e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return new MapResult<K, V>(k, new BindResult<V>(PROVIDER_INSTANCE, v, null)); 10044e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 10054e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1006bf2b16c06a5ff7c099fe60f9a46cfb130ce45962Christian Edward Gruber static class MapResult<K, V> { 10074e11457f34addf5d10fe0c31cefd54c75c37b540sberlin private final K k; 10084e11457f34addf5d10fe0c31cefd54c75c37b540sberlin private final BindResult<V> v; 10094e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 10104e11457f34addf5d10fe0c31cefd54c75c37b540sberlin MapResult(K k, BindResult<V> v) { 10114e11457f34addf5d10fe0c31cefd54c75c37b540sberlin this.k = k; 10124e11457f34addf5d10fe0c31cefd54c75c37b540sberlin this.v = v; 10134e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 10144e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 10154e11457f34addf5d10fe0c31cefd54c75c37b540sberlin @Override 10164e11457f34addf5d10fe0c31cefd54c75c37b540sberlin public String toString() { 10174e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return "entry[key[" + k + "],value[" + v + "]]"; 10184e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 10194e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1020af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 1021af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private static boolean matches(Binding<?> item, BindResult<?> result) { 1022af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber switch (result.type) { 1023af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber case INSTANCE: 1024af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (item instanceof InstanceBinding 1025af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber && ((InstanceBinding) item).getInstance().equals(result.instance)) { 1026af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return true; 1027af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 1028af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber break; 1029af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber case LINKED: 1030af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (item instanceof LinkedKeyBinding 1031af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber && ((LinkedKeyBinding) item).getLinkedKey().equals(result.key)) { 1032af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return true; 1033af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 1034af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber break; 1035af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber case PROVIDER_INSTANCE: 1036af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (item instanceof ProviderInstanceBinding 1037af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber && Objects.equal(((ProviderInstanceBinding) item).getUserSuppliedProvider().get(), 1038af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber result.instance)) { 1039af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return true; 1040af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 1041af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber break; 1042af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber case PROVIDER_KEY: 1043af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (item instanceof ProviderKeyBinding 1044af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber && ((ProviderKeyBinding) item).getProviderKey().equals(result.key)) { 1045af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return true; 1046af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 1047af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber break; 1048af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 1049af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return false; 1050af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 10514e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1052af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static <T> BindResult<T> instance(T t) { 10534e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return new BindResult<T>(INSTANCE, t, null); 10544e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 10554e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1056af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static <T> BindResult<T> linked(Class<? extends T> clazz) { 10574e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return new BindResult<T>(LINKED, null, Key.get(clazz)); 10584e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 10594e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1060af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static <T> BindResult<T> linked(Key<? extends T> key) { 10614e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return new BindResult<T>(LINKED, null, key); 10624e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 10634e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1064af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static <T> BindResult<T> providerInstance(T t) { 10654e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return new BindResult<T>(PROVIDER_INSTANCE, t, null); 10664e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1067af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 1068af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static <T> BindResult<T> providerKey(Key<T> key) { 1069af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return new BindResult<T>(PROVIDER_KEY, null, key); 1070af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 10714e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 10724e11457f34addf5d10fe0c31cefd54c75c37b540sberlin /** The kind of binding. */ 1073af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static enum BindType { INSTANCE, LINKED, PROVIDER_INSTANCE, PROVIDER_KEY } 10744e11457f34addf5d10fe0c31cefd54c75c37b540sberlin /** The result of the binding. */ 1075bf2b16c06a5ff7c099fe60f9a46cfb130ce45962Christian Edward Gruber static class BindResult<T> { 10764e11457f34addf5d10fe0c31cefd54c75c37b540sberlin private final BindType type; 1077af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Key<?> key; 10784e11457f34addf5d10fe0c31cefd54c75c37b540sberlin private final T instance; 10794e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1080af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private BindResult(BindType type, T instance, Key<?> key) { 10814e11457f34addf5d10fe0c31cefd54c75c37b540sberlin this.type = type; 10824e11457f34addf5d10fe0c31cefd54c75c37b540sberlin this.instance = instance; 10834e11457f34addf5d10fe0c31cefd54c75c37b540sberlin this.key = key; 10844e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 10854e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 10864e11457f34addf5d10fe0c31cefd54c75c37b540sberlin @Override 10874e11457f34addf5d10fe0c31cefd54c75c37b540sberlin public String toString() { 10884e11457f34addf5d10fe0c31cefd54c75c37b540sberlin switch(type) { 10894e11457f34addf5d10fe0c31cefd54c75c37b540sberlin case INSTANCE: 10904e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return "instance[" + instance + "]"; 10914e11457f34addf5d10fe0c31cefd54c75c37b540sberlin case LINKED: 10924e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return "linkedKey[" + key + "]"; 10934e11457f34addf5d10fe0c31cefd54c75c37b540sberlin case PROVIDER_INSTANCE: 10944e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return "providerInstance[" + instance + "]"; 1095af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber case PROVIDER_KEY: 1096af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return "providerKey[" + key + "]"; 10974e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 10984e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return null; 10994e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 11004e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 11014e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 11024e11457f34addf5d10fe0c31cefd54c75c37b540sberlin private static class Visitor<T> extends 11034e11457f34addf5d10fe0c31cefd54c75c37b540sberlin DefaultBindingTargetVisitor<T, Object> implements MultibindingsTargetVisitor<T, Object> { 11044e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 11054e11457f34addf5d10fe0c31cefd54c75c37b540sberlin public Object visit(MultibinderBinding<? extends T> multibinding) { 11064e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return multibinding; 11074e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 11084e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 11094e11457f34addf5d10fe0c31cefd54c75c37b540sberlin public Object visit(MapBinderBinding<? extends T> mapbinding) { 11104e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return mapbinding; 1111af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 1112af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 1113af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public Object visit(OptionalBinderBinding<? extends T> optionalbinding) { 1114af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return optionalbinding; 1115af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 11164e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 11174e11457f34addf5d10fe0c31cefd54c75c37b540sberlin} 1118