/* * Copyright 2013 Google Inc. * * 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 com.google.gwt.inject.client.multibindings; import com.google.gwt.inject.client.binder.GinBinder; import com.google.gwt.inject.client.binder.GinConstantBindingBuilder; import com.google.gwt.inject.client.binder.GinLinkedBindingBuilder; import com.google.inject.Inject; import com.google.inject.Key; import com.google.inject.TypeLiteral; /** * A helper to register a binding of T to {@link RuntimeBindingsRegistry}. * <p> * {@code BindingRecorder} converts compile time multibinding information into runtime binding * information with the help of eager singletons and generics. */ class BindingRecorder { private final GinBinder binder; public <T> BindingRecorder(GinBinder binder, Key<T> multibindingKey) { BindingRegistererModule<T> module = new BindingRegistererModule<T>(multibindingKey); binder.install(module); this.binder = module.getBinder(); } public <T> GinLinkedBindingBuilder<T> bind(TypeLiteral<T> type) { return binder.bind(type).annotatedWith(Internal.class); } public <T> GinConstantBindingBuilder bindConstant() { return binder.bindConstant().annotatedWith(Internal.class); } /** * A module that configures BindingRegisterer in a way that type bound to 'T' in {@link #binder} * will be available at runtime via BindingRegistry<T>. */ // TODO(user): not private due to http://code.google.com/p/google-gin/issues/detail?id=184 static class BindingRegistererModule<T> extends InternalModule<T> { private GinBinder binder; public BindingRegistererModule(Key<T> multibindingKey) { super(multibindingKey); } @Override protected void configure() { this.binder = binder(); bindInternalBindingsRegistry(); bind(registererOf(multibindingType())).asEagerSingleton(); } public GinBinder getBinder() { return binder; } } static class BindingRegisterer<T> { @Inject public BindingRegisterer(@Internal RuntimeBindingsRegistry<T> registry, @Internal T binding) { registry.register(binding); } } private static TypeLiteral<?> registererOf(TypeLiteral<?> type) { return TypeLiterals.newParameterizedType(BindingRegisterer.class, type); } }