Coverage Summary for Class: ImmutableClassToInstanceMap (com.google.common.collect)
| Class | Method, % | Line, % |
|---|---|---|
| ImmutableClassToInstanceMap | 63.6% (7/11) | 55.6% (10/18) |
| ImmutableClassToInstanceMap$Builder | 60% (3/5) | 53.3% (8/15) |
| Total | 62.5% (10/16) | 54.5% (18/33) |
1 /* 2 * Copyright (C) 2009 The Guava 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 com.google.common.collect; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 21 import com.google.common.annotations.GwtIncompatible; 22 import com.google.common.primitives.Primitives; 23 import com.google.errorprone.annotations.CanIgnoreReturnValue; 24 import com.google.errorprone.annotations.DoNotCall; 25 import com.google.errorprone.annotations.Immutable; 26 import java.io.Serializable; 27 import java.util.Map; 28 import org.checkerframework.checker.nullness.qual.Nullable; 29 30 /** 31 * A {@link ClassToInstanceMap} whose contents will never change, with many other important 32 * properties detailed at {@link ImmutableCollection}. 33 * 34 * @author Kevin Bourrillion 35 * @since 2.0 36 */ 37 @Immutable(containerOf = "B") 38 @GwtIncompatible 39 public final class ImmutableClassToInstanceMap<B> extends ForwardingMap<Class<? extends B>, B> 40 implements ClassToInstanceMap<B>, Serializable { 41 42 private static final ImmutableClassToInstanceMap<Object> EMPTY = 43 new ImmutableClassToInstanceMap<>(ImmutableMap.<Class<?>, Object>of()); 44 45 /** 46 * Returns an empty {@code ImmutableClassToInstanceMap}. 47 * 48 * <p><b>Performance note:</b> the instance returned is a singleton. 49 * 50 * @since 19.0 51 */ 52 @SuppressWarnings("unchecked") 53 public static <B> ImmutableClassToInstanceMap<B> of() { 54 return (ImmutableClassToInstanceMap<B>) EMPTY; 55 } 56 57 /** 58 * Returns an {@code ImmutableClassToInstanceMap} containing a single entry. 59 * 60 * @since 19.0 61 */ 62 public static <B, T extends B> ImmutableClassToInstanceMap<B> of(Class<T> type, T value) { 63 ImmutableMap<Class<? extends B>, B> map = ImmutableMap.<Class<? extends B>, B>of(type, value); 64 return new ImmutableClassToInstanceMap<B>(map); 65 } 66 67 /** 68 * Returns a new builder. The generated builder is equivalent to the builder created by the {@link 69 * Builder} constructor. 70 */ 71 public static <B> Builder<B> builder() { 72 return new Builder<B>(); 73 } 74 75 /** 76 * A builder for creating immutable class-to-instance maps. Example: 77 * 78 * <pre>{@code 79 * static final ImmutableClassToInstanceMap<Handler> HANDLERS = 80 * new ImmutableClassToInstanceMap.Builder<Handler>() 81 * .put(FooHandler.class, new FooHandler()) 82 * .put(BarHandler.class, new SubBarHandler()) 83 * .put(Handler.class, new QuuxHandler()) 84 * .build(); 85 * }</pre> 86 * 87 * <p>After invoking {@link #build()} it is still possible to add more entries and build again. 88 * Thus each map generated by this builder will be a superset of any map generated before it. 89 * 90 * @since 2.0 91 */ 92 public static final class Builder<B> { 93 private final ImmutableMap.Builder<Class<? extends B>, B> mapBuilder = ImmutableMap.builder(); 94 95 /** 96 * Associates {@code key} with {@code value} in the built map. Duplicate keys are not allowed, 97 * and will cause {@link #build} to fail. 98 */ 99 @CanIgnoreReturnValue 100 public <T extends B> Builder<B> put(Class<T> key, T value) { 101 mapBuilder.put(key, value); 102 return this; 103 } 104 105 /** 106 * Associates all of {@code map's} keys and values in the built map. Duplicate keys are not 107 * allowed, and will cause {@link #build} to fail. 108 * 109 * @throws NullPointerException if any key or value in {@code map} is null 110 * @throws ClassCastException if any value is not an instance of the type specified by its key 111 */ 112 @CanIgnoreReturnValue 113 public <T extends B> Builder<B> putAll(Map<? extends Class<? extends T>, ? extends T> map) { 114 for (Entry<? extends Class<? extends T>, ? extends T> entry : map.entrySet()) { 115 Class<? extends T> type = entry.getKey(); 116 T value = entry.getValue(); 117 mapBuilder.put(type, cast(type, value)); 118 } 119 return this; 120 } 121 122 private static <B, T extends B> T cast(Class<T> type, B value) { 123 return Primitives.wrap(type).cast(value); 124 } 125 126 /** 127 * Returns a new immutable class-to-instance map containing the entries provided to this 128 * builder. 129 * 130 * @throws IllegalArgumentException if duplicate keys were added 131 */ 132 public ImmutableClassToInstanceMap<B> build() { 133 ImmutableMap<Class<? extends B>, B> map = mapBuilder.build(); 134 if (map.isEmpty()) { 135 return of(); 136 } else { 137 return new ImmutableClassToInstanceMap<B>(map); 138 } 139 } 140 } 141 142 /** 143 * Returns an immutable map containing the same entries as {@code map}. If {@code map} somehow 144 * contains entries with duplicate keys (for example, if it is a {@code SortedMap} whose 145 * comparator is not <i>consistent with equals</i>), the results of this method are undefined. 146 * 147 * <p><b>Note:</b> Despite what the method name suggests, if {@code map} is an {@code 148 * ImmutableClassToInstanceMap}, no copy will actually be performed. 149 * 150 * @throws NullPointerException if any key or value in {@code map} is null 151 * @throws ClassCastException if any value is not an instance of the type specified by its key 152 */ 153 public static <B, S extends B> ImmutableClassToInstanceMap<B> copyOf( 154 Map<? extends Class<? extends S>, ? extends S> map) { 155 if (map instanceof ImmutableClassToInstanceMap) { 156 @SuppressWarnings("unchecked") // covariant casts safe (unmodifiable) 157 ImmutableClassToInstanceMap<B> cast = (ImmutableClassToInstanceMap<B>) map; 158 return cast; 159 } 160 return new Builder<B>().putAll(map).build(); 161 } 162 163 private final ImmutableMap<Class<? extends B>, B> delegate; 164 165 private ImmutableClassToInstanceMap(ImmutableMap<Class<? extends B>, B> delegate) { 166 this.delegate = delegate; 167 } 168 169 @Override 170 protected Map<Class<? extends B>, B> delegate() { 171 return delegate; 172 } 173 174 @Override 175 @SuppressWarnings("unchecked") // value could not get in if not a T 176 public <T extends B> @Nullable T getInstance(Class<T> type) { 177 return (T) delegate.get(checkNotNull(type)); 178 } 179 180 /** 181 * Guaranteed to throw an exception and leave the map unmodified. 182 * 183 * @throws UnsupportedOperationException always 184 * @deprecated Unsupported operation. 185 */ 186 @CanIgnoreReturnValue 187 @Deprecated 188 @Override 189 @DoNotCall("Always throws UnsupportedOperationException") 190 public <T extends B> T putInstance(Class<T> type, T value) { 191 throw new UnsupportedOperationException(); 192 } 193 194 Object readResolve() { 195 return isEmpty() ? of() : this; 196 } 197 }