PageRenderTime 1151ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java

https://gitlab.com/metamorphiccode/guice
Java | 1117 lines | 953 code | 84 blank | 80 comment | 294 complexity | 0a8dff47bb8403a67079df6597ae818f MD5 | raw file
  1. /**
  2. * Copyright (C) 2010 Google Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.google.inject.multibindings;
  17. import static com.google.inject.multibindings.MapBinder.entryOfProviderOf;
  18. import static com.google.inject.multibindings.MapBinder.mapOf;
  19. import static com.google.inject.multibindings.MapBinder.mapOfJavaxProviderOf;
  20. import static com.google.inject.multibindings.MapBinder.mapOfProviderOf;
  21. import static com.google.inject.multibindings.MapBinder.mapOfSetOfProviderOf;
  22. import static com.google.inject.multibindings.Multibinder.collectionOfJavaxProvidersOf;
  23. import static com.google.inject.multibindings.Multibinder.collectionOfProvidersOf;
  24. import static com.google.inject.multibindings.Multibinder.setOf;
  25. import static com.google.inject.multibindings.OptionalBinder.javaOptionalOfJavaxProvider;
  26. import static com.google.inject.multibindings.OptionalBinder.javaOptionalOfProvider;
  27. import static com.google.inject.multibindings.OptionalBinder.optionalOfJavaxProvider;
  28. import static com.google.inject.multibindings.OptionalBinder.optionalOfProvider;
  29. import static com.google.inject.multibindings.SpiUtils.BindType.INSTANCE;
  30. import static com.google.inject.multibindings.SpiUtils.BindType.LINKED;
  31. import static com.google.inject.multibindings.SpiUtils.BindType.PROVIDER_INSTANCE;
  32. import static com.google.inject.multibindings.SpiUtils.BindType.PROVIDER_KEY;
  33. import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH;
  34. import static com.google.inject.multibindings.SpiUtils.VisitType.INJECTOR;
  35. import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE;
  36. import static junit.framework.Assert.assertEquals;
  37. import static junit.framework.Assert.assertFalse;
  38. import static junit.framework.Assert.assertNotNull;
  39. import static junit.framework.Assert.assertNull;
  40. import static junit.framework.Assert.assertTrue;
  41. import static junit.framework.Assert.fail;
  42. import com.google.common.base.Objects;
  43. import com.google.common.base.Optional;
  44. import com.google.common.collect.ImmutableMap;
  45. import com.google.common.collect.ImmutableSet;
  46. import com.google.common.collect.Lists;
  47. import com.google.common.collect.Maps;
  48. import com.google.common.collect.Multimap;
  49. import com.google.common.collect.MultimapBuilder;
  50. import com.google.common.collect.Sets;
  51. import com.google.inject.Binding;
  52. import com.google.inject.Guice;
  53. import com.google.inject.Injector;
  54. import com.google.inject.Key;
  55. import com.google.inject.Module;
  56. import com.google.inject.Provider;
  57. import com.google.inject.TypeLiteral;
  58. import com.google.inject.multibindings.Indexer.IndexedBinding;
  59. import com.google.inject.multibindings.MapBinder.RealMapBinder.ProviderMapEntry;
  60. import com.google.inject.multibindings.OptionalBinder.Source;
  61. import com.google.inject.spi.DefaultBindingTargetVisitor;
  62. import com.google.inject.spi.Element;
  63. import com.google.inject.spi.Elements;
  64. import com.google.inject.spi.InstanceBinding;
  65. import com.google.inject.spi.LinkedKeyBinding;
  66. import com.google.inject.spi.ProviderInstanceBinding;
  67. import com.google.inject.spi.ProviderKeyBinding;
  68. import com.google.inject.spi.ProviderLookup;
  69. import java.util.HashSet;
  70. import java.util.List;
  71. import java.util.Map;
  72. import java.util.Set;
  73. /**
  74. * Utilities for testing the Multibinder & MapBinder extension SPI.
  75. *
  76. * @author sameb@google.com (Sam Berlin)
  77. */
  78. public class SpiUtils {
  79. private static final boolean HAS_JAVA_OPTIONAL;
  80. static {
  81. Class<?> optional = null;
  82. try {
  83. optional = Class.forName("java.util.Optional");
  84. } catch (ClassNotFoundException ignored) {}
  85. HAS_JAVA_OPTIONAL = optional != null;
  86. }
  87. /** The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both. */
  88. enum VisitType { INJECTOR, MODULE, BOTH }
  89. /**
  90. * Asserts that MapBinderBinding visitors for work correctly.
  91. *
  92. * @param <T> The type of the binding
  93. * @param mapKey The key the map belongs to.
  94. * @param keyType the TypeLiteral of the key of the map
  95. * @param valueType the TypeLiteral of the value of the map
  96. * @param modules The modules that define the mapbindings
  97. * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both.
  98. * @param allowDuplicates If duplicates are allowed.
  99. * @param expectedMapBindings The number of other mapbinders we expect to see.
  100. * @param results The kind of bindings contained in the mapbinder.
  101. */
  102. static <T> void assertMapVisitor(Key<T> mapKey, TypeLiteral<?> keyType, TypeLiteral<?> valueType,
  103. Iterable<? extends Module> modules, VisitType visitType, boolean allowDuplicates,
  104. int expectedMapBindings, MapResult... results) {
  105. if(visitType == null) {
  106. fail("must test something");
  107. }
  108. if (visitType == BOTH || visitType == INJECTOR) {
  109. mapInjectorTest(mapKey, keyType, valueType, modules, allowDuplicates, expectedMapBindings,
  110. results);
  111. }
  112. if (visitType == BOTH || visitType == MODULE) {
  113. mapModuleTest(mapKey, keyType, valueType, modules, allowDuplicates, expectedMapBindings,
  114. results);
  115. }
  116. }
  117. @SuppressWarnings("unchecked")
  118. private static <T> void mapInjectorTest(Key<T> mapKey, TypeLiteral<?> keyType,
  119. TypeLiteral<?> valueType, Iterable<? extends Module> modules, boolean allowDuplicates,
  120. int expectedMapBindings, MapResult... results) {
  121. Injector injector = Guice.createInjector(modules);
  122. Visitor<T> visitor = new Visitor<T>();
  123. Binding<T> mapBinding = injector.getBinding(mapKey);
  124. MapBinderBinding<T> mapbinder = (MapBinderBinding<T>)mapBinding.acceptTargetVisitor(visitor);
  125. assertNotNull(mapbinder);
  126. assertEquals(keyType, mapbinder.getKeyTypeLiteral());
  127. assertEquals(valueType, mapbinder.getValueTypeLiteral());
  128. assertEquals(allowDuplicates, mapbinder.permitsDuplicates());
  129. List<Map.Entry<?, Binding<?>>> entries = Lists.newArrayList(mapbinder.getEntries());
  130. List<MapResult> mapResults = Lists.newArrayList(results);
  131. assertEquals("wrong entries, expected: " + mapResults + ", but was: " + entries,
  132. mapResults.size(), entries.size());
  133. for(MapResult result : mapResults) {
  134. Map.Entry<?, Binding<?>> found = null;
  135. for(Map.Entry<?, Binding<?>> entry : entries) {
  136. Object key = entry.getKey();
  137. Binding<?> value = entry.getValue();
  138. if(key.equals(result.k) && matches(value, result.v)) {
  139. found = entry;
  140. break;
  141. }
  142. }
  143. if(found == null) {
  144. fail("Could not find entry: " + result + " in remaining entries: " + entries);
  145. } else {
  146. assertTrue("mapBinder doesn't contain: " + found.getValue(),
  147. mapbinder.containsElement(found.getValue()));
  148. entries.remove(found);
  149. }
  150. }
  151. if(!entries.isEmpty()) {
  152. fail("Found all entries of: " + mapResults + ", but more were left over: " + entries);
  153. }
  154. Key<?> mapOfJavaxProvider = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType));
  155. Key<?> mapOfProvider = mapKey.ofType(mapOfProviderOf(keyType, valueType));
  156. Key<?> mapOfSetOfProvider = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType));
  157. Key<?> mapOfSet = mapKey.ofType(mapOf(keyType, setOf(valueType)));
  158. Key<?> setOfEntry = mapKey.ofType(setOf(entryOfProviderOf(keyType, valueType)));
  159. Key<?> collectionOfProvidersOfEntryOfProvider =
  160. mapKey.ofType(collectionOfProvidersOf(entryOfProviderOf(keyType, valueType)));
  161. Key<?> collectionOfJavaxProvidersOfEntryOfProvider =
  162. mapKey.ofType(collectionOfJavaxProvidersOf(entryOfProviderOf(keyType, valueType)));
  163. boolean entrySetMatch = false;
  164. boolean mapJavaxProviderMatch = false;
  165. boolean mapProviderMatch = false;
  166. boolean mapSetMatch = false;
  167. boolean mapSetProviderMatch = false;
  168. boolean collectionOfProvidersOfEntryOfProviderMatch = false;
  169. boolean collectionOfJavaxProvidersOfEntryOfProviderMatch = false;
  170. List<Object> otherMapBindings = Lists.newArrayList();
  171. List<Binding> otherMatches = Lists.newArrayList();
  172. Multimap<Object, IndexedBinding> indexedEntries =
  173. MultimapBuilder.hashKeys().hashSetValues().build();
  174. Indexer indexer = new Indexer(injector);
  175. int duplicates = 0;
  176. for(Binding b : injector.getAllBindings().values()) {
  177. boolean contains = mapbinder.containsElement(b);
  178. Object visited = b.acceptTargetVisitor(visitor);
  179. if(visited instanceof MapBinderBinding) {
  180. if(visited.equals(mapbinder)) {
  181. assertTrue(contains);
  182. } else {
  183. otherMapBindings.add(visited);
  184. }
  185. } else if(b.getKey().equals(mapOfProvider)) {
  186. assertTrue(contains);
  187. mapProviderMatch = true;
  188. } else if (b.getKey().equals(mapOfJavaxProvider)) {
  189. assertTrue(contains);
  190. mapJavaxProviderMatch = true;
  191. } else if(b.getKey().equals(mapOfSet)) {
  192. assertTrue(contains);
  193. mapSetMatch = true;
  194. } else if(b.getKey().equals(mapOfSetOfProvider)) {
  195. assertTrue(contains);
  196. mapSetProviderMatch = true;
  197. } else if(b.getKey().equals(setOfEntry)) {
  198. assertTrue(contains);
  199. entrySetMatch = true;
  200. // Validate that this binding is also a MultibinderBinding.
  201. assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding);
  202. } else if(b.getKey().equals(collectionOfProvidersOfEntryOfProvider)) {
  203. assertTrue(contains);
  204. collectionOfProvidersOfEntryOfProviderMatch = true;
  205. } else if(b.getKey().equals(collectionOfJavaxProvidersOfEntryOfProvider)) {
  206. assertTrue(contains);
  207. collectionOfJavaxProvidersOfEntryOfProviderMatch = true;
  208. } else if (contains) {
  209. if (b instanceof ProviderInstanceBinding) {
  210. ProviderInstanceBinding<?> pib = (ProviderInstanceBinding<?>)b;
  211. if (pib.getUserSuppliedProvider() instanceof ProviderMapEntry) {
  212. // weird casting required to workaround compilation issues with jdk6
  213. ProviderMapEntry<?, ?> pme =
  214. (ProviderMapEntry<?, ?>) (Provider) pib.getUserSuppliedProvider();
  215. Binding<?> valueBinding = injector.getBinding(pme.getValueKey());
  216. if (indexer.isIndexable(valueBinding)
  217. && !indexedEntries.put(pme.getKey(), valueBinding.acceptTargetVisitor(indexer))) {
  218. duplicates++;
  219. }
  220. }
  221. }
  222. otherMatches.add(b);
  223. }
  224. }
  225. int sizeOfOther = otherMatches.size();
  226. if(allowDuplicates) {
  227. sizeOfOther--; // account for 1 duplicate binding
  228. }
  229. // Multiply by two because each has a value and Map.Entry.
  230. int expectedSize = 2 * (mapResults.size() + duplicates);
  231. assertEquals("Incorrect other matches: " + otherMatches, expectedSize, sizeOfOther);
  232. assertTrue(entrySetMatch);
  233. assertTrue(mapProviderMatch);
  234. assertTrue(mapJavaxProviderMatch);
  235. assertTrue(collectionOfProvidersOfEntryOfProviderMatch);
  236. assertTrue(collectionOfJavaxProvidersOfEntryOfProviderMatch);
  237. assertEquals(allowDuplicates, mapSetMatch);
  238. assertEquals(allowDuplicates, mapSetProviderMatch);
  239. assertEquals("other MapBindings found: " + otherMapBindings, expectedMapBindings,
  240. otherMapBindings.size());
  241. }
  242. @SuppressWarnings("unchecked")
  243. private static <T> void mapModuleTest(Key<T> mapKey, TypeLiteral<?> keyType,
  244. TypeLiteral<?> valueType, Iterable<? extends Module> modules, boolean allowDuplicates,
  245. int expectedMapBindings, MapResult... results) {
  246. Set<Element> elements = ImmutableSet.copyOf(Elements.getElements(modules));
  247. Visitor<T> visitor = new Visitor<T>();
  248. MapBinderBinding<T> mapbinder = null;
  249. Map<Key<?>, Binding<?>> keyMap = Maps.newHashMap();
  250. for(Element element : elements) {
  251. if(element instanceof Binding) {
  252. Binding<?> binding = (Binding<?>)element;
  253. keyMap.put(binding.getKey(), binding);
  254. if (binding.getKey().equals(mapKey)) {
  255. mapbinder = (MapBinderBinding<T>)((Binding<T>)binding).acceptTargetVisitor(visitor);
  256. }
  257. }
  258. }
  259. assertNotNull(mapbinder);
  260. assertEquals(keyType, mapbinder.getKeyTypeLiteral());
  261. assertEquals(valueType, mapbinder.getValueTypeLiteral());
  262. List<MapResult> mapResults = Lists.newArrayList(results);
  263. Key<?> mapOfProvider = mapKey.ofType(mapOfProviderOf(keyType, valueType));
  264. Key<?> mapOfJavaxProvider = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType));
  265. Key<?> mapOfSetOfProvider = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType));
  266. Key<?> mapOfSet = mapKey.ofType(mapOf(keyType, setOf(valueType)));
  267. Key<?> setOfEntry = mapKey.ofType(setOf(entryOfProviderOf(keyType, valueType)));
  268. Key<?> collectionOfProvidersOfEntry =
  269. mapKey.ofType(collectionOfProvidersOf(entryOfProviderOf(keyType, valueType)));
  270. Key<?> collectionOfJavaxProvidersOfEntry =
  271. mapKey.ofType(collectionOfJavaxProvidersOf(entryOfProviderOf(keyType, valueType)));
  272. boolean entrySetMatch = false;
  273. boolean mapProviderMatch = false;
  274. boolean mapJavaxProviderMatch = false;
  275. boolean mapSetMatch = false;
  276. boolean mapSetProviderMatch = false;
  277. boolean collectionOfProvidersOfEntryMatch = false;
  278. boolean collectionOfJavaxProvidersOfEntryMatch = false;
  279. List<Object> otherMapBindings = Lists.newArrayList();
  280. List<Element> otherMatches = Lists.newArrayList();
  281. List<Element> otherElements = Lists.newArrayList();
  282. Indexer indexer = new Indexer(null);
  283. Multimap<Object, IndexedBinding> indexedEntries =
  284. MultimapBuilder.hashKeys().hashSetValues().build();
  285. int duplicates = 0;
  286. for(Element element : elements) {
  287. boolean contains = mapbinder.containsElement(element);
  288. if(!contains) {
  289. otherElements.add(element);
  290. }
  291. boolean matched = false;
  292. Key key = null;
  293. Binding b = null;
  294. if(element instanceof Binding) {
  295. b = (Binding)element;
  296. if (b instanceof ProviderInstanceBinding) {
  297. ProviderInstanceBinding<?> pb = (ProviderInstanceBinding<?>) b;
  298. if (pb.getUserSuppliedProvider() instanceof ProviderMapEntry) {
  299. // weird casting required to workaround jdk6 compilation problems
  300. ProviderMapEntry<?, ?> pme =
  301. (ProviderMapEntry<?, ?>) (Provider) pb.getUserSuppliedProvider();
  302. Binding<?> valueBinding = keyMap.get(pme.getValueKey());
  303. if (indexer.isIndexable(valueBinding)
  304. && !indexedEntries.put(pme.getKey(), valueBinding.acceptTargetVisitor(indexer))) {
  305. duplicates++;
  306. }
  307. }
  308. }
  309. key = b.getKey();
  310. Object visited = b.acceptTargetVisitor(visitor);
  311. if(visited instanceof MapBinderBinding) {
  312. matched = true;
  313. if(visited.equals(mapbinder)) {
  314. assertTrue(contains);
  315. } else {
  316. otherMapBindings.add(visited);
  317. }
  318. }
  319. } else if(element instanceof ProviderLookup) {
  320. key = ((ProviderLookup)element).getKey();
  321. }
  322. if(!matched && key != null) {
  323. if(key.equals(mapOfProvider)) {
  324. matched = true;
  325. assertTrue(contains);
  326. mapProviderMatch = true;
  327. } else if(key.equals(mapOfJavaxProvider)) {
  328. matched = true;
  329. assertTrue(contains);
  330. mapJavaxProviderMatch = true;
  331. } else if(key.equals(mapOfSet)) {
  332. matched = true;
  333. assertTrue(contains);
  334. mapSetMatch = true;
  335. } else if(key.equals(mapOfSetOfProvider)) {
  336. matched = true;
  337. assertTrue(contains);
  338. mapSetProviderMatch = true;
  339. } else if(key.equals(setOfEntry)) {
  340. matched = true;
  341. assertTrue(contains);
  342. entrySetMatch = true;
  343. // Validate that this binding is also a MultibinderBinding.
  344. if(b != null) {
  345. assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding);
  346. }
  347. } else if(key.equals(collectionOfProvidersOfEntry)) {
  348. matched = true;
  349. assertTrue(contains);
  350. collectionOfProvidersOfEntryMatch = true;
  351. } else if(key.equals(collectionOfJavaxProvidersOfEntry)) {
  352. matched = true;
  353. assertTrue(contains);
  354. collectionOfJavaxProvidersOfEntryMatch = true;
  355. }
  356. }
  357. if (!matched && contains) {
  358. otherMatches.add(element);
  359. }
  360. }
  361. int otherMatchesSize = otherMatches.size();
  362. if (allowDuplicates) {
  363. otherMatchesSize--; // allow for 1 duplicate binding
  364. }
  365. // Multiply by 3 because each has a value, ProviderLookup, and Map.Entry
  366. int expectedSize = (mapResults.size() + duplicates) * 3;
  367. assertEquals("incorrect number of contains, leftover matches: " + otherMatches,
  368. expectedSize, otherMatchesSize);
  369. assertTrue(entrySetMatch);
  370. assertTrue(mapProviderMatch);
  371. assertTrue(mapJavaxProviderMatch);
  372. assertTrue(collectionOfProvidersOfEntryMatch);
  373. assertTrue(collectionOfJavaxProvidersOfEntryMatch);
  374. assertEquals(allowDuplicates, mapSetMatch);
  375. assertEquals(allowDuplicates, mapSetProviderMatch);
  376. assertEquals("other MapBindings found: " + otherMapBindings, expectedMapBindings,
  377. otherMapBindings.size());
  378. // Validate that we can construct an injector out of the remaining bindings.
  379. Guice.createInjector(Elements.getModule(otherElements));
  380. }
  381. /**
  382. * Asserts that MultibinderBinding visitors work correctly.
  383. *
  384. * @param <T> The type of the binding
  385. * @param setKey The key the set belongs to.
  386. * @param elementType the TypeLiteral of the element
  387. * @param modules The modules that define the multibindings
  388. * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both.
  389. * @param allowDuplicates If duplicates are allowed.
  390. * @param expectedMultibindings The number of other multibinders we expect to see.
  391. * @param results The kind of bindings contained in the multibinder.
  392. */
  393. static <T> void assertSetVisitor(Key<Set<T>> setKey, TypeLiteral<?> elementType,
  394. Iterable<? extends Module> modules, VisitType visitType, boolean allowDuplicates,
  395. int expectedMultibindings, BindResult... results) {
  396. if(visitType == null) {
  397. fail("must test something");
  398. }
  399. if(visitType == BOTH || visitType == INJECTOR) {
  400. setInjectorTest(setKey, elementType, modules, allowDuplicates,
  401. expectedMultibindings, results);
  402. }
  403. if(visitType == BOTH || visitType == MODULE) {
  404. setModuleTest(setKey, elementType, modules, allowDuplicates,
  405. expectedMultibindings, results);
  406. }
  407. }
  408. @SuppressWarnings("unchecked")
  409. private static <T> void setInjectorTest(Key<Set<T>> setKey, TypeLiteral<?> elementType,
  410. Iterable<? extends Module> modules, boolean allowDuplicates, int otherMultibindings,
  411. BindResult... results) {
  412. Key<?> collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType));
  413. Key<?> collectionOfJavaxProvidersKey =
  414. setKey.ofType(collectionOfJavaxProvidersOf(elementType));
  415. Injector injector = Guice.createInjector(modules);
  416. Visitor<Set<T>> visitor = new Visitor<Set<T>>();
  417. Binding<Set<T>> binding = injector.getBinding(setKey);
  418. MultibinderBinding<Set<T>> multibinder =
  419. (MultibinderBinding<Set<T>>)binding.acceptTargetVisitor(visitor);
  420. assertNotNull(multibinder);
  421. assertEquals(elementType, multibinder.getElementTypeLiteral());
  422. assertEquals(allowDuplicates, multibinder.permitsDuplicates());
  423. List<Binding<?>> elements = Lists.newArrayList(multibinder.getElements());
  424. List<BindResult> bindResults = Lists.newArrayList(results);
  425. assertEquals("wrong bind elements, expected: " + bindResults
  426. + ", but was: " + multibinder.getElements(),
  427. bindResults.size(), elements.size());
  428. for(BindResult result : bindResults) {
  429. Binding found = null;
  430. for(Binding item : elements) {
  431. if (matches(item, result)) {
  432. found = item;
  433. break;
  434. }
  435. }
  436. if(found == null) {
  437. fail("Could not find element: " + result + " in remaining elements: " + elements);
  438. } else {
  439. elements.remove(found);
  440. }
  441. }
  442. if(!elements.isEmpty()) {
  443. fail("Found all elements of: " + bindResults + ", but more were left over: " + elements);
  444. }
  445. Set<Binding> setOfElements = new HashSet<Binding>(multibinder.getElements());
  446. Set<IndexedBinding> setOfIndexed = Sets.newHashSet();
  447. Indexer indexer = new Indexer(injector);
  448. for (Binding<?> oneBinding : setOfElements) {
  449. setOfIndexed.add(oneBinding.acceptTargetVisitor(indexer));
  450. }
  451. List<Object> otherMultibinders = Lists.newArrayList();
  452. List<Binding> otherContains = Lists.newArrayList();
  453. boolean collectionOfProvidersMatch = false;
  454. boolean collectionOfJavaxProvidersMatch = false;
  455. for(Binding b : injector.getAllBindings().values()) {
  456. boolean contains = multibinder.containsElement(b);
  457. Key key = b.getKey();
  458. Object visited = b.acceptTargetVisitor(visitor);
  459. if(visited != null) {
  460. if(visited.equals(multibinder)) {
  461. assertTrue(contains);
  462. } else {
  463. otherMultibinders.add(visited);
  464. }
  465. } else if(setOfElements.contains(b)) {
  466. assertTrue(contains);
  467. } else if (key.equals(collectionOfProvidersKey)) {
  468. assertTrue(contains);
  469. collectionOfProvidersMatch = true;
  470. } else if (key.equals(collectionOfJavaxProvidersKey)) {
  471. assertTrue(contains);
  472. collectionOfJavaxProvidersMatch = true;
  473. } else if (contains) {
  474. if (!indexer.isIndexable(b) || !setOfIndexed.contains(b.acceptTargetVisitor(indexer))) {
  475. otherContains.add(b);
  476. }
  477. }
  478. }
  479. assertTrue(collectionOfProvidersMatch);
  480. assertTrue(collectionOfJavaxProvidersMatch);
  481. if(allowDuplicates) {
  482. assertEquals("contained more than it should: " + otherContains, 1, otherContains.size());
  483. } else {
  484. assertTrue("contained more than it should: " + otherContains, otherContains.isEmpty());
  485. }
  486. assertEquals("other multibindings found: " + otherMultibinders, otherMultibindings,
  487. otherMultibinders.size());
  488. }
  489. @SuppressWarnings("unchecked")
  490. private static <T> void setModuleTest(Key<Set<T>> setKey, TypeLiteral<?> elementType,
  491. Iterable<? extends Module> modules, boolean allowDuplicates, int otherMultibindings,
  492. BindResult... results) {
  493. Key<?> collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType));
  494. Key<?> collectionOfJavaxProvidersKey =
  495. setKey.ofType(collectionOfJavaxProvidersOf(elementType));
  496. List<BindResult> bindResults = Lists.newArrayList(results);
  497. List<Element> elements = Elements.getElements(modules);
  498. Visitor<T> visitor = new Visitor<T>();
  499. MultibinderBinding<Set<T>> multibinder = null;
  500. for(Element element : elements) {
  501. if(element instanceof Binding && ((Binding)element).getKey().equals(setKey)) {
  502. multibinder = (MultibinderBinding<Set<T>>)((Binding)element).acceptTargetVisitor(visitor);
  503. break;
  504. }
  505. }
  506. assertNotNull(multibinder);
  507. assertEquals(elementType, multibinder.getElementTypeLiteral());
  508. List<Object> otherMultibinders = Lists.newArrayList();
  509. Set<Element> otherContains = new HashSet<Element>();
  510. List<Element> otherElements = Lists.newArrayList();
  511. int duplicates = 0;
  512. Set<IndexedBinding> setOfIndexed = Sets.newHashSet();
  513. Indexer indexer = new Indexer(null);
  514. boolean collectionOfProvidersMatch = false;
  515. boolean collectionOfJavaxProvidersMatch = false;
  516. for(Element element : elements) {
  517. boolean contains = multibinder.containsElement(element);
  518. if(!contains) {
  519. otherElements.add(element);
  520. }
  521. boolean matched = false;
  522. Key key = null;
  523. if(element instanceof Binding) {
  524. Binding binding = (Binding)element;
  525. if (indexer.isIndexable(binding)
  526. && !setOfIndexed.add((IndexedBinding) binding.acceptTargetVisitor(indexer))) {
  527. duplicates++;
  528. }
  529. key = binding.getKey();
  530. Object visited = binding.acceptTargetVisitor(visitor);
  531. if(visited != null) {
  532. matched = true;
  533. if(visited.equals(multibinder)) {
  534. assertTrue(contains);
  535. } else {
  536. otherMultibinders.add(visited);
  537. }
  538. }
  539. }
  540. if (collectionOfProvidersKey.equals(key)) {
  541. assertTrue(contains);
  542. assertFalse(matched);
  543. collectionOfProvidersMatch = true;
  544. } else if (collectionOfJavaxProvidersKey.equals(key)) {
  545. assertTrue(contains);
  546. assertFalse(matched);
  547. collectionOfJavaxProvidersMatch = true;
  548. } else if (!matched && contains) {
  549. otherContains.add(element);
  550. }
  551. }
  552. if(allowDuplicates) {
  553. assertEquals("wrong contained elements: " + otherContains,
  554. bindResults.size() + 1 + duplicates, otherContains.size());
  555. } else {
  556. assertEquals("wrong contained elements: " + otherContains,
  557. bindResults.size() + duplicates, otherContains.size());
  558. }
  559. assertEquals("other multibindings found: " + otherMultibinders, otherMultibindings,
  560. otherMultibinders.size());
  561. assertTrue(collectionOfProvidersMatch);
  562. assertTrue(collectionOfJavaxProvidersMatch);
  563. // Validate that we can construct an injector out of the remaining bindings.
  564. Guice.createInjector(Elements.getModule(otherElements));
  565. }
  566. /**
  567. * Asserts that OptionalBinderBinding visitors for work correctly.
  568. *
  569. * @param <T> The type of the binding
  570. * @param keyType The key OptionalBinder is binding
  571. * @param modules The modules that define the bindings
  572. * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module)
  573. * test, or both.
  574. * @param expectedOtherOptionalBindings the # of other optional bindings we expect to see.
  575. * @param expectedDefault the expected default binding, or null if none
  576. * @param expectedActual the expected actual binding, or null if none
  577. * @param expectedUserLinkedActual the user binding that is the actual binding, used if
  578. * neither the default nor actual are set and a user binding existed for the type.
  579. */
  580. static <T> void assertOptionalVisitor(Key<T> keyType,
  581. Iterable<? extends Module> modules,
  582. VisitType visitType,
  583. int expectedOtherOptionalBindings,
  584. BindResult<?> expectedDefault,
  585. BindResult<?> expectedActual,
  586. BindResult<?> expectedUserLinkedActual) {
  587. if (visitType == null) {
  588. fail("must test something");
  589. }
  590. // if java.util.Optional is bound, there'll be twice as many as we expect.
  591. if (HAS_JAVA_OPTIONAL) {
  592. expectedOtherOptionalBindings *= 2;
  593. }
  594. if (visitType == BOTH || visitType == INJECTOR) {
  595. optionalInjectorTest(keyType, modules, expectedOtherOptionalBindings, expectedDefault,
  596. expectedActual, expectedUserLinkedActual);
  597. }
  598. if (visitType == BOTH || visitType == MODULE) {
  599. optionalModuleTest(keyType, modules, expectedOtherOptionalBindings, expectedDefault,
  600. expectedActual, expectedUserLinkedActual);
  601. }
  602. }
  603. @SuppressWarnings({ "unchecked", "rawtypes" })
  604. private static <T> void optionalInjectorTest(Key<T> keyType,
  605. Iterable<? extends Module> modules,
  606. int expectedOtherOptionalBindings,
  607. BindResult<?> expectedDefault,
  608. BindResult<?> expectedActual,
  609. BindResult<?> expectedUserLinkedActual) {
  610. if (expectedUserLinkedActual != null) {
  611. assertNull("cannot have actual if expecting user binding", expectedActual);
  612. assertNull("cannot have default if expecting user binding", expectedDefault);
  613. }
  614. Key<Optional<T>> optionalKey =
  615. keyType.ofType(OptionalBinder.optionalOf(keyType.getTypeLiteral()));
  616. Key<?> javaOptionalKey = HAS_JAVA_OPTIONAL ?
  617. keyType.ofType(OptionalBinder.javaOptionalOf(keyType.getTypeLiteral())) : null;
  618. Injector injector = Guice.createInjector(modules);
  619. Binding<Optional<T>> optionalBinding = injector.getBinding(optionalKey);
  620. Visitor visitor = new Visitor();
  621. OptionalBinderBinding<Optional<T>> optionalBinder =
  622. (OptionalBinderBinding<Optional<T>>) optionalBinding.acceptTargetVisitor(visitor);
  623. assertNotNull(optionalBinder);
  624. assertEquals(optionalKey, optionalBinder.getKey());
  625. Binding<?> javaOptionalBinding = null;
  626. OptionalBinderBinding<?> javaOptionalBinder = null;
  627. if (HAS_JAVA_OPTIONAL) {
  628. javaOptionalBinding = injector.getBinding(javaOptionalKey);
  629. javaOptionalBinder = (OptionalBinderBinding<?>) javaOptionalBinding.acceptTargetVisitor(visitor);
  630. assertNotNull(javaOptionalBinder);
  631. assertEquals(javaOptionalKey, javaOptionalBinder.getKey());
  632. }
  633. if (expectedDefault == null) {
  634. assertNull("did not expect a default binding", optionalBinder.getDefaultBinding());
  635. if (HAS_JAVA_OPTIONAL) {
  636. assertNull("did not expect a default binding", javaOptionalBinder.getDefaultBinding());
  637. }
  638. } else {
  639. assertTrue("expectedDefault: " + expectedDefault + ", actualDefault: "
  640. + optionalBinder.getDefaultBinding(),
  641. matches(optionalBinder.getDefaultBinding(), expectedDefault));
  642. if (HAS_JAVA_OPTIONAL) {
  643. assertTrue("expectedDefault: " + expectedDefault + ", actualDefault: "
  644. + javaOptionalBinder.getDefaultBinding(),
  645. matches(javaOptionalBinder.getDefaultBinding(), expectedDefault));
  646. }
  647. }
  648. if (expectedActual == null && expectedUserLinkedActual == null) {
  649. assertNull(optionalBinder.getActualBinding());
  650. if (HAS_JAVA_OPTIONAL) {
  651. assertNull(javaOptionalBinder.getActualBinding());
  652. }
  653. } else if (expectedActual != null) {
  654. assertTrue("expectedActual: " + expectedActual + ", actualActual: "
  655. + optionalBinder.getActualBinding(),
  656. matches(optionalBinder.getActualBinding(), expectedActual));
  657. if (HAS_JAVA_OPTIONAL) {
  658. assertTrue("expectedActual: " + expectedActual + ", actualActual: "
  659. + javaOptionalBinder.getActualBinding(),
  660. matches(javaOptionalBinder.getActualBinding(), expectedActual));
  661. }
  662. } else if (expectedUserLinkedActual != null) {
  663. assertTrue("expectedUserLinkedActual: " + expectedUserLinkedActual + ", actualActual: "
  664. + optionalBinder.getActualBinding(),
  665. matches(optionalBinder.getActualBinding(), expectedUserLinkedActual));
  666. if (HAS_JAVA_OPTIONAL) {
  667. assertTrue("expectedUserLinkedActual: " + expectedUserLinkedActual + ", actualActual: "
  668. + javaOptionalBinder.getActualBinding(),
  669. matches(javaOptionalBinder.getActualBinding(), expectedUserLinkedActual));
  670. }
  671. }
  672. Key<Optional<javax.inject.Provider<T>>> optionalJavaxProviderKey =
  673. keyType.ofType(optionalOfJavaxProvider(keyType.getTypeLiteral()));
  674. Key<?> javaOptionalJavaxProviderKey = HAS_JAVA_OPTIONAL ?
  675. keyType.ofType(javaOptionalOfJavaxProvider(keyType.getTypeLiteral())) : null;
  676. Key<Optional<Provider<T>>> optionalProviderKey =
  677. keyType.ofType(optionalOfProvider(keyType.getTypeLiteral()));
  678. Key<?> javaOptionalProviderKey = HAS_JAVA_OPTIONAL ?
  679. keyType.ofType(javaOptionalOfProvider(keyType.getTypeLiteral())) : null;
  680. boolean keyMatch = false;
  681. boolean optionalKeyMatch = false;
  682. boolean javaOptionalKeyMatch = false;
  683. boolean optionalJavaxProviderKeyMatch = false;
  684. boolean javaOptionalJavaxProviderKeyMatch = false;
  685. boolean optionalProviderKeyMatch = false;
  686. boolean javaOptionalProviderKeyMatch = false;
  687. boolean defaultMatch = false;
  688. boolean actualMatch = false;
  689. List<Object> otherOptionalBindings = Lists.newArrayList();
  690. List<Binding> otherMatches = Lists.newArrayList();
  691. for (Binding b : injector.getAllBindings().values()) {
  692. boolean contains = optionalBinder.containsElement(b);
  693. if (HAS_JAVA_OPTIONAL) {
  694. assertEquals(contains, javaOptionalBinder.containsElement(b));
  695. }
  696. Object visited = b.acceptTargetVisitor(visitor);
  697. if (visited instanceof OptionalBinderBinding) {
  698. if (visited.equals(optionalBinder)) {
  699. assertTrue(contains);
  700. } else if (HAS_JAVA_OPTIONAL && visited.equals(javaOptionalBinder)) {
  701. assertTrue(contains);
  702. } else {
  703. otherOptionalBindings.add(visited);
  704. }
  705. }
  706. if (b.getKey().equals(keyType)) {
  707. // keyType might match because a user bound it
  708. // (which is possible in a purely absent OptionalBinder)
  709. assertEquals(expectedDefault != null || expectedActual != null, contains);
  710. if (contains) {
  711. keyMatch = true;
  712. }
  713. } else if (b.getKey().equals(optionalKey)) {
  714. assertTrue(contains);
  715. optionalKeyMatch = true;
  716. } else if (b.getKey().equals(javaOptionalKey)) {
  717. assertTrue(contains);
  718. javaOptionalKeyMatch = true;
  719. } else if (b.getKey().equals(optionalJavaxProviderKey)) {
  720. assertTrue(contains);
  721. optionalJavaxProviderKeyMatch = true;
  722. } else if (b.getKey().equals(javaOptionalJavaxProviderKey)) {
  723. assertTrue(contains);
  724. javaOptionalJavaxProviderKeyMatch = true;
  725. } else if (b.getKey().equals(optionalProviderKey)) {
  726. assertTrue(contains);
  727. optionalProviderKeyMatch = true;
  728. } else if (b.getKey().equals(javaOptionalProviderKey)) {
  729. assertTrue(contains);
  730. javaOptionalProviderKeyMatch = true;
  731. } else if (expectedDefault != null && matches(b, expectedDefault)) {
  732. assertTrue(contains);
  733. defaultMatch = true;
  734. } else if (expectedActual != null && matches(b, expectedActual)) {
  735. assertTrue(contains);
  736. actualMatch = true;
  737. } else if (contains) {
  738. otherMatches.add(b);
  739. }
  740. }
  741. assertEquals(otherMatches.toString(), 0, otherMatches.size());
  742. // only expect a keymatch if either default or actual are set
  743. assertEquals(expectedDefault != null || expectedActual != null, keyMatch);
  744. assertTrue(optionalKeyMatch);
  745. assertTrue(optionalJavaxProviderKeyMatch);
  746. assertTrue(optionalProviderKeyMatch);
  747. assertEquals(HAS_JAVA_OPTIONAL, javaOptionalKeyMatch);
  748. assertEquals(HAS_JAVA_OPTIONAL, javaOptionalJavaxProviderKeyMatch);
  749. assertEquals(HAS_JAVA_OPTIONAL, javaOptionalProviderKeyMatch);
  750. assertEquals(expectedDefault != null, defaultMatch);
  751. assertEquals(expectedActual != null, actualMatch);
  752. assertEquals("other OptionalBindings found: " + otherOptionalBindings,
  753. expectedOtherOptionalBindings, otherOptionalBindings.size());
  754. }
  755. @SuppressWarnings({ "unchecked", "rawtypes" })
  756. private static <T> void optionalModuleTest(Key<T> keyType,
  757. Iterable<? extends Module> modules,
  758. int expectedOtherOptionalBindings,
  759. BindResult<?> expectedDefault,
  760. BindResult<?> expectedActual,
  761. BindResult<?> expectedUserLinkedActual) {
  762. if (expectedUserLinkedActual != null) {
  763. assertNull("cannot have actual if expecting user binding", expectedActual);
  764. assertNull("cannot have default if expecting user binding", expectedDefault);
  765. }
  766. Set<Element> elements = ImmutableSet.copyOf(Elements.getElements(modules));
  767. Map<Key<?>, Binding<?>> indexed = index(elements);
  768. Key<Optional<T>> optionalKey =
  769. keyType.ofType(OptionalBinder.optionalOf(keyType.getTypeLiteral()));
  770. Key<?> javaOptionalKey = HAS_JAVA_OPTIONAL ?
  771. keyType.ofType(OptionalBinder.javaOptionalOf(keyType.getTypeLiteral())) : null;
  772. Visitor visitor = new Visitor();
  773. OptionalBinderBinding<Optional<T>> optionalBinder = null;
  774. OptionalBinderBinding<?> javaOptionalBinder = null;
  775. Key<?> defaultKey = null;
  776. Key<?> actualKey = null;
  777. Binding optionalBinding = indexed.get(optionalKey);
  778. optionalBinder =
  779. (OptionalBinderBinding<Optional<T>>) optionalBinding.acceptTargetVisitor(visitor);
  780. if (HAS_JAVA_OPTIONAL) {
  781. Binding javaOptionalBinding = indexed.get(javaOptionalKey);
  782. javaOptionalBinder = (OptionalBinderBinding) javaOptionalBinding.acceptTargetVisitor(visitor);
  783. }
  784. // Locate the defaultKey & actualKey
  785. for (Element element : elements) {
  786. if (optionalBinder.containsElement(element) && element instanceof Binding) {
  787. Binding binding = (Binding) element;
  788. if (isSourceEntry(binding, Source.DEFAULT)) {
  789. defaultKey = binding.getKey();
  790. } else if (isSourceEntry(binding, Source.ACTUAL)) {
  791. actualKey = binding.getKey();
  792. }
  793. }
  794. }
  795. assertNotNull(optionalBinder);
  796. if (HAS_JAVA_OPTIONAL) {
  797. assertNotNull(javaOptionalBinder);
  798. }
  799. assertEquals(expectedDefault == null, defaultKey == null);
  800. assertEquals(expectedActual == null, actualKey == null);
  801. Key<Optional<javax.inject.Provider<T>>> optionalJavaxProviderKey =
  802. keyType.ofType(optionalOfJavaxProvider(keyType.getTypeLiteral()));
  803. Key<?> javaOptionalJavaxProviderKey = HAS_JAVA_OPTIONAL ?
  804. keyType.ofType(javaOptionalOfJavaxProvider(keyType.getTypeLiteral())) : null;
  805. Key<Optional<Provider<T>>> optionalProviderKey =
  806. keyType.ofType(optionalOfProvider(keyType.getTypeLiteral()));
  807. Key<?> javaOptionalProviderKey = HAS_JAVA_OPTIONAL ?
  808. keyType.ofType(javaOptionalOfProvider(keyType.getTypeLiteral())) : null;
  809. boolean keyMatch = false;
  810. boolean optionalKeyMatch = false;
  811. boolean javaOptionalKeyMatch = false;
  812. boolean optionalJavaxProviderKeyMatch = false;
  813. boolean javaOptionalJavaxProviderKeyMatch = false;
  814. boolean optionalProviderKeyMatch = false;
  815. boolean javaOptionalProviderKeyMatch = false;
  816. boolean defaultMatch = false;
  817. boolean actualMatch = false;
  818. List<Object> otherOptionalElements = Lists.newArrayList();
  819. List<Element> otherContains = Lists.newArrayList();
  820. List<Element> nonContainedElements = Lists.newArrayList();
  821. for (Element element : elements) {
  822. boolean contains = optionalBinder.containsElement(element);
  823. if (HAS_JAVA_OPTIONAL) {
  824. assertEquals(contains, javaOptionalBinder.containsElement(element));
  825. }
  826. if (!contains) {
  827. nonContainedElements.add(element);
  828. }
  829. Key key = null;
  830. Binding b = null;
  831. if (element instanceof Binding) {
  832. b = (Binding) element;
  833. key = b.getKey();
  834. Object visited = b.acceptTargetVisitor(visitor);
  835. if (visited instanceof OptionalBinderBinding) {
  836. if (visited.equals(optionalBinder)) {
  837. assertTrue(contains);
  838. } else if (HAS_JAVA_OPTIONAL && visited.equals(javaOptionalBinder)) {
  839. assertTrue(contains);
  840. } else {
  841. otherOptionalElements.add(visited);
  842. }
  843. }
  844. } else if (element instanceof ProviderLookup) {
  845. key = ((ProviderLookup) element).getKey();
  846. }
  847. if (key != null && key.equals(keyType)) {
  848. // keyType might match because a user bound it
  849. // (which is possible in a purely absent OptionalBinder)
  850. assertEquals(expectedDefault != null || expectedActual != null, contains);
  851. if (contains) {
  852. keyMatch = true;
  853. }
  854. } else if (key != null && key.equals(optionalKey)) {
  855. assertTrue(contains);
  856. optionalKeyMatch = true;
  857. } else if (key != null && key.equals(javaOptionalKey)) {
  858. assertTrue(contains);
  859. javaOptionalKeyMatch = true;
  860. } else if (key != null && key.equals(optionalJavaxProviderKey)) {
  861. assertTrue(contains);
  862. optionalJavaxProviderKeyMatch = true;
  863. } else if (key != null && key.equals(javaOptionalJavaxProviderKey)) {
  864. assertTrue(contains);
  865. javaOptionalJavaxProviderKeyMatch = true;
  866. } else if (key != null && key.equals(optionalProviderKey)) {
  867. assertTrue(contains);
  868. optionalProviderKeyMatch = true;
  869. } else if (key != null && key.equals(javaOptionalProviderKey)) {
  870. assertTrue(contains);
  871. javaOptionalProviderKeyMatch = true;
  872. } else if (key != null && key.equals(defaultKey)) {
  873. assertTrue(contains);
  874. if (b != null) { // otherwise it might just be a ProviderLookup into it
  875. assertTrue("expected: " + expectedDefault + ", but was: " + b,
  876. matches(b, expectedDefault));
  877. defaultMatch = true;
  878. }
  879. } else if (key != null && key.equals(actualKey)) {
  880. assertTrue(contains);
  881. if (b != null) { // otherwise it might just be a ProviderLookup into it
  882. assertTrue("expected: " + expectedActual + ", but was: " + b, matches(b, expectedActual));
  883. actualMatch = true;
  884. }
  885. } else if (contains) {
  886. otherContains.add(element);
  887. }
  888. }
  889. // only expect a keymatch if either default or actual are set
  890. assertEquals(expectedDefault != null || expectedActual != null, keyMatch);
  891. assertTrue(optionalKeyMatch);
  892. assertTrue(optionalJavaxProviderKeyMatch);
  893. assertTrue(optionalProviderKeyMatch);
  894. assertEquals(HAS_JAVA_OPTIONAL, javaOptionalKeyMatch);
  895. assertEquals(HAS_JAVA_OPTIONAL, javaOptionalJavaxProviderKeyMatch);
  896. assertEquals(HAS_JAVA_OPTIONAL, javaOptionalProviderKeyMatch);
  897. assertEquals(expectedDefault != null, defaultMatch);
  898. assertEquals(expectedActual != null, actualMatch);
  899. assertEquals(otherContains.toString(), 0, otherContains.size());
  900. assertEquals("other OptionalBindings found: " + otherOptionalElements,
  901. expectedOtherOptionalBindings, otherOptionalElements.size());
  902. // Validate that we can construct an injector out of the remaining bindings.
  903. Guice.createInjector(Elements.getModule(nonContainedElements));
  904. }
  905. private static boolean isSourceEntry(Binding b, Source type) {
  906. switch(type) {
  907. case ACTUAL:
  908. return b.getKey().getAnnotation() instanceof OptionalBinder.Actual;
  909. case DEFAULT:
  910. return b.getKey().getAnnotation() instanceof OptionalBinder.Default;
  911. default:
  912. throw new IllegalStateException("invalid type: " + type);
  913. }
  914. }
  915. /** Returns the subset of elements that have keys, indexed by them. */
  916. private static Map<Key<?>, Binding<?>> index(Iterable<Element> elements) {
  917. ImmutableMap.Builder<Key<?>, Binding<?>> builder = ImmutableMap.builder();
  918. for (Element element : elements) {
  919. if (element instanceof Binding) {
  920. builder.put(((Binding) element).getKey(), (Binding) element);
  921. }
  922. }
  923. return builder.build();
  924. }
  925. static <K, V> MapResult instance(K k, V v) {
  926. return new MapResult<K, V>(k, new BindResult<V>(INSTANCE, v, null));
  927. }
  928. static <K, V> MapResult linked(K k, Class<? extends V> clazz) {
  929. return new MapResult<K, V>(k, new BindResult<V>(LINKED, null, Key.get(clazz)));
  930. }
  931. static <K, V> MapResult linked(K k, Key<? extends V> key) {
  932. return new MapResult<K, V>(k, new BindResult<V>(LINKED, null, key));
  933. }
  934. static <K, V> MapResult providerInstance(K k, V v) {
  935. return new MapResult<K, V>(k, new BindResult<V>(PROVIDER_INSTANCE, v, null));
  936. }
  937. static class MapResult<K, V> {
  938. private final K k;
  939. private final BindResult<V> v;
  940. MapResult(K k, BindResult<V> v) {
  941. this.k = k;
  942. this.v = v;
  943. }
  944. @Override
  945. public String toString() {
  946. return "entry[key[" + k + "],value[" + v + "]]";
  947. }
  948. }
  949. private static boolean matches(Binding<?> item, BindResult<?> result) {
  950. switch (result.type) {
  951. case INSTANCE:
  952. if (item instanceof InstanceBinding
  953. && ((InstanceBinding) item).getInstance().equals(result.instance)) {
  954. return true;
  955. }
  956. break;
  957. case LINKED:
  958. if (item instanceof LinkedKeyBinding
  959. && ((LinkedKeyBinding) item).getLinkedKey().equals(result.key)) {
  960. return true;
  961. }
  962. break;
  963. case PROVIDER_INSTANCE:
  964. if (item instanceof ProviderInstanceBinding
  965. && Objects.equal(((ProviderInstanceBinding) item).getUserSuppliedProvider().get(),
  966. result.instance)) {
  967. return true;
  968. }
  969. break;
  970. case PROVIDER_KEY:
  971. if (item instanceof ProviderKeyBinding
  972. && ((ProviderKeyBinding) item).getProviderKey().equals(result.key)) {
  973. return true;
  974. }
  975. break;
  976. }
  977. return false;
  978. }
  979. static <T> BindResult<T> instance(T t) {
  980. return new BindResult<T>(INSTANCE, t, null);
  981. }
  982. static <T> BindResult<T> linked(Class<? extends T> clazz) {
  983. return new BindResult<T>(LINKED, null, Key.get(clazz));
  984. }
  985. static <T> BindResult<T> linked(Key<? extends T> key) {
  986. return new BindResult<T>(LINKED, null, key);
  987. }
  988. static <T> BindResult<T> providerInstance(T t) {
  989. return new BindResult<T>(PROVIDER_INSTANCE, t, null);
  990. }
  991. static <T> BindResult<T> providerKey(Key<T> key) {
  992. return new BindResult<T>(PROVIDER_KEY, null, key);
  993. }
  994. /** The kind of binding. */
  995. static enum BindType { INSTANCE, LINKED, PROVIDER_INSTANCE, PROVIDER_KEY }
  996. /** The result of the binding. */
  997. static class BindResult<T> {
  998. private final BindType type;
  999. private final Key<?> key;
  1000. private final T instance;
  1001. private BindResult(BindType type, T instance, Key<?> key) {
  1002. this.type = type;
  1003. this.instance = instance;
  1004. this.key = key;
  1005. }
  1006. @Override
  1007. public String toString() {
  1008. switch(type) {
  1009. case INSTANCE:
  1010. return "instance[" + instance + "]";
  1011. case LINKED:
  1012. return "linkedKey[" + key + "]";
  1013. case PROVIDER_INSTANCE:
  1014. return "providerInstance[" + instance + "]";
  1015. case PROVIDER_KEY:
  1016. return "providerKey[" + key + "]";
  1017. }
  1018. return null;
  1019. }
  1020. }
  1021. private static class Visitor<T> extends
  1022. DefaultBindingTargetVisitor<T, Object> implements MultibindingsTargetVisitor<T, Object> {
  1023. public Object visit(MultibinderBinding<? extends T> multibinding) {
  1024. return multibinding;
  1025. }
  1026. public Object visit(MapBinderBinding<? extends T> mapbinding) {
  1027. return mapbinding;
  1028. }
  1029. public Object visit(OptionalBinderBinding<? extends T> optionalbinding) {
  1030. return optionalbinding;
  1031. }
  1032. }
  1033. }