<commit_before>package de.jpaw.dp;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.jpaw.dp.exceptions.DuplicateStartupSortOrderException;
import de.jpaw.dp.exceptions.MissingOnStartupMethodException;
import de.jpaw.dp.exceptions.NoSuitableImplementationException;
import de.jpaw.dp.exceptions.NoSuitableProviderException;

/** JDP - jpaw dependency provider. */

// This dependency provider knows the following JSR 330 stuff:

// Scopes:
// @Singleton (@Eager or @Lazy, by default @Lazy)
// @Dependent
// @PerThread

// @Inject for class fields:
// will change the field to final and perform initialization at construction (before constructor code is run!)
// An active annotation will change the @Inject to = Jdp.get or Jdp.getProvider()

// FEATURE: Can inject objects of any type (Strings, Integers etc)
// FEATURE: Does not need proxy objects, therefore final can be used on classes and methods as usual
// FEATURE: works with new(), does not need getInstance()
// BUT: ATTENTION: This of course cannot work if you have cyclic injections! (But that would be bad application design anyway)

// @Specializes is supported (is default if an annotated class is extended)
// @Alternative
// NOT: @Qualifier
// @Default
// @Named => for Qualifier

// RESTRICTION: All objects for a given type must have the same scope!

public class Jdp {
    private static final Logger LOG = LoggerFactory.getLogger(Jdp.class);
    static private final Map<Class<?>, JdpTypeEntry<?>> typeIndex = new ConcurrentHashMap<Class<?>, JdpTypeEntry<?>>(1000);
    
    // typesafe access methods
    static private <X> JdpTypeEntry<X> getType(Class<X> type) {
        return (JdpTypeEntry<X>) typeIndex.get(type);
    }
    
    public static String dump(Class<?> type) {
        JdpTypeEntry<?> te = getType(type);
        if (te == null)
            return "No entry for type " + type.getSimpleName();
        else
            return "Registered entries for type "  + type.getSimpleName() + " are\n" + te.dump();
    }
    
    public static String dump() {
        StringBuilder b = new StringBuilder(2000);
        b.append("Full Jdp type dump:\n");
        for (Map.Entry<Class<?>, JdpTypeEntry<?>> e : typeIndex.entrySet()) {
            b.append("Registered entries for type "  + e.getKey().getSimpleName() + " are\n" + e.getValue().dump());
        }
        return b.toString();
    }
    
    /** returns an object of the requested type. Exception: if the type is an interface, an implementation of it is returned. */
    @Deprecated
    static public <T> T get(Class<T> type) {
        return getOptional(type, null);
    }
    static public <T> T getOptional(Class<T> type) {
        return getOptional(type, null);
    }
    static public <T> T get(Class<T> type, boolean isRequired) {
        return isRequired ? getRequired(type, null) : getOptional(type, null);
    }
    static public <T> T getRequired(Class<T> type) {
        return getRequired(type, null);
    }
    
    
    @Deprecated
    static public <T> T get(Class<T> type, String qualifier) {
        return getOptional(type, qualifier);
    }
    static public <T> T getOptional(Class<T> type, String qualifier) {
        Provider<? extends T> p = getProvider(type, qualifier);
        return p == null ? null : p.get();
    }
    static public <T> T getRequired(Class<T> type, String qualifier) {
        T result = getOptional(type, qualifier);
        if (result == null)
            throw new NoSuitableImplementationException(type, qualifier);
        return result;
    }
    static public <T> T get(Class<T> type, String qualifier, boolean isRequired) {
        return isRequired ? getRequired(type, qualifier) : getOptional(type, qualifier);
    }
    
    

    /** returns an object of the requested type. */
    static public <T> Provider<T> getProvider(Class<T> type) {
        return getProvider(type, null);
    }

    static public <T> Provider<T> getProvider(Class<T> type, String qualifier) {
        JdpTypeEntry<T> te = getType(type);
        JdpEntry<? extends T> firstEntry = te == null ? null : te.getFirstEntry(qualifier);	// JdpEntry<T> implements Provider<T>
        if (firstEntry == null) {
        	throw new NoSuitableProviderException(type, qualifier);
        }
        return (Provider<T>)firstEntry; 
    }

    /** Destructs all objects which have been created in this thread context. */
    static public void clearThreadContext() {

    }

    /** Get all valid matches. The primary match is returned as the first list element. */
    static public <T> List<T> getAll(Class<T> type) {
        return getAll(type, null);
    }

    /** Get all valid matches. The primary match is returned as the first list element. */
    static public <T> List<T> getAll(Class<T> type, String qualifier) {
        JdpTypeEntry<T> te = getType(type);<commit_msg>allow optional Provider call in JDP<commit_after>package de.jpaw.dp;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.jpaw.dp.exceptions.DuplicateStartupSortOrderException;
import de.jpaw.dp.exceptions.MissingOnStartupMethodException;
import de.jpaw.dp.exceptions.NoSuitableImplementationException;
import de.jpaw.dp.exceptions.NoSuitableProviderException;

/** JDP - jpaw dependency provider. */

// This dependency provider knows the following JSR 330 stuff:

// Scopes:
// @Singleton (@Eager or @Lazy, by default @Lazy)
// @Dependent
// @PerThread

// @Inject for class fields:
// will change the field to final and perform initialization at construction (before constructor code is run!)
// An active annotation will change the @Inject to = Jdp.get or Jdp.getProvider()

// FEATURE: Can inject objects of any type (Strings, Integers etc)
// FEATURE: Does not need proxy objects, therefore final can be used on classes and methods as usual
// FEATURE: works with new(), does not need getInstance()
// BUT: ATTENTION: This of course cannot work if you have cyclic injections! (But that would be bad application design anyway)

// @Specializes is supported (is default if an annotated class is extended)
// @Alternative
// NOT: @Qualifier
// @Default
// @Named => for Qualifier

// RESTRICTION: All objects for a given type must have the same scope!

public class Jdp {
    private static final Logger LOG = LoggerFactory.getLogger(Jdp.class);
    static private final Map<Class<?>, JdpTypeEntry<?>> typeIndex = new ConcurrentHashMap<Class<?>, JdpTypeEntry<?>>(1000);
    
    // typesafe access methods
    static private <X> JdpTypeEntry<X> getType(Class<X> type) {
        return (JdpTypeEntry<X>) typeIndex.get(type);
    }
    
    public static String dump(Class<?> type) {
        JdpTypeEntry<?> te = getType(type);
        if (te == null)
            return "No entry for type " + type.getSimpleName();
        else
            return "Registered entries for type "  + type.getSimpleName() + " are\n" + te.dump();
    }
    
    public static String dump() {
        StringBuilder b = new StringBuilder(2000);
        b.append("Full Jdp type dump:\n");
        for (Map.Entry<Class<?>, JdpTypeEntry<?>> e : typeIndex.entrySet()) {
            b.append("Registered entries for type "  + e.getKey().getSimpleName() + " are\n" + e.getValue().dump());
        }
        return b.toString();
    }
    
    /** returns an object of the requested type. Exception: if the type is an interface, an implementation of it is returned. */
    @Deprecated
    static public <T> T get(Class<T> type) {
        return getOptional(type, null);
    }
    static public <T> T getOptional(Class<T> type) {
        return getOptional(type, null);
    }
    static public <T> T get(Class<T> type, boolean isRequired) {
        return isRequired ? getRequired(type, null) : getOptional(type, null);
    }
    static public <T> T getRequired(Class<T> type) {
        return getRequired(type, null);
    }
    
    
    @Deprecated
    static public <T> T get(Class<T> type, String qualifier) {
        return getOptional(type, qualifier);
    }
    static public <T> T getOptional(Class<T> type, String qualifier) {
        Provider<? extends T> p = getOptionalProvider(type, qualifier);
        return p == null ? null : p.get();
    }
    static public <T> T getRequired(Class<T> type, String qualifier) {
        T result = getOptional(type, qualifier);
        if (result == null)
            throw new NoSuitableImplementationException(type, qualifier);
        return result;
    }
    static public <T> T get(Class<T> type, String qualifier, boolean isRequired) {
        return isRequired ? getRequired(type, qualifier) : getOptional(type, qualifier);
    }
    
    

    /** returns an object of the requested type. */
    static public <T> Provider<T> getProvider(Class<T> type) {
        return getProvider(type, null);
    }

    static public <T> Provider<T> getOptionalProvider(Class<T> type, String qualifier) {
        JdpTypeEntry<T> te = getType(type);
        JdpEntry<? extends T> firstEntry = te == null ? null : te.getFirstEntry(qualifier);	// JdpEntry<T> implements Provider<T>
        return (Provider<T>)firstEntry; 
    }

    static public <T> Provider<T> getProvider(Class<T> type, String qualifier) {
        Provider<T> firstEntry = getOptionalProvider(type, qualifier);
        if (firstEntry == null) {
        	throw new NoSuitableProviderException(type, qualifier);
        }
        return firstEntry; 
    }
    
    /** Destructs all objects which have been created in this thread context. */
    static public void clearThreadContext() {

    }

    /** Get all valid matches. The primary match is returned as the first list element. */
    static public <T> List<T> getAll(Class<T> type) {
        return getAll(type, null);
    }

    /** Get all valid matches. The primary match is returned as the first list element. */
    static public <T> List<T> getAll(Class<T> type, String qualifier) {
        JdpTypeEntry<T> te = getType(type);
{'fraction_non_alphanumeric': 0.1115932459201962, 'fraction_numerical': 0.002452598811432884, 'mean_word_length': 3.192170818505338, 'pattern_counts': {'":': 0, '<': 107, '<?xml version=': 0, '>': 109, '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': '4769492', 'n_tokens_mistral': 3143, 'n_tokens_neox': 3076, 'n_words': 1014}