<commit_before>package com.redhat.ceylon.common.tool;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import com.redhat.ceylon.common.OSUtil;
import com.redhat.ceylon.common.tool.OptionModel.ArgumentType;

/**
 * Responsible for locating a Class for a given tool name and constucting a 
 * {@link ToolModel} by reflection on that class. 
 * @author tom
 */
public abstract class ToolLoader {

    protected static final String SCRIPT_PREFIX = "SCRIPT:";

    protected final ClassLoader loader;

    private Map<String, ToolModel<? extends Tool>> toolModels = new HashMap<String, ToolModel<? extends Tool>>();
    
    public ToolLoader() {
        this(ToolLoader.class.getClassLoader());
    }
    
    public ToolLoader(ClassLoader loader) {
        this.loader = loader == null ? ClassLoader.getSystemClassLoader() : loader;
    }
    
    protected <T extends Tool> Class<T> loadToolClass(final String toolName) {
        String className = getToolClassName(toolName);
        if (className == null) {
            return null;
        }
        try {
            Class<T> toolClass = (Class<T>)loader.loadClass(className);
            return toolClass;
        } catch (ClassNotFoundException e) {
            return null;
        }
    }

    protected String getToolClassName(final String toolName) {
        List<String> classNames = new ArrayList<>();
        String className = null;
        for (String cls : toolClassNames()) {
            if (toolName.equals(getToolName(cls))) {
                classNames.add(cls);
            }
        }
        if (new HashSet<String>(classNames).size() > 1) {
            // TODO Allow fully qualified tool names to avoid ambiguities?
            throw new ToolException("Ambiguous tool name " + toolName + ", classes: " + classNames);
        }
        if (classNames.isEmpty()) {
            return null;
        }
        className = classNames.get(0);
        return className;
    }

    /**
     * Returns a ToolModel given the name of the tool, or null if no such tool is 
     * know to this tool loader.
     */
    public synchronized <T extends Tool> ToolModel<T> loadToolModel(String toolName) {
        @SuppressWarnings("unchecked")
        ToolModel<T> loadedModel = (ToolModel<T>) toolModels.get(toolName);
        if(loadedModel == null){
            loadedModel = loadToolModelMemoised(toolName);
            toolModels.put(toolName, loadedModel);
        }
        return loadedModel;
    }
    
    private <T extends Tool> ToolModel<T> loadToolModelMemoised(String toolName) {
        String className = getToolClassName(toolName);
        if(className != null && className.startsWith(SCRIPT_PREFIX)){
            return loadScriptTool(className, toolName);
        }else{
            Class<T> toolClass = loadToolClass(toolName);
            if (toolClass != null) {
                final ToolModel<T> toolModel;
                try {
                    toolModel = loadModel(toolClass, toolName);
                } catch (ModelException e) {
                    throw e;
                } catch (RuntimeException e) {
                    throw new ModelException("Failed to load model for tool " + toolName +"(" + toolClass + ")", e);
                }
                toolModel.setToolLoader(this);
                return toolModel;
            }
        }
        return null;
    }
    
    private <T extends Tool> ToolModel<T> loadScriptTool(String className, String toolName) {
        ToolModel<T> model = new ToolModel<T>();
        model.setScript(true);
        model.setScriptName(className.substring(7));
        model.setName(toolName);
        model.setToolLoader(this);
        return model;
    }

    private static URL[] makeClasspath(File... jars) {
        URL[] urls = new URL[jars.length];
        for (int ii = 0; ii <jars.length; ii++) {
            try {
                urls[ii] = jars[ii].toURI().toURL();
            } catch (MalformedURLException e) {
                throw new ToolException(e);
            }
        }
        return urls;
    }
    
    private <T extends Tool> ToolModel<T> loadModel(Class<T> cls, String toolName) {
        checkClass(cls);<commit_msg>ToolLoader: removed unused method<commit_after>package com.redhat.ceylon.common.tool;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import com.redhat.ceylon.common.OSUtil;
import com.redhat.ceylon.common.tool.OptionModel.ArgumentType;

/**
 * Responsible for locating a Class for a given tool name and constucting a 
 * {@link ToolModel} by reflection on that class. 
 * @author tom
 */
public abstract class ToolLoader {

    protected static final String SCRIPT_PREFIX = "SCRIPT:";

    protected final ClassLoader loader;

    private Map<String, ToolModel<? extends Tool>> toolModels = new HashMap<String, ToolModel<? extends Tool>>();
    
    public ToolLoader() {
        this(ToolLoader.class.getClassLoader());
    }
    
    public ToolLoader(ClassLoader loader) {
        this.loader = loader == null ? ClassLoader.getSystemClassLoader() : loader;
    }
    
    protected <T extends Tool> Class<T> loadToolClass(final String toolName) {
        String className = getToolClassName(toolName);
        if (className == null) {
            return null;
        }
        try {
            Class<T> toolClass = (Class<T>)loader.loadClass(className);
            return toolClass;
        } catch (ClassNotFoundException e) {
            return null;
        }
    }

    protected String getToolClassName(final String toolName) {
        List<String> classNames = new ArrayList<>();
        String className = null;
        for (String cls : toolClassNames()) {
            if (toolName.equals(getToolName(cls))) {
                classNames.add(cls);
            }
        }
        if (new HashSet<String>(classNames).size() > 1) {
            // TODO Allow fully qualified tool names to avoid ambiguities?
            throw new ToolException("Ambiguous tool name " + toolName + ", classes: " + classNames);
        }
        if (classNames.isEmpty()) {
            return null;
        }
        className = classNames.get(0);
        return className;
    }

    /**
     * Returns a ToolModel given the name of the tool, or null if no such tool is 
     * know to this tool loader.
     */
    public synchronized <T extends Tool> ToolModel<T> loadToolModel(String toolName) {
        @SuppressWarnings("unchecked")
        ToolModel<T> loadedModel = (ToolModel<T>) toolModels.get(toolName);
        if(loadedModel == null){
            loadedModel = loadToolModelMemoised(toolName);
            toolModels.put(toolName, loadedModel);
        }
        return loadedModel;
    }
    
    private <T extends Tool> ToolModel<T> loadToolModelMemoised(String toolName) {
        String className = getToolClassName(toolName);
        if(className != null && className.startsWith(SCRIPT_PREFIX)){
            return loadScriptTool(className, toolName);
        }else{
            Class<T> toolClass = loadToolClass(toolName);
            if (toolClass != null) {
                final ToolModel<T> toolModel;
                try {
                    toolModel = loadModel(toolClass, toolName);
                } catch (ModelException e) {
                    throw e;
                } catch (RuntimeException e) {
                    throw new ModelException("Failed to load model for tool " + toolName +"(" + toolClass + ")", e);
                }
                toolModel.setToolLoader(this);
                return toolModel;
            }
        }
        return null;
    }
    
    private <T extends Tool> ToolModel<T> loadScriptTool(String className, String toolName) {
        ToolModel<T> model = new ToolModel<T>();
        model.setScript(true);
        model.setScriptName(className.substring(7));
        model.setName(toolName);
        model.setToolLoader(this);
        return model;
    }

    private <T extends Tool> ToolModel<T> loadModel(Class<T> cls, String toolName) {
        checkClass(cls);
{'fraction_non_alphanumeric': 0.10250595305590203, 'fraction_numerical': 0.0007937407869372944, 'mean_word_length': 2.34597875569044, 'pattern_counts': {'":': 0, '<': 56, '<?xml version=': 0, '>': 57, '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': '5038122', 'n_tokens_mistral': 2420, 'n_tokens_neox': 2372, 'n_words': 617}