/**
 * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */

package com.opengamma.language.invoke;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * An aggregation of other {@link TypeConverterProvider} instances.
 */
public final class AggregatingTypeConverterProvider implements TypeConverterProvider {

  /**
   * The list of converters, in the order added, set to null when the converters are fetched for the first
   * time (after which the aggregator cannot be modified).
   */
  private List<TypeConverterProvider> _typeConverterProviders = new LinkedList<TypeConverterProvider>();
  private volatile List<TypeConverter> _typeConverters;

  public AggregatingTypeConverterProvider() {
  }

  public synchronized void addTypeConverterProvider(final TypeConverterProvider typeConverterProvider) {
    if (_typeConverterProviders == null) {
      throw new IllegalStateException();
    }
    _typeConverterProviders.add(typeConverterProvider);
  }

  @Override
  public List<TypeConverter> getTypeConverters() {
    if (_typeConverters == null) {
      synchronized (this) {
        final Map<String, TypeConverter> typeConverters = new LinkedHashMap<String, TypeConverter>();
        for (TypeConverterProvider typeConverterProvider : _typeConverterProviders) {
          for (TypeConverter typeConverter : typeConverterProvider.getTypeConverters()) {
            typeConverters.remove(typeConverter.getTypeConverterKey());
            typeConverters.put(typeConverter.getTypeConverterKey(), typeConverter);
          }
        }
        _typeConverterProviders = null;
        _typeConverters = Collections.unmodifiableList(new ArrayList<TypeConverter>(typeConverters.values()));
      }
    }
    return _typeConverters;
  }

}

@@ -1270,24 +1270,65 @@
 ed (this) %7B%0A
+        if (_typeConverters == null) %7B%0A  
         fina
@@ -1413,24 +1413,26 @@
 nverter%3E();%0A
+  
         for 
@@ -1507,32 +1507,34 @@
 rs) %7B%0A          
+  
 for (TypeConvert
@@ -1593,24 +1593,26 @@
 erters()) %7B%0A
+  
             
@@ -1675,32 +1675,34 @@
 ));%0A            
+  
 typeConverters.p
@@ -1757,16 +1757,18 @@
 erter);%0A
+  
         
@@ -1771,34 +1771,38 @@
       %7D%0A        
-%7D%0A
+  %7D%0A  
         _typeCon
@@ -1825,16 +1825,18 @@
 = null;%0A
+  
         
@@ -1934,24 +1934,34 @@
 values()));%0A
+        %7D%0A
       %7D%0A    

Correct AggregatingTypeConverterProvider when initialising itself concurrently.