/*
* Grapht, an open source dependency injector.
* Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt)
* Copyright 2010-2014 Regents of the University of Minnesota
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.grouplens.grapht;
import org.grouplens.grapht.solver.BindRule;
import org.grouplens.grapht.reflect.Satisfaction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Provider;
import javax.inject.Qualifier;
import java.lang.annotation.Annotation;
/**
* Binding is part of the fluent API used for configuring an {@link Injector}.
* It represents a binding action from one type to another type.
*
* @author <a href="http://grouplens.org">GroupLens Research</a>
* @param <T> The source type
*/
public interface Binding<T> {
/**
* <p>
* Configure the binding to match the given {@link Qualifier} annotation.
* The given annotation type must be annotated with {@link Qualifier}. The
* created binding will match injection points only if the qualifier is
* applied to the injection point, unless the annotation inherits from the
* default qualifier.
* <p>
* This will override any previous name or qualifier annotation.
*
* @param qualifier The Qualifier that must match
* @return A newly configured Binding
*/
Binding<T> withQualifier(@Nonnull Class<? extends Annotation> qualifier);
/**
* Configure the binding to match injection points that have been annotated with the exact
* annotation instance.
*
* <p>This will override any previous name or qualifier annotation.
*
* <p>The annotation provided must be serializable. Annotations built by {@link
* org.grouplens.grapht.annotation.AnnotationBuilder} (recommended) or retrieved from the Java
* reflection API are serializable; if you use some other annotation implementation, it must be
* serializable.
*
* @param annot The annotation instance to match.
* @return A newly configured Binding
*/
Binding<T> withQualifier(@Nonnull Annotation annot);
/**
* Configure the binding to match injection points that have any qualifier annotation (including
* no qualifier).
*
* <p>This will override any previous name or qualifier annotation.
*
* @return A newly configured Binding
*/
Binding<T> withAnyQualifier();
/**
* <p>
* Configure the binding to only match injection points that have no
* qualifier. By default, the binding matches any injection point with the
* given type, whether or not its been qualified. A qualified binding to the
* same type will still be preferred first when resolving a qualified
* injection point.
*
* @return A newly configured binding
*/
Binding<T> unqualified();
/**
* Exclude the provided type from being matched when examining injection
* points. Bindings can generate multiple {@link BindRule BindRules} for
* super and sub types. Excluded classes for a binding will not have
* BindRules generated for them.
*
* @param exclude The type to exclude from automated rule generation
* @return A newly configured Binding
*/
Binding<T> exclude(@Nonnull Class<?> exclude);
/**
* Configure the binding so that a shared instance is always used when
* satisfying matched injection points, effectively making it a singleton or
* memoized within its container.
*
* @return A newly configured Binding
*/
Binding<T> shared();
/**
* Configure the binding so that new instances are always created when
* satisfying matched injection.
*
* @return A newly configured binding
*/
Binding<T> unshared();
/**
* Configure the binding so that its results are 'fixed'. Fixed results will not be rewritten
* by the dependency solver in rewrite mode.
* @return A newly configured binding.
*/
Binding<T> fixed();
/**
* <p>
* Complete this binding by specifying a subtype that will satisfy the
* desired type. The implementation does not have to be instantiable; if
* it's not then additional bindings must be configured to bind to reach an
* instantiable type. It is recommended for types to be instantiable.
* <p>
* The given type may have its own dependencies that will have to be
* satisfied by other bindings.
* <p>It is permissible to have two bindings forming a chain, like
* <code>A → B → C</code>. The {@code chained} parameter controls
* whether the chain is followed. If {@code chained == false} for the {@code A → B}
* binding, then the {@code B → C} binding is not followed (and the {@code A → B}
* binding is called <em>terminal</em>).
*
* @param impl The implementation type
* @param chained Whether further binding lookup will be done on the implementation type.
* {@code true} allows lookup, {@code false} creates a terminal binding.
*/
void to(@Nonnull Class<? extends T> impl, boolean chained);
/**
* Bind to an implementation type non-terminally. This calls {@link #to(Class, boolean)}
* as {@code this.to(impl, true)}.
*
* @param impl The implementation type.
*/
void to(@Nonnull Class<? extends T> impl);
/**
* Complete this binding by specifying an instance to use. The instance will
* be used to satisfy matched injection points. Because the instance never
* changes, any cache policy assigned by {@link #shared()} or
* {@link #unshared()} is effectively ignored.
*
* @param instance The instance to use. If {@code null}, binds explicitly to
* null.
*/
void to(@Nullable T instance);
/**
* Complete this binding by specifying a Provider class to be instantiated
* and used to create instances of type T. The Provider class may have its
* own dependencies that will be resolved by the injector.
*
* @param provider The provider type that will satisfy this binding
*/
void toProvider(@Nonnull Class<? extends Provider<? extends T>> provider);
/**
* Complete this binding by specifying a Provider instance that will be used
* to create instances of type T to satisfy this binding.
*
* @param provider The provider instance
*/
void toProvider(@Nonnull Provider<? extends T> provider);
/**
* Complete this binding by explicitly binding to {@code null}. The resulting
* bindings may not create an instantiable graph, as non-nullable injection points
* still require a non-null instance.
*/
void toNull();
/**
* Complete this binding by explicitly binding to {@code null} with a type.
* @param type The type of {@code null} to bind.
* @see #toNull()
*/
void toNull(Class<? extends T> type);
/**
* Bind this binding directly to a satisfaction.
*
* <p><strong>Note:</strong> this method is intended for use by applications that extend Grapht,
* or for bindings to other JVM languages. Most applications will have no use for this method,
* and developers consider if one of the other methods is more applicable for their situation.
* </p>
*
* <p>Bindings to satisfactions are always {@linkplain org.grouplens.grapht.solver.BindRule#isTerminal() terminal}.
* </p>
*
* @param sat The satisfaction to bind to.
*/
void toSatisfaction(@Nonnull Satisfaction sat);
}