<commit_before>package org.carrot2.workbench.core.helpers;

import java.util.*;

import org.carrot2.core.ProcessingComponent;
import org.eclipse.core.runtime.*;

public class ComponentLoader
{
    private String extensionName;
    private String elementName;
    private String captionAttName;
    private String classAttName;
    private Map<String, ComponentWrapper> converterCache;

    public static final ComponentLoader SOURCE_LOADER = new ComponentLoader("source",
        "source", "label", "class");

    public static final ComponentLoader ALGORITHM_LOADER = new ComponentLoader(
        "algorithm", "algorithm", "label", "class");

    /**
     * All of parameters should be taken from schema files (*.exsd). Plugin name is
     * assumed to be <code>org.carrot2.core</code>, since this class is dedicated to
     * loading document sources and clustering algorithms, and those both extensions are
     * defined in <code>org.carrot2.core</code> plugin.
     * 
     * @param extensionName extension point ID (without plugin ID as a prefix)
     * @param elementName name of element, that stores info about component
     * @param captionName name of a attribute, that stores label/caption/etc. of a component
     * @param className name of a attribute, that stores name of a class of a component
     */
    private ComponentLoader(String extensionName, String elementName, String captionName,
        String className)
    {
        this.extensionName = extensionName;
        this.elementName = elementName;
        this.captionAttName = captionName;
        this.classAttName = className;
    }

    /**
     * Analyzes extension registry to find all extensions for point defined in
     * constructor. Plugins are not loaded inside this method! List of all components is
     * cached, so only first invocation actually reads the registry.
     * 
     * @return captions for all components of a given type
     * @see ComponentLoader#ComponentLoader(String, String, String, String)
     */
    public List<String> getCaptions()
    {
        loadExtensions();
        return new ArrayList<String>(converterCache.keySet());
    }

    /**
     * Creates instance of a given component. Plugin, in which component is defined, is
     * loaded while invoking this method! Use when necessary!
     * 
     * @param caption
     * @return instance of a component with the given caption.
     */
    public ProcessingComponent getComponent(String caption)
    {
        return converterCache.get(caption).getExecutableComponent();
    }

    /*
     * 
     */
    private void loadExtensions()
    {
        if (converterCache == null)
        {
            converterCache = new HashMap<String, ComponentWrapper>();
            IExtension [] extensions = Platform.getExtensionRegistry().getExtensionPoint(
                "org.carrot2.core", extensionName).getExtensions();
            for (int i = 0; i < extensions.length; i++)
            {
                IExtension extension = extensions[i];
                parseExtension(extension.getConfigurationElements());
            }
        }
    }

    /*
     * 
     */
    private void parseExtension(IConfigurationElement [] configurationElements)
    {
        for (int i = 0; i < configurationElements.length; i++)
        {
            IConfigurationElement configurationElement = configurationElements[i];
            if (!configurationElement.getName().equals(elementName))
            {
                return;
            }
            ComponentWrapper wrapper = new ComponentWrapper(configurationElement,
                captionAttName, classAttName);
            converterCache.put(wrapper.getCaption(), wrapper);
        }<commit_msg>React to non-existing components with a runtime exception (is there a better exception type for non-recoverable errors within Eclipse's UI?).<commit_after>package org.carrot2.workbench.core.helpers;

import java.util.*;

import org.carrot2.core.ProcessingComponent;
import org.eclipse.core.runtime.*;

import com.google.common.collect.Maps;

public class ComponentLoader
{
    private final String extensionName;
    private final String elementName;
    private final String captionAttName;
    private final String classAttName;

    private final Map<String, ComponentWrapper> converterCache = Maps.newHashMap();

    public static final ComponentLoader SOURCE_LOADER = new ComponentLoader("source",
        "source", "label", "class");

    public static final ComponentLoader ALGORITHM_LOADER = new ComponentLoader(
        "algorithm", "algorithm", "label", "class");

    /**
     * All of parameters should be taken from schema files (*.exsd). Plugin name is
     * assumed to be <code>org.carrot2.core</code>, since this class is dedicated to
     * loading document sources and clustering algorithms, and those both extensions are
     * defined in <code>org.carrot2.core</code> plugin.
     * 
     * @param extensionName extension point ID (without plugin ID as a prefix)
     * @param elementName name of element, that stores info about component
     * @param captionName name of a attribute, that stores label/caption/etc. of a
     *            component
     * @param className name of a attribute, that stores name of a class of a component
     */
    private ComponentLoader(String extensionName, String elementName, String captionName,
        String className)
    {
        this.extensionName = extensionName;
        this.elementName = elementName;
        this.captionAttName = captionName;
        this.classAttName = className;
    }

    /**
     * Analyzes extension registry to find all extensions for point defined in
     * constructor. Plugins are not loaded inside this method! List of all components is
     * cached, so only first invocation actually reads the registry.
     * 
     * @return captions for all components of a given type
     * @see ComponentLoader#ComponentLoader(String, String, String, String)
     */
    public List<String> getCaptions()
    {
        loadExtensions();
        return new ArrayList<String>(converterCache.keySet());
    }

    /**
     * Creates instance of a given component. Plugin, in which component is defined, is
     * loaded while invoking this method! Use when necessary!
     * 
     * @param caption
     * @return instance of a component with the given caption.
     */
    public ProcessingComponent getComponent(String caption)
    {
        if (!converterCache.containsKey(caption))
        {
            throw new RuntimeException("No such component: " + caption);
        }

        return converterCache.get(caption).getExecutableComponent();
    }

    /*
     * 
     */
    private void loadExtensions()
    {
        final IExtension [] extensions = Platform.getExtensionRegistry()
            .getExtensionPoint("org.carrot2.core", extensionName).getExtensions();
        for (IExtension extension : extensions)
        {
            parseExtension(extension.getConfigurationElements());
        }
    }

    /*
     * 
     */
    private void parseExtension(IConfigurationElement [] configurationElements)
    {
        for (int i = 0; i < configurationElements.length; i++)
        {
            IConfigurationElement configurationElement = configurationElements[i];
            if (!configurationElement.getName().equals(elementName))
            {
                return;
            }
            ComponentWrapper wrapper = new ComponentWrapper(configurationElement,
                captionAttName, classAttName);
            converterCache.put(wrapper.getCaption(), wrapper);
        }
{'fraction_non_alphanumeric': 0.0824891461649783, 'fraction_numerical': 0.0017103012761478752, 'mean_word_length': 2.731958762886598, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 18, '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': '5456875', 'n_tokens_mistral': 1880, 'n_tokens_neox': 1807, 'n_words': 611}