package org.apache.ibatis.executor.loader;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.apache.ibatis.reflection.MetaObject;

public class ResultLoaderMap {

  private final Map<String, LoadPair> loaderMap = new HashMap<String, LoadPair>();

  public void addLoader(String property, MetaObject metaResultObject, ResultLoader resultLoader) {
    String upperFirst = getUppercaseFirstProperty(property);
    loaderMap.put(upperFirst, new LoadPair(property, metaResultObject, resultLoader));
  }
  
  public Set<String> getPropertyNames() {
    return loaderMap.keySet();
  }

  public int size() {
    return loaderMap.size();
  }

  public boolean hasLoader(String property) {
    return loaderMap.containsKey(property.toUpperCase(Locale.ENGLISH));
  }
  
  public boolean load(String property) throws SQLException {
    LoadPair pair = loaderMap.remove(property.toUpperCase(Locale.ENGLISH));
    if (pair != null) {
      pair.load();
      return true;
    }
    return false;
  }

  public void loadAll() throws SQLException {
    final Set<String> methodNameSet = loaderMap.keySet();
    String[] methodNames = methodNameSet.toArray(new String[methodNameSet.size()]);
    for (String methodName : methodNames) {
      load(methodName);
    }
  }

  private static String getUppercaseFirstProperty(String property) {
    String[] parts = property.split("\\.");
    return parts[0].toUpperCase(Locale.ENGLISH);
  }

  private static class LoadPair {
    private String property;
    private MetaObject metaResultObject;
    private ResultLoader resultLoader;

    private LoadPair(String property, MetaObject metaResultObject, ResultLoader resultLoader) {
      this.property = property;
      this.metaResultObject = metaResultObject;
      this.resultLoader = resultLoader;
    }

    public void load() throws SQLException {
      metaResultObject.setValue(property, resultLoader.loadResult());
    }
  }
}

@@ -167,24 +167,78 @@
 til.Set;%0D%0A%0D%0A
+import org.apache.ibatis.executor.ExecutorException;%0D%0A
 import org.a
@@ -554,24 +554,423 @@
 property);%0D%0A
+    if (!upperFirst.equalsIgnoreCase(property) && loaderMap.containsKey(upperFirst)) %7B%0D%0A      throw new ExecutorException(%22Nested lazy loaded result property '%22 + property +%0D%0A              %22' for query id '%22 + resultLoader.mappedStatement.getId() +%0D%0A              %22 already exists in the result map. The leftmost property of all lazy loaded properties must be unique within a result map.%22);%0D%0A    %7D%0D%0A
     loaderMa

fix for http://code.google.com/p/mybatis/issues/detail?id=281 throw an exception if more than one lazy loaded result maps to the same property prefix