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