package com.github.zhongl.hs4j.kit.arguments;

import java.lang.reflect.*;

import com.github.zhongl.hs4j.kit.annotations.*;
import com.github.zhongl.hs4j.kit.annotations.HandlerSocket.Action;

/**
 * {@link StaticCollectorFactory}
 * 
 * @author <a href=mailto:zhong.lunfu@gmail.com>zhongl</a>
 * @created 2011-6-3
 * 
 */
public class StaticCollectorFactory {
  private static final int ENTITY_INDEX = 0;
  private static final int PRIMARY_INDEX = 0;

  public static Collector<String[]> createKeysCollectorBy(ParameterAnnotations locator) {
    final Method method = locator.getMethod();
    final EntityClass entityClass = method.getAnnotation(EntityClass.class);
    if (entityClass != null) { // to find parameter type is entity class.
      assertNotBothEntityClassAndOperatorAreAnnotatedBy(locator);
      assertParameterTypeJustOnlyBeEntityClassOn(method);
      return new EntityKeysCollector(ENTITY_INDEX, PRIMARY_INDEX);
    }
    return new KeysCollector(locator.getOnlyOneParamterIndexAnnotatedBy(Operator.class));
  }

  private static void assertNotBothEntityClassAndOperatorAreAnnotatedBy(ParameterAnnotations locator) {
    if (!locator.getAnnotationsOf(Operator.class).isEmpty())
      throw new IllegalArgumentException("Either " + EntityClass.class + " or " + Operator.class + " can be annotated");
  }

  public static Collector<Integer> createLimitCollectorBy(ParameterAnnotations locator) {
    return new LimitCollector(locator.getOnlyOneMoreParamterIndexAnnotatedBy(Limit.class));
  }

  public static Collector<Integer> createOffsetCollectorBy(ParameterAnnotations locator) {
    return new OffsetCollector(locator.getOnlyOneMoreParamterIndexAnnotatedBy(Offset.class));
  }

  public static Collector<String[]> createValuesCollectorFrom(ParameterAnnotations locator) {
    final Method method = locator.getMethod();
    final EntityClass entityClass = method.getAnnotation(EntityClass.class);
    if (entityClass != null) { // to find parameter type is entity class.
      assertParameterTypeJustOnlyBeEntityClassOn(method);
      final boolean excludePrimary = method.getAnnotation(HandlerSocket.class).value() != Action.INSERT;
      return new EntityValuesCollector(ENTITY_INDEX, PRIMARY_INDEX, excludePrimary);
    }
    return new ArgumentsValuesCollector(locator.getAnnotationlessParameterIndexs());
  }

  private static void assertParameterTypeJustOnlyBeEntityClassOn(final Method method) {
    final Class<?>[] parameterTypes = method.getParameterTypes();
    Class<?> entityClass = method.getAnnotation(EntityClass.class).value();
    if (parameterTypes.length != 1 || !parameterTypes[0].equals(entityClass))
      throw new IllegalArgumentException("Paramter Types should only be " + entityClass);
  }

  private StaticCollectorFactory() {}

}

@@ -518,39 +518,43 @@
 eterAnnotations 
-locator
+annotations
 ) %7B%0A    final Me
@@ -559,39 +559,43 @@
 Method method = 
-locator
+annotations
 .getMethod();%0A  
@@ -799,23 +799,27 @@
 tatedBy(
-locator
+annotations
 );%0A     
@@ -965,39 +965,43 @@
 w KeysCollector(
-locator
+annotations
 .getOnlyOneParam
@@ -1128,39 +1128,43 @@
 eterAnnotations 
-locator
+annotations
 ) %7B%0A    if (!loc
@@ -1160,23 +1160,27 @@
    if (!
-locator
+annotations
 .getAnno
@@ -1413,39 +1413,43 @@
 eterAnnotations 
-locator
+annotations
 ) %7B%0A    return n
@@ -1458,39 +1458,43 @@
  LimitCollector(
-locator
+annotations
 .getOnlyOneMoreP
@@ -1609,39 +1609,43 @@
 eterAnnotations 
-locator
+annotations
 ) %7B%0A    return n
@@ -1659,31 +1659,35 @@
 etCollector(
-locator
+annotations
 .getOnlyOneM
@@ -1818,23 +1818,27 @@
 tations 
-locator
+annotations
 ) %7B%0A    
@@ -1859,23 +1859,27 @@
 ethod = 
-locator
+annotations
 .getMeth
@@ -2333,15 +2333,19 @@
 tor(
-locator
+annotations
 .get

clean code.