001    /*
002     * Copyright (C) 2012 The Guava Authors
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package com.google.common.reflect;
018    
019    import com.google.common.annotations.Beta;
020    import com.google.common.collect.ForwardingMap;
021    import com.google.common.collect.Maps;
022    
023    import java.util.Map;
024    
025    import javax.annotation.Nullable;
026    
027    /**
028     * A mutable type-to-instance map.
029     * See also {@link ImmutableTypeToInstanceMap}.
030     *
031     * @author Ben Yu
032     * @since 13.0
033     */
034    @Beta
035    public final class MutableTypeToInstanceMap<B> extends ForwardingMap<TypeToken<? extends B>, B>
036        implements TypeToInstanceMap<B> {
037    
038      private final Map<TypeToken<? extends B>, B> backingMap = Maps.newHashMap();
039    
040      @Nullable
041      @Override
042      public <T extends B> T getInstance(Class<T> type) {
043        return trustedGet(TypeToken.of(type));
044      }
045    
046      @Nullable
047      @Override
048      public <T extends B> T putInstance(Class<T> type, @Nullable T value) {
049        return trustedPut(TypeToken.of(type), value);
050      }
051    
052      @Nullable
053      @Override
054      public <T extends B> T getInstance(TypeToken<T> type) {
055        return trustedGet(type.rejectTypeVariables());
056      }
057    
058      @Nullable
059      @Override
060      public <T extends B> T putInstance(TypeToken<T> type, @Nullable T value) {
061        return trustedPut(type.rejectTypeVariables(), value);
062      }
063    
064      /** Not supported. Use {@link #putInstance} instead. */
065      @Override public B put(TypeToken<? extends B> key, B value) {
066        throw new UnsupportedOperationException("Please use putInstance() instead.");
067      }
068    
069      /** Not supported. Use {@link #putInstance} instead. */
070      @Override public void putAll(Map<? extends TypeToken<? extends B>, ? extends B> map) {
071        throw new UnsupportedOperationException("Please use putInstance() instead.");
072      }
073    
074      @Override protected Map<TypeToken<? extends B>, B> delegate() {
075        return backingMap;
076      }
077    
078      @SuppressWarnings("unchecked") // value could not get in if not a T
079      @Nullable
080      private <T extends B> T trustedPut(TypeToken<T> type, @Nullable T value) {
081        return (T) backingMap.put(type, value);
082      }
083    
084      @SuppressWarnings("unchecked") // value could not get in if not a T
085      @Nullable
086      private <T extends B> T trustedGet(TypeToken<T> type) {
087        return (T) backingMap.get(type);
088      }
089    }