1 /* 2 * Copyright (C) 2014 The Dagger Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dagger; 18 19 import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 20 import static java.lang.annotation.RetentionPolicy.RUNTIME; 21 22 import java.lang.annotation.Documented; 23 import java.lang.annotation.Retention; 24 import java.lang.annotation.Target; 25 import java.util.Map; 26 27 /** 28 * Identifies annotation types that are used to associate keys with values returned by {@linkplain 29 * Provides provider methods} in order to compose a {@linkplain dagger.multibindings.IntoMap map}. 30 * 31 * <p>Every provider method annotated with {@code @Provides} and {@code @IntoMap} 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 {@code 38 * 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 49 * {@literal @}IntoMap 50 * {@literal @}SomeEnumKey(SomeEnum.FOO) 51 * Integer provideFooValue() { 52 * return 2; 53 * } 54 * } 55 * 56 * class SomeInjectedType { 57 * {@literal @}Inject 58 * SomeInjectedType({@literal Map<SomeEnum, Integer>} map) { 59 * assert map.get(SomeEnum.FOO) == 2; 60 * } 61 * } 62 * </code></pre> 63 * 64 * <p>If {@code unwrapValue} is true, the annotation's single member can be any type except an 65 * array. 66 * 67 * <p>See {@link dagger.multibindings} for standard unwrapped map key annotations for keys that are 68 * boxed primitives, strings, or classes. 69 * 70 * <h2>Annotations as keys</h2> 71 * 72 * <p>If {@link #unwrapValue} is false, then the annotation itself is used as the map key. For 73 * example, to add an entry to a {@code Map<MyMapKey, Integer>} map: 74 * 75 * <pre><code> 76 * {@literal @}MapKey(unwrapValue = false) 77 * {@literal @}interface MyMapKey { 78 * String someString(); 79 * MyEnum someEnum(); 80 * } 81 * 82 * {@literal @}Module 83 * class SomeModule { 84 * {@literal @}Provides 85 * {@literal @}IntoMap 86 * {@literal @}MyMapKey(someString = "foo", someEnum = BAR) 87 * Integer provideFooBarValue() { 88 * return 2; 89 * } 90 * } 91 * 92 * class SomeInjectedType { 93 * {@literal @}Inject 94 * SomeInjectedType({@literal Map<MyMapKey, Integer>} map) { 95 * assert map.get(new MyMapKeyImpl("foo", MyEnum.BAR)) == 2; 96 * } 97 * } 98 * </code></pre> 99 * 100 * <p>(Note that there must be a class {@code MyMapKeyImpl} that implements {@code MyMapKey} in 101 * order to call {@link Map#get(Object)} on the provided map.) 102 * 103 * @see <a href="https://dagger.dev/multibindings#map-multibindings">Map multibinding</a> 104 */ 105 @Documented 106 @Target(ANNOTATION_TYPE) 107 @Retention(RUNTIME) 108 public @interface MapKey { 109 /** 110 * True to use the value of the single member of the annotated annotation as the map key; false 111 * to use the annotation instance as the map key. 112 * 113 * <p>If true, the single member must not be an array. 114 */ unwrapValue()115 boolean unwrapValue() default true; 116 } 117