<commit_before>/**
 * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.servlet.ServletContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.Lifecycle;
import org.springframework.web.context.ServletContextAware;

import com.opengamma.util.ArgumentChecker;

/**
 * A repository for OpenGamma components.
 * <p>
 * The OpenGamma logical architecture consists of a set of components.
 * This repository manages the components.
 * <p>
 * This class uses concurrent collections, but instances are intended to be created
 * from a single thread at startup.
 */
public class ComponentRepository implements Lifecycle, ServletContextAware {

  /**
   * The key used to refer to repository in the servlet context.
   */
  public static final String SERVLET_CONTEXT_KEY = ComponentRepository.class.getName();
  /** Logger. */
  private static final Logger s_logger = LoggerFactory.getLogger(ComponentRepository.class);
  /**
   * The thread-local instance.
   */
  private static final ThreadLocal<ComponentRepository> s_threadRepo = new InheritableThreadLocal<ComponentRepository>();

  /**
   * The map of info by type.
   */
  private final ConcurrentMap<Class<?>, ComponentTypeInfo> _infoMap = new ConcurrentHashMap<Class<?>, ComponentTypeInfo>();
  /**
   * The repository of component instances.
   */
  private final ConcurrentMap<ComponentKey, Object> _instanceMap = new ConcurrentHashMap<ComponentKey, Object>();
  /**
   * The repository of RESTful published components.
   */
  private final RestComponents _restPublished = new RestComponents();
  /**
   * The objects with {@code Lifecycle}.
   */
  private final List<Lifecycle> _lifecycles = new ArrayList<Lifecycle>();
  /**
   * The objects with {@code ServletContextAware}.
   */
  private final List<ServletContextAware> _servletContextAware = new ArrayList<ServletContextAware>();
  /**
   * The status.
   */
  private volatile Status _status = Status.CREATING;

  /**
   * Creates an instance.
   */
  public ComponentRepository() {
  }

  //-------------------------------------------------------------------------
  /**
   * Gets all the instances.
   * <p>
   * This method will return infrastructure instances.
   * 
   * @return the instance map, not null
   */
  public Map<ComponentKey, Object> getInstanceMap() {
    return new HashMap<ComponentKey, Object>(_instanceMap);
  }

  /**
   * Gets an instance of a component.
   * <p>
   * This finds an instance that matches the specified type.
   * This may be used to find both component and infrastructure instances.
   * 
   * @param <T>  the type
   * @param type  the type to get, not null
   * @param classifier  the classifier that distinguishes the component, empty for default, not null
   * @return the component instance, not null
   * @throws IllegalArgumentException if no component is available
   */
  public <T> T getInstance(Class<T> type, String classifier) {
    ArgumentChecker.notNull(type, "type");
    ComponentKey key = ComponentKey.of(type, classifier);
    Object result = _instanceMap.get(key);
    if (result == null) {
      throw new IllegalArgumentException("No component available: " + key);
    }
    return type.cast(result);
  }

  //-------------------------------------------------------------------------
  /**
   * Gets all the type information for the component.
   * <p>
   * This method will not return infrastructure instances.
   * 
   * @return the component type information, not null
   * @throws IllegalArgumentException if no component is available
   */
  public Collection<ComponentTypeInfo> getTypeInfo() {
    return new ArrayList<ComponentTypeInfo>(_infoMap.values());
  }

  /**
   * Gets the type information for the component.
   * <p>
   * This method will not find infrastructure instances.
   * 
   * @param type  the type to get, not null
   * @return the component type information, not null
   * @throws IllegalArgumentException if no component is available
   */
  public ComponentTypeInfo getTypeInfo(Class<?> type) {
    ComponentTypeInfo typeInfo = _infoMap.get(type);
    if (typeInfo == null) {
      throw new IllegalArgumentException("Unknown component: " + type);
    }
    return typeInfo;
  }

  //-------------------------------------------------------------------------
  /**
   * Gets the component information.
   * <p>
   * This method will not find infrastructure instances.
   * 
   * @param type  the type to get, not null
   * @param classifier  the classifier that distinguishes the component, empty for default, not null
   * @return the component information, not null
   * @throws IllegalArgumentException if no component is available
   */
  public ComponentInfo getInfo(Class<?> type, String classifier) {
    ArgumentChecker.notNull(type, "type");
    ComponentTypeInfo typeInfo = getTypeInfo(type);
    return typeInfo.getInfo(classifier);
  }

  /**
   * Gets the component information for an instance.
   * <p>
   * This method will not find infrastructure instances.
   * 
   * @param instance  the instance to find info for, not null
   * @return the component information, not null
   * @throws IllegalArgumentException if no component is available
   */
  public ComponentInfo getInfo(Object instance) {
    for (Entry<ComponentKey, Object> entry : _instanceMap.entrySet()) {
      if (entry.getValue() == instance) {
        return getInfo(entry.getKey().getType(), entry.getKey().getClassifier());
      }
    }
    throw new IllegalArgumentException("Unknown component instance: " + instance);
  }

  //-------------------------------------------------------------------------
  /**
   * Gets the RESTful components.<commit_msg>[PLAT-1658] Enhance ability to lookup components<commit_after>/**
 * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.servlet.ServletContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.Lifecycle;
import org.springframework.web.context.ServletContextAware;

import com.opengamma.util.ArgumentChecker;

/**
 * A repository for OpenGamma components.
 * <p>
 * The OpenGamma logical architecture consists of a set of components.
 * This repository manages the components.
 * <p>
 * This class uses concurrent collections, but instances are intended to be created
 * from a single thread at startup.
 */
public class ComponentRepository implements Lifecycle, ServletContextAware {

  /**
   * The key used to refer to repository in the servlet context.
   */
  public static final String SERVLET_CONTEXT_KEY = ComponentRepository.class.getName();
  /** Logger. */
  private static final Logger s_logger = LoggerFactory.getLogger(ComponentRepository.class);
  /**
   * The thread-local instance.
   */
  private static final ThreadLocal<ComponentRepository> s_threadRepo = new InheritableThreadLocal<ComponentRepository>();

  /**
   * The map of info by type.
   */
  private final ConcurrentMap<Class<?>, ComponentTypeInfo> _infoMap = new ConcurrentHashMap<Class<?>, ComponentTypeInfo>();
  /**
   * The repository of component instances.
   */
  private final ConcurrentMap<ComponentKey, Object> _instanceMap = new ConcurrentHashMap<ComponentKey, Object>();
  /**
   * The repository of RESTful published components.
   */
  private final RestComponents _restPublished = new RestComponents();
  /**
   * The objects with {@code Lifecycle}.
   */
  private final List<Lifecycle> _lifecycles = new ArrayList<Lifecycle>();
  /**
   * The objects with {@code ServletContextAware}.
   */
  private final List<ServletContextAware> _servletContextAware = new ArrayList<ServletContextAware>();
  /**
   * The status.
   */
  private volatile Status _status = Status.CREATING;

  /**
   * Creates an instance.
   */
  public ComponentRepository() {
  }

  //-------------------------------------------------------------------------
  /**
   * Gets all the instances.
   * <p>
   * This method will return infrastructure instances.
   * 
   * @return the instance map, not null
   */
  public Map<ComponentKey, Object> getInstanceMap() {
    return new HashMap<ComponentKey, Object>(_instanceMap);
  }

  /**
   * Gets an instance of a component.
   * <p>
   * This finds an instance that matches the specified type.
   * This may be used to find both component and infrastructure instances.
   * 
   * @param <T>  the type
   * @param type  the type to get, not null
   * @param classifier  the classifier that distinguishes the component, empty for default, not null
   * @return the component instance, not null
   * @throws IllegalArgumentException if no component is available
   */
  public <T> T getInstance(Class<T> type, String classifier) {
    ArgumentChecker.notNull(type, "type");
    ComponentKey key = ComponentKey.of(type, classifier);
    Object result = _instanceMap.get(key);
    if (result == null) {
      throw new IllegalArgumentException("No component available: " + key);
    }
    return type.cast(result);
  }

  //-------------------------------------------------------------------------
  /**
   * Gets all the type information for the component.
   * <p>
   * This method will not return infrastructure instances.
   * 
   * @return the component type information, not null
   * @throws IllegalArgumentException if no component is available
   */
  public Collection<ComponentTypeInfo> getTypeInfo() {
    return new ArrayList<ComponentTypeInfo>(_infoMap.values());
  }

  /**
   * Gets the type information for the component.
   * <p>
   * This method will not find infrastructure instances.
   * 
   * @param type  the type to get, not null
   * @return the component type information, not null
   * @throws IllegalArgumentException if no component is available
   */
  public ComponentTypeInfo getTypeInfo(Class<?> type) {
    ComponentTypeInfo typeInfo = _infoMap.get(type);
    if (typeInfo == null) {
      throw new IllegalArgumentException("Unknown component: " + type);
    }
    return typeInfo;
  }

  //-------------------------------------------------------------------------
  /**
   * Gets the component information.
   * <p>
   * This method will not find infrastructure instances.
   * 
   * @param type  the type to get, not null
   * @param classifier  the classifier that distinguishes the component, not null
   * @return the component information, not null
   * @throws IllegalArgumentException if no component is available
   */
  public ComponentInfo getInfo(Class<?> type, String classifier) {
    ArgumentChecker.notNull(type, "type");
    ComponentTypeInfo typeInfo = getTypeInfo(type);
    return typeInfo.getInfo(classifier);
  }

  /**
   * Gets the component information for an instance.
   * <p>
   * This method will not find infrastructure instances.
   * 
   * @param instance  the instance to find info for, not null
   * @return the component information, not null
   * @throws IllegalArgumentException if no component is available
   */
  public ComponentInfo getInfo(Object instance) {
    for (Entry<ComponentKey, Object> entry : _instanceMap.entrySet()) {
      if (entry.getValue() == instance) {
        return getInfo(entry.getKey().getType(), entry.getKey().getClassifier());
      }
    }
    throw new IllegalArgumentException("Unknown component instance: " + instance);
  }

  //-------------------------------------------------------------------------
  /**
   * Finds the type information for the component.
   * <p>
   * This method is lenient, ignoring case and matching simple type names.
   * This method will not find infrastructure instances.
   * 
   * @param typeName  the name of the type to get, case insensitive, not null
   * @return the component type information, null if not found
   */
  public ComponentTypeInfo findTypeInfo(String typeName) {
    ArgumentChecker.notNull(typeName, "type");
    for (Class<?> realType : _infoMap.keySet()) {
      if (realType.getName().equalsIgnoreCase(typeName) || realType.getSimpleName().equalsIgnoreCase(typeName)) {
        return getTypeInfo(realType);
      }
    }
    return null;
  }

  /**
   * Finds the component information.
   * <p>
   * This method is lenient, ignoring case and matching simple type names.
   * This method will not find infrastructure instances.
   * 
   * @param typeName  the simple name of the type to get, case insensitive, not null
   * @param classifier  the classifier that distinguishes the component, case insensitive, not null
   * @return the component information, null if not found
   */
  public ComponentInfo findInfo(String typeName, String classifier) {
    ArgumentChecker.notNull(typeName, "type");
    ComponentTypeInfo typeInfo = findTypeInfo(typeName);
    if (typeInfo != null) {
      for (String realClassifier : typeInfo.getInfoMap().keySet()) {
        if (realClassifier.equalsIgnoreCase(classifier)) {
          return typeInfo.getInfo(realClassifier);
        }
      }
    }
    return null;
  }

  //-------------------------------------------------------------------------
  /**
   * Gets the RESTful components.
{'fraction_non_alphanumeric': 0.13807106598984772, 'fraction_numerical': 0.001160261058738216, 'mean_word_length': 2.903481460515143, 'pattern_counts': {'":': 0, '<': 66, '<?xml version=': 0, '>': 66, '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': '4154896', 'n_tokens_mistral': 3542, 'n_tokens_neox': 3508, 'n_words': 1209}