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 190888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.base.Preconditions.checkNotNull; 200888a09821a98ac0680fad765217302858e70fa4Paul Duffin 217dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.annotations.Beta; 220888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.base.Function; 237dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.ForwardingMap; 240888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.collect.ForwardingMapEntry; 250888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.collect.ForwardingSet; 260888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.collect.Iterators; 277dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.Maps; 287dd252788645e940eada959bdde927426e2531c9Paul Duffin 290888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.Iterator; 307dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Map; 310888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.Set; 327dd252788645e940eada959bdde927426e2531c9Paul Duffin 337dd252788645e940eada959bdde927426e2531c9Paul Duffinimport javax.annotation.Nullable; 347dd252788645e940eada959bdde927426e2531c9Paul Duffin 357dd252788645e940eada959bdde927426e2531c9Paul Duffin/** 367dd252788645e940eada959bdde927426e2531c9Paul Duffin * A mutable type-to-instance map. 377dd252788645e940eada959bdde927426e2531c9Paul Duffin * See also {@link ImmutableTypeToInstanceMap}. 387dd252788645e940eada959bdde927426e2531c9Paul Duffin * 397dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author Ben Yu 407dd252788645e940eada959bdde927426e2531c9Paul Duffin * @since 13.0 417dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 427dd252788645e940eada959bdde927426e2531c9Paul Duffin@Beta 437dd252788645e940eada959bdde927426e2531c9Paul Duffinpublic final class MutableTypeToInstanceMap<B> extends ForwardingMap<TypeToken<? extends B>, B> 447dd252788645e940eada959bdde927426e2531c9Paul Duffin implements TypeToInstanceMap<B> { 457dd252788645e940eada959bdde927426e2531c9Paul Duffin 467dd252788645e940eada959bdde927426e2531c9Paul Duffin private final Map<TypeToken<? extends B>, B> backingMap = Maps.newHashMap(); 477dd252788645e940eada959bdde927426e2531c9Paul Duffin 487dd252788645e940eada959bdde927426e2531c9Paul Duffin @Nullable 490888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 507dd252788645e940eada959bdde927426e2531c9Paul Duffin public <T extends B> T getInstance(Class<T> type) { 517dd252788645e940eada959bdde927426e2531c9Paul Duffin return trustedGet(TypeToken.of(type)); 527dd252788645e940eada959bdde927426e2531c9Paul Duffin } 537dd252788645e940eada959bdde927426e2531c9Paul Duffin 547dd252788645e940eada959bdde927426e2531c9Paul Duffin @Nullable 550888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 567dd252788645e940eada959bdde927426e2531c9Paul Duffin public <T extends B> T putInstance(Class<T> type, @Nullable T value) { 577dd252788645e940eada959bdde927426e2531c9Paul Duffin return trustedPut(TypeToken.of(type), value); 587dd252788645e940eada959bdde927426e2531c9Paul Duffin } 597dd252788645e940eada959bdde927426e2531c9Paul Duffin 607dd252788645e940eada959bdde927426e2531c9Paul Duffin @Nullable 610888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 627dd252788645e940eada959bdde927426e2531c9Paul Duffin public <T extends B> T getInstance(TypeToken<T> type) { 637dd252788645e940eada959bdde927426e2531c9Paul Duffin return trustedGet(type.rejectTypeVariables()); 647dd252788645e940eada959bdde927426e2531c9Paul Duffin } 657dd252788645e940eada959bdde927426e2531c9Paul Duffin 667dd252788645e940eada959bdde927426e2531c9Paul Duffin @Nullable 670888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 687dd252788645e940eada959bdde927426e2531c9Paul Duffin public <T extends B> T putInstance(TypeToken<T> type, @Nullable T value) { 697dd252788645e940eada959bdde927426e2531c9Paul Duffin return trustedPut(type.rejectTypeVariables(), value); 707dd252788645e940eada959bdde927426e2531c9Paul Duffin } 717dd252788645e940eada959bdde927426e2531c9Paul Duffin 727dd252788645e940eada959bdde927426e2531c9Paul Duffin /** Not supported. Use {@link #putInstance} instead. */ 730888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public B put(TypeToken<? extends B> key, B value) { 747dd252788645e940eada959bdde927426e2531c9Paul Duffin throw new UnsupportedOperationException("Please use putInstance() instead."); 757dd252788645e940eada959bdde927426e2531c9Paul Duffin } 767dd252788645e940eada959bdde927426e2531c9Paul Duffin 777dd252788645e940eada959bdde927426e2531c9Paul Duffin /** Not supported. Use {@link #putInstance} instead. */ 780888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public void putAll(Map<? extends TypeToken<? extends B>, ? extends B> map) { 797dd252788645e940eada959bdde927426e2531c9Paul Duffin throw new UnsupportedOperationException("Please use putInstance() instead."); 807dd252788645e940eada959bdde927426e2531c9Paul Duffin } 817dd252788645e940eada959bdde927426e2531c9Paul Duffin 820888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public Set<Entry<TypeToken<? extends B>, B>> entrySet() { 830888a09821a98ac0680fad765217302858e70fa4Paul Duffin return UnmodifiableEntry.transformEntries(super.entrySet()); 840888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 850888a09821a98ac0680fad765217302858e70fa4Paul Duffin 860888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override protected Map<TypeToken<? extends B>, B> delegate() { 877dd252788645e940eada959bdde927426e2531c9Paul Duffin return backingMap; 887dd252788645e940eada959bdde927426e2531c9Paul Duffin } 897dd252788645e940eada959bdde927426e2531c9Paul Duffin 900888a09821a98ac0680fad765217302858e70fa4Paul Duffin @SuppressWarnings("unchecked") // value could not get in if not a T 917dd252788645e940eada959bdde927426e2531c9Paul Duffin @Nullable 927dd252788645e940eada959bdde927426e2531c9Paul Duffin private <T extends B> T trustedPut(TypeToken<T> type, @Nullable T value) { 937dd252788645e940eada959bdde927426e2531c9Paul Duffin return (T) backingMap.put(type, value); 947dd252788645e940eada959bdde927426e2531c9Paul Duffin } 957dd252788645e940eada959bdde927426e2531c9Paul Duffin 960888a09821a98ac0680fad765217302858e70fa4Paul Duffin @SuppressWarnings("unchecked") // value could not get in if not a T 977dd252788645e940eada959bdde927426e2531c9Paul Duffin @Nullable 987dd252788645e940eada959bdde927426e2531c9Paul Duffin private <T extends B> T trustedGet(TypeToken<T> type) { 997dd252788645e940eada959bdde927426e2531c9Paul Duffin return (T) backingMap.get(type); 1007dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1010888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1020888a09821a98ac0680fad765217302858e70fa4Paul Duffin private static final class UnmodifiableEntry<K, V> extends ForwardingMapEntry<K, V> { 1030888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1040888a09821a98ac0680fad765217302858e70fa4Paul Duffin private final Entry<K, V> delegate; 1050888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1060888a09821a98ac0680fad765217302858e70fa4Paul Duffin static <K, V> Set<Entry<K, V>> transformEntries(final Set<Entry<K, V>> entries) { 1070888a09821a98ac0680fad765217302858e70fa4Paul Duffin return new ForwardingSet<Map.Entry<K, V>>() { 1080888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override protected Set<Entry<K, V>> delegate() { 1090888a09821a98ac0680fad765217302858e70fa4Paul Duffin return entries; 1100888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1110888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public Iterator<Entry<K, V>> iterator() { 1120888a09821a98ac0680fad765217302858e70fa4Paul Duffin return UnmodifiableEntry.transformEntries(super.iterator()); 1130888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1140888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public Object[] toArray() { 1150888a09821a98ac0680fad765217302858e70fa4Paul Duffin return standardToArray(); 1160888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1170888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public <T> T[] toArray(T[] array) { 1180888a09821a98ac0680fad765217302858e70fa4Paul Duffin return standardToArray(array); 1190888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1200888a09821a98ac0680fad765217302858e70fa4Paul Duffin }; 1210888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1220888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1230888a09821a98ac0680fad765217302858e70fa4Paul Duffin private static <K, V> Iterator<Entry<K, V>> transformEntries(Iterator<Entry<K, V>> entries) { 1240888a09821a98ac0680fad765217302858e70fa4Paul Duffin return Iterators.transform(entries, new Function<Entry<K, V>, Entry<K, V>>() { 1250888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public Entry<K, V> apply(Entry<K, V> entry) { 1260888a09821a98ac0680fad765217302858e70fa4Paul Duffin return new UnmodifiableEntry<K, V>(entry); 1270888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1280888a09821a98ac0680fad765217302858e70fa4Paul Duffin }); 1290888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1300888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1310888a09821a98ac0680fad765217302858e70fa4Paul Duffin private UnmodifiableEntry(java.util.Map.Entry<K, V> delegate) { 1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin this.delegate = checkNotNull(delegate); 1330888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1340888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1350888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override protected Entry<K, V> delegate() { 1360888a09821a98ac0680fad765217302858e70fa4Paul Duffin return delegate; 1370888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1380888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1390888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public V setValue(V value) { 1400888a09821a98ac0680fad765217302858e70fa4Paul Duffin throw new UnsupportedOperationException(); 1410888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1420888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1437dd252788645e940eada959bdde927426e2531c9Paul Duffin} 144