17dd252788645e940eada959bdde927426e2531c9Paul Duffin/* 27dd252788645e940eada959bdde927426e2531c9Paul Duffin * Copyright (C) 2012 The Guava Authors 37dd252788645e940eada959bdde927426e2531c9Paul Duffin * 47dd252788645e940eada959bdde927426e2531c9Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License"); 57dd252788645e940eada959bdde927426e2531c9Paul Duffin * you may not use this file except in compliance with the License. 67dd252788645e940eada959bdde927426e2531c9Paul Duffin * You may obtain a copy of the License at 77dd252788645e940eada959bdde927426e2531c9Paul Duffin * 87dd252788645e940eada959bdde927426e2531c9Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0 97dd252788645e940eada959bdde927426e2531c9Paul Duffin * 107dd252788645e940eada959bdde927426e2531c9Paul Duffin * Unless required by applicable law or agreed to in writing, software 117dd252788645e940eada959bdde927426e2531c9Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS, 127dd252788645e940eada959bdde927426e2531c9Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137dd252788645e940eada959bdde927426e2531c9Paul Duffin * See the License for the specific language governing permissions and 147dd252788645e940eada959bdde927426e2531c9Paul Duffin * limitations under the License. 157dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 167dd252788645e940eada959bdde927426e2531c9Paul Duffin 177dd252788645e940eada959bdde927426e2531c9Paul Duffinpackage com.google.common.reflect; 187dd252788645e940eada959bdde927426e2531c9Paul Duffin 197dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.annotations.Beta; 207dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.ForwardingMap; 217dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.ImmutableMap; 227dd252788645e940eada959bdde927426e2531c9Paul Duffin 237dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Map; 247dd252788645e940eada959bdde927426e2531c9Paul Duffin 257dd252788645e940eada959bdde927426e2531c9Paul Duffin/** 267dd252788645e940eada959bdde927426e2531c9Paul Duffin * A type-to-instance map backed by an {@link ImmutableMap}. See also {@link 277dd252788645e940eada959bdde927426e2531c9Paul Duffin * MutableTypeToInstanceMap}. 287dd252788645e940eada959bdde927426e2531c9Paul Duffin * 297dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author Ben Yu 307dd252788645e940eada959bdde927426e2531c9Paul Duffin * @since 13.0 317dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 327dd252788645e940eada959bdde927426e2531c9Paul Duffin@Beta 337dd252788645e940eada959bdde927426e2531c9Paul Duffinpublic final class ImmutableTypeToInstanceMap<B> extends ForwardingMap<TypeToken<? extends B>, B> 347dd252788645e940eada959bdde927426e2531c9Paul Duffin implements TypeToInstanceMap<B> { 357dd252788645e940eada959bdde927426e2531c9Paul Duffin 367dd252788645e940eada959bdde927426e2531c9Paul Duffin /** Returns an empty type to instance map. */ 377dd252788645e940eada959bdde927426e2531c9Paul Duffin public static <B> ImmutableTypeToInstanceMap<B> of() { 380888a09821a98ac0680fad765217302858e70fa4Paul Duffin return new ImmutableTypeToInstanceMap<B>(ImmutableMap.<TypeToken<? extends B>, B>of()); 397dd252788645e940eada959bdde927426e2531c9Paul Duffin } 407dd252788645e940eada959bdde927426e2531c9Paul Duffin 417dd252788645e940eada959bdde927426e2531c9Paul Duffin /** Returns a new builder. */ 427dd252788645e940eada959bdde927426e2531c9Paul Duffin public static <B> Builder<B> builder() { 437dd252788645e940eada959bdde927426e2531c9Paul Duffin return new Builder<B>(); 447dd252788645e940eada959bdde927426e2531c9Paul Duffin } 457dd252788645e940eada959bdde927426e2531c9Paul Duffin 467dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 477dd252788645e940eada959bdde927426e2531c9Paul Duffin * A builder for creating immutable type-to-instance maps. Example: 487dd252788645e940eada959bdde927426e2531c9Paul Duffin * <pre> {@code 497dd252788645e940eada959bdde927426e2531c9Paul Duffin * 507dd252788645e940eada959bdde927426e2531c9Paul Duffin * static final ImmutableTypeToInstanceMap<Handler<?>> HANDLERS = 517dd252788645e940eada959bdde927426e2531c9Paul Duffin * ImmutableTypeToInstanceMap.<Handler<?>>builder() 527dd252788645e940eada959bdde927426e2531c9Paul Duffin * .put(new TypeToken<Handler<Foo>>() {}, new FooHandler()) 537dd252788645e940eada959bdde927426e2531c9Paul Duffin * .put(new TypeToken<Handler<Bar>>() {}, new SubBarHandler()) 547dd252788645e940eada959bdde927426e2531c9Paul Duffin * .build();}</pre> 557dd252788645e940eada959bdde927426e2531c9Paul Duffin * 560888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <p>After invoking {@link #build()} it is still possible to add more entries 577dd252788645e940eada959bdde927426e2531c9Paul Duffin * and build again. Thus each map generated by this builder will be a superset 587dd252788645e940eada959bdde927426e2531c9Paul Duffin * of any map generated before it. 597dd252788645e940eada959bdde927426e2531c9Paul Duffin * 607dd252788645e940eada959bdde927426e2531c9Paul Duffin * @since 13.0 617dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 627dd252788645e940eada959bdde927426e2531c9Paul Duffin @Beta 637dd252788645e940eada959bdde927426e2531c9Paul Duffin public static final class Builder<B> { 640888a09821a98ac0680fad765217302858e70fa4Paul Duffin private final ImmutableMap.Builder<TypeToken<? extends B>, B> mapBuilder 650888a09821a98ac0680fad765217302858e70fa4Paul Duffin = ImmutableMap.builder(); 667dd252788645e940eada959bdde927426e2531c9Paul Duffin 677dd252788645e940eada959bdde927426e2531c9Paul Duffin private Builder() {} 687dd252788645e940eada959bdde927426e2531c9Paul Duffin 697dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 707dd252788645e940eada959bdde927426e2531c9Paul Duffin * Associates {@code key} with {@code value} in the built map. Duplicate 717dd252788645e940eada959bdde927426e2531c9Paul Duffin * keys are not allowed, and will cause {@link #build} to fail. 727dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 737dd252788645e940eada959bdde927426e2531c9Paul Duffin public <T extends B> Builder<B> put(Class<T> key, T value) { 747dd252788645e940eada959bdde927426e2531c9Paul Duffin mapBuilder.put(TypeToken.of(key), value); 757dd252788645e940eada959bdde927426e2531c9Paul Duffin return this; 767dd252788645e940eada959bdde927426e2531c9Paul Duffin } 777dd252788645e940eada959bdde927426e2531c9Paul Duffin 787dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 797dd252788645e940eada959bdde927426e2531c9Paul Duffin * Associates {@code key} with {@code value} in the built map. Duplicate 807dd252788645e940eada959bdde927426e2531c9Paul Duffin * keys are not allowed, and will cause {@link #build} to fail. 817dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 827dd252788645e940eada959bdde927426e2531c9Paul Duffin public <T extends B> Builder<B> put(TypeToken<T> key, T value) { 837dd252788645e940eada959bdde927426e2531c9Paul Duffin mapBuilder.put(key.rejectTypeVariables(), value); 847dd252788645e940eada959bdde927426e2531c9Paul Duffin return this; 857dd252788645e940eada959bdde927426e2531c9Paul Duffin } 867dd252788645e940eada959bdde927426e2531c9Paul Duffin 877dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 887dd252788645e940eada959bdde927426e2531c9Paul Duffin * Returns a new immutable type-to-instance map containing the entries 897dd252788645e940eada959bdde927426e2531c9Paul Duffin * provided to this builder. 907dd252788645e940eada959bdde927426e2531c9Paul Duffin * 917dd252788645e940eada959bdde927426e2531c9Paul Duffin * @throws IllegalArgumentException if duplicate keys were added 927dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 937dd252788645e940eada959bdde927426e2531c9Paul Duffin public ImmutableTypeToInstanceMap<B> build() { 947dd252788645e940eada959bdde927426e2531c9Paul Duffin return new ImmutableTypeToInstanceMap<B>(mapBuilder.build()); 957dd252788645e940eada959bdde927426e2531c9Paul Duffin } 967dd252788645e940eada959bdde927426e2531c9Paul Duffin } 977dd252788645e940eada959bdde927426e2531c9Paul Duffin 987dd252788645e940eada959bdde927426e2531c9Paul Duffin private final ImmutableMap<TypeToken<? extends B>, B> delegate; 997dd252788645e940eada959bdde927426e2531c9Paul Duffin 1007dd252788645e940eada959bdde927426e2531c9Paul Duffin private ImmutableTypeToInstanceMap(ImmutableMap<TypeToken<? extends B>, B> delegate) { 1017dd252788645e940eada959bdde927426e2531c9Paul Duffin this.delegate = delegate; 1027dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1037dd252788645e940eada959bdde927426e2531c9Paul Duffin 1040888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public <T extends B> T getInstance(TypeToken<T> type) { 1057dd252788645e940eada959bdde927426e2531c9Paul Duffin return trustedGet(type.rejectTypeVariables()); 1067dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1077dd252788645e940eada959bdde927426e2531c9Paul Duffin 1087dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 1097dd252788645e940eada959bdde927426e2531c9Paul Duffin * Guaranteed to throw an exception and leave the map unmodified. 1107dd252788645e940eada959bdde927426e2531c9Paul Duffin * 1117dd252788645e940eada959bdde927426e2531c9Paul Duffin * @throws UnsupportedOperationException always 1127dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 1130888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public <T extends B> T putInstance(TypeToken<T> type, T value) { 1147dd252788645e940eada959bdde927426e2531c9Paul Duffin throw new UnsupportedOperationException(); 1157dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1167dd252788645e940eada959bdde927426e2531c9Paul Duffin 1170888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public <T extends B> T getInstance(Class<T> type) { 1187dd252788645e940eada959bdde927426e2531c9Paul Duffin return trustedGet(TypeToken.of(type)); 1197dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1207dd252788645e940eada959bdde927426e2531c9Paul Duffin 1217dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 1227dd252788645e940eada959bdde927426e2531c9Paul Duffin * Guaranteed to throw an exception and leave the map unmodified. 1237dd252788645e940eada959bdde927426e2531c9Paul Duffin * 1247dd252788645e940eada959bdde927426e2531c9Paul Duffin * @throws UnsupportedOperationException always 1257dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 1260888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public <T extends B> T putInstance(Class<T> type, T value) { 1277dd252788645e940eada959bdde927426e2531c9Paul Duffin throw new UnsupportedOperationException(); 1287dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1297dd252788645e940eada959bdde927426e2531c9Paul Duffin 1300888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override protected Map<TypeToken<? extends B>, B> delegate() { 1317dd252788645e940eada959bdde927426e2531c9Paul Duffin return delegate; 1327dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1337dd252788645e940eada959bdde927426e2531c9Paul Duffin 1340888a09821a98ac0680fad765217302858e70fa4Paul Duffin @SuppressWarnings("unchecked") // value could not get in if not a T 1357dd252788645e940eada959bdde927426e2531c9Paul Duffin private <T extends B> T trustedGet(TypeToken<T> type) { 1367dd252788645e940eada959bdde927426e2531c9Paul Duffin return (T) delegate.get(type); 1377dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1387dd252788645e940eada959bdde927426e2531c9Paul Duffin} 139