1 /* 2 * Copyright (C) 2024 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.internal; 18 19 import java.util.Collection; 20 import java.util.Map; 21 import java.util.Set; 22 23 /** 24 * A class keyed map that delegates to a string keyed map under the hood. 25 * 26 * <p>A {@code LazyClassKeyMap} is created for @LazyClassKey contributed map binding. 27 */ 28 public final class LazyClassKeyMap<V> implements Map<Class<?>, V> { 29 private final Map<String, V> delegate; 30 of(Map<String, V> delegate)31 public static <V> Map<Class<?>, V> of(Map<String, V> delegate) { 32 return new LazyClassKeyMap<>(delegate); 33 } 34 LazyClassKeyMap(Map<String, V> delegate)35 private LazyClassKeyMap(Map<String, V> delegate) { 36 this.delegate = delegate; 37 } 38 39 @Override get(Object key)40 public V get(Object key) { 41 if (!(key instanceof Class)) { 42 throw new IllegalArgumentException("Key must be a class"); 43 } 44 return delegate.get(((Class<?>) key).getName()); 45 } 46 47 @Override keySet()48 public Set<Class<?>> keySet() { 49 // This method will load all class keys, therefore no need to use @LazyClassKey annotated 50 // bindings. 51 throw new UnsupportedOperationException( 52 "Maps created with @LazyClassKey do not support usage of keySet(). Consider @ClassKey" 53 + " instead."); 54 } 55 56 @Override values()57 public Collection<V> values() { 58 return delegate.values(); 59 } 60 61 @Override isEmpty()62 public boolean isEmpty() { 63 return delegate.isEmpty(); 64 } 65 66 @Override containsKey(Object key)67 public boolean containsKey(Object key) { 68 if (!(key instanceof Class)) { 69 throw new IllegalArgumentException("Key must be a class"); 70 } 71 return delegate.containsKey(((Class<?>) key).getName()); 72 } 73 74 @Override containsValue(Object value)75 public boolean containsValue(Object value) { 76 return delegate.containsValue(value); 77 } 78 79 @Override size()80 public int size() { 81 return delegate.size(); 82 } 83 84 @Override entrySet()85 public Set<Map.Entry<Class<?>, V>> entrySet() { 86 // This method will load all class keys, therefore no need to use @LazyClassKey annotated 87 // bindings. 88 throw new UnsupportedOperationException( 89 "Maps created with @LazyClassKey do not support usage of entrySet(). Consider @ClassKey" 90 + " instead."); 91 } 92 93 // The dagger map binding should be a immutable map. 94 @Override remove(Object key)95 public V remove(Object key) { 96 throw new UnsupportedOperationException("Dagger map bindings are immutable"); 97 } 98 99 @Override clear()100 public void clear() { 101 throw new UnsupportedOperationException("Dagger map bindings are immutable"); 102 } 103 104 @Override put(Class<?> key, V value)105 public V put(Class<?> key, V value) { 106 throw new UnsupportedOperationException("Dagger map bindings are immutable"); 107 } 108 109 @Override putAll(Map<? extends Class<?>, ? extends V> map)110 public void putAll(Map<? extends Class<?>, ? extends V> map) { 111 throw new UnsupportedOperationException("Dagger map bindings are immutable"); 112 } 113 114 /** A factory for {@code LazyClassKeyMap}. */ 115 public static class Factory<V> implements Provider<Map<Class<?>, V>> { 116 MapFactory<String, V> delegate; 117 of(MapFactory<String, V> delegate)118 public static <V> Factory<V> of(MapFactory<String, V> delegate) { 119 return new Factory<>(delegate); 120 } 121 Factory(MapFactory<String, V> delegate)122 private Factory(MapFactory<String, V> delegate) { 123 this.delegate = delegate; 124 } 125 126 @Override get()127 public Map<Class<?>, V> get() { 128 return LazyClassKeyMap.of(delegate.get()); 129 } 130 } 131 } 132