/* * Copyright (C) 2014 The Dagger Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package dagger.internal; import static dagger.internal.DaggerCollections.newLinkedHashMapWithExpectedSize; import static dagger.internal.Preconditions.checkNotNull; import static java.util.Collections.unmodifiableMap; import java.util.LinkedHashMap; import java.util.Map; import javax.inject.Provider; /** * An {@code abstract} {@link Factory} implementation used to implement {@link Map} bindings. * * @param the key type of the map that this provides * @param the type that each contributing factory * @param the value type of the map that this provides */ abstract class AbstractMapFactory implements Factory> { private final Map> contributingMap; AbstractMapFactory(Map> map) { this.contributingMap = unmodifiableMap(map); } /** The map of {@link Provider}s that contribute to this map binding. */ final Map> contributingMap() { return contributingMap; } /** A builder for {@link AbstractMapFactory}. */ public abstract static class Builder { final LinkedHashMap> map; Builder(int size) { this.map = newLinkedHashMapWithExpectedSize(size); } // Unfortunately, we cannot return a self-type here because a raw Provider type passed to one of // these methods affects the returned type of the method. The first put*() call erases the self // type to the "raw" self type, and the second erases the type to the upper bound // (AbstractMapFactory.Builder), which doesn't have a build() method. // // The methods are therefore not declared public so that each subtype will redeclare them and // expand their accessibility /** Associates {@code key} with {@code providerOfValue}. */ Builder put(K key, Provider providerOfValue) { map.put(checkNotNull(key, "key"), checkNotNull(providerOfValue, "provider")); return this; } Builder putAll(Provider> mapOfProviders) { if (mapOfProviders instanceof DelegateFactory) { @SuppressWarnings("unchecked") DelegateFactory> asDelegateFactory = (DelegateFactory) mapOfProviders; return putAll(asDelegateFactory.getDelegate()); } @SuppressWarnings("unchecked") AbstractMapFactory asAbstractMapFactory = ((AbstractMapFactory) (Provider) mapOfProviders); map.putAll(asAbstractMapFactory.contributingMap); return this; } } }