<commit_before>package io.datakernel.di.core;

import io.datakernel.di.impl.*;
import io.datakernel.di.util.Constructors.*;
import io.datakernel.di.util.LocationInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

import static io.datakernel.di.util.Utils.checkArgument;
import static io.datakernel.di.util.Utils.union;
import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toSet;

/**
 * A binding is one of the main components of DataKernel DI.
 * It boils down to "introspectable function", since it only describes
 * a {@link BindingCompiler function} to create an instance of T from an array of objects and
 * an array of its {@link Dependency dependencies} in known terms.
 * <p>
 * Also it contains a set of {@link io.datakernel.di.module.AbstractModule binding-DSL-like} static factory methods
 * as well as some functional transformations for the ease of creating immutable binding modifications.
 */
@SuppressWarnings({"unused", "WeakerAccess", "ArraysAsListWithZeroOrOneArgument"})
public final class Binding<T> {
	private final Set<Dependency> dependencies;
	private final BindingCompiler<T> compiler;

	@Nullable
	private LocationInfo location;

	public Binding(@NotNull Set<Dependency> dependencies, @NotNull BindingCompiler<T> compiler) {
		this(dependencies, null, compiler);
	}

	public Binding(@NotNull Set<Dependency> dependencies, @Nullable LocationInfo location, @NotNull BindingCompiler<T> compiler) {
		this.dependencies = dependencies;
		this.compiler = compiler;
		this.location = location;
	}

	public static <T> Binding<T> to(Class<? extends T> key) {
		return Binding.to(Key.of(key));
	}

	@SuppressWarnings("unchecked")
	public static <T> Binding<T> to(Key<? extends T> key) {
		return new Binding<>(new HashSet<>(asList(Dependency.toKey(key))),
				(compiledBindings, threadsafe, scope, index) -> (CompiledBinding<T>) compiledBindings.get(key));
	}

	public static <T> Binding<T> toInstance(@NotNull T instance) {
		return new Binding<>(emptySet(),
				(compiledBindings, threadsafe, scope, index) ->
						new CompiledBinding<T>() {
							@Override
							public T getInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) {
								//noinspection unchecked
								scopedInstances[scope].lazySet(index, instance);
								return instance;
							}

							@Override
							public T createInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) {
								return instance;
							}
						});<commit_msg>Make sure Binding.to(key) stores its instance in instances registry<commit_after>package io.datakernel.di.core;

import io.datakernel.di.impl.*;
import io.datakernel.di.util.Constructors.*;
import io.datakernel.di.util.LocationInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

import static io.datakernel.di.util.Utils.checkArgument;
import static io.datakernel.di.util.Utils.union;
import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toSet;

/**
 * A binding is one of the main components of DataKernel DI.
 * It boils down to "introspectable function", since it only describes
 * a {@link BindingCompiler function} to create an instance of T from an array of objects and
 * an array of its {@link Dependency dependencies} in known terms.
 * <p>
 * Also it contains a set of {@link io.datakernel.di.module.AbstractModule binding-DSL-like} static factory methods
 * as well as some functional transformations for the ease of creating immutable binding modifications.
 */
@SuppressWarnings({"unused", "WeakerAccess", "ArraysAsListWithZeroOrOneArgument"})
public final class Binding<T> {
	private final Set<Dependency> dependencies;
	private final BindingCompiler<T> compiler;

	@Nullable
	private LocationInfo location;

	public Binding(@NotNull Set<Dependency> dependencies, @NotNull BindingCompiler<T> compiler) {
		this(dependencies, null, compiler);
	}

	public Binding(@NotNull Set<Dependency> dependencies, @Nullable LocationInfo location, @NotNull BindingCompiler<T> compiler) {
		this.dependencies = dependencies;
		this.compiler = compiler;
		this.location = location;
	}

	public static <T> Binding<T> to(Class<? extends T> key) {
		return Binding.to(Key.of(key));
	}

	@SuppressWarnings("unchecked")
	public static <T> Binding<T> to(Key<? extends T> key) {
		return new Binding<>(new HashSet<>(asList(Dependency.toKey(key))),
				(compiledBindings, threadsafe, scope, index) ->
						new CompiledBinding<T>() {
							final CompiledBinding<T> compiledBinding = (CompiledBinding<T>) compiledBindings.get(key);

							@Override
							public T getInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) {
								T instance = compiledBinding.getInstance(scopedInstances, synchronizedScope);
								scopedInstances[scope].lazySet(index, instance);
								return instance;
							}

							@Override
							public T createInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) {
								return compiledBinding.createInstance(scopedInstances, synchronizedScope);
							}
						});
	}

	public static <T> Binding<T> toInstance(@NotNull T instance) {
		return new Binding<>(emptySet(),
				(compiledBindings, threadsafe, scope, index) ->
						new CompiledBinding<T>() {
							@Override
							public T getInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) {
								//noinspection unchecked
								scopedInstances[scope].lazySet(index, instance);
								return instance;
							}

							@Override
							public T createInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) {
								return instance;
							}
						});
{'fraction_non_alphanumeric': 0.10346945041449186, 'fraction_numerical': 0.0, 'mean_word_length': 4.704903677758319, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5625408', 'n_tokens_mistral': 2111, 'n_tokens_neox': 1819, 'n_words': 506}