1 /* 2 * Copyright (C) 2014 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 dagger; 17 18 import dagger.internal.Beta; 19 import java.lang.annotation.Documented; 20 import java.lang.annotation.Retention; 21 import java.lang.annotation.Target; 22 import java.util.Map; 23 24 import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 25 import static java.lang.annotation.RetentionPolicy.RUNTIME; 26 27 /** 28 * Identifies annotation types that are used to associate keys with values returned by 29 * {@linkplain Provides provider methods} in order to compose a {@linkplain Provides.Type#MAP map}. 30 * 31 * <p>Every provider method annotated with {@code @Provides(type = MAP)} must also have an 32 * annotation that identifies the key for that map entry. That annotation's type must be annotated 33 * with {@code @MapKey}. 34 * 35 * <p>Typically, the key annotation has a single member, whose value is used as the map key. 36 * 37 * <p>For example, to add an entry to a {@code Map<SomeEnum, Integer>} with key 38 * {@code SomeEnum.FOO}, you could use an annotation called {@code @SomeEnumKey}: 39 * 40 * <pre><code> 41 * {@literal @}MapKey 42 * {@literal @}interface SomeEnumKey { 43 * SomeEnum value(); 44 * } 45 * 46 * {@literal @}Module 47 * class SomeModule { 48 * {@literal @}Provides(type = MAP) 49 * {@literal @}SomeEnumKey(SomeEnum.FOO) 50 * Integer provideFooValue() { 51 * return 2; 52 * } 53 * } 54 * 55 * class SomeInjectedType { 56 * {@literal @}Inject 57 * SomeInjectedType(Map<SomeEnum, Integer> map) { 58 * assert map.get(SomeEnum.FOO) == 2; 59 * } 60 * } 61 * </code></pre> 62 * 63 * <p>If {@code unwrapValue} is true, the annotation's single member can be any type except an 64 * array. 65 * 66 * <p>See {@link dagger.mapkeys} for standard unwrapped map key annotations for keys that are boxed 67 * primitives, strings, or classes. 68 * 69 * <h2>Annotations as keys</h2> 70 * 71 * <p>If {@link #unwrapValue} is false, then the annotation itself is used as the map key. For 72 * example, to add an entry to a {@code Map<MyMapKey, Integer>} map: 73 * 74 * <pre><code> 75 * {@literal @}MapKey(unwrapValue = false) 76 * {@literal @}interface MyMapKey { 77 * String someString(); 78 * MyEnum someEnum(); 79 * } 80 * 81 * {@literal @}Module 82 * class SomeModule { 83 * {@literal @}Provides(type = MAP) 84 * {@literal @}MyMapKey(someString = "foo", someEnum = BAR) 85 * Integer provideFooBarValue() { 86 * return 2; 87 * } 88 * } 89 * 90 * class SomeInjectedType { 91 * {@literal @}Inject 92 * SomeInjectedType(Map<MyMapKey, Integer> map) { 93 * assert map.get(new MyMapKeyImpl("foo", MyEnum.BAR)) == 2; 94 * } 95 * } 96 * </code></pre> 97 * 98 * <p>(Note that there must be a class {@code MyMapKeyImpl} that implements {@code MyMapKey} in 99 * order to call {@link Map#get(Object)} on the provided map.) 100 * 101 */ 102 @Documented 103 @Target(ANNOTATION_TYPE) 104 @Retention(RUNTIME) 105 @Beta 106 public @interface MapKey { 107 /** 108 * True to use the value of the single member of the annotated annotation as the map key; false 109 * to use the annotation instance as the map key. 110 * 111 * <p>If true, the single member must not be an array. 112 */ unwrapValue()113 boolean unwrapValue() default true; 114 } 115