content: package com.alibaba.tamper.process.convertor;
  
  import java.lang.reflect.Array;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.LinkedHashMap;
  import java.util.LinkedHashSet;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  import java.util.TreeMap;
  import java.util.TreeSet;
  import java.util.Vector;
  
  import org.apache.commons.lang.StringUtils;
  
  import com.alibaba.tamper.BeanCopy;
  import com.alibaba.tamper.BeanMap;
  import com.alibaba.tamper.BeanMapping;
  import com.alibaba.tamper.core.BeanMappingException;
  import com.alibaba.tamper.core.config.BeanMappingConfigHelper;
  import com.alibaba.tamper.core.config.BeanMappingField;
  import com.alibaba.tamper.core.config.BeanMappingObject;
  import com.alibaba.tamper.core.helper.ReflectionHelper;
  
  /**
   * Collection <-> Collection 的转化器 , Collection范围包括Array(几种原型数组),List,Set各种实现类
   * 
   * @author jianghang 2011-5-26 上午09:23:00
   */
  public class CollectionAndCollectionConvertor {
  
      public static abstract class BaseCollectionConvertor extends AbastactConvertor implements CollectionConvertor {
  
          @Override
          public Object convert(Object src, Class destClass) {
              return convertCollection(src, destClass, getComponentClass(src, destClass));
          }
  
          public Object convertCollection(Object src, Class destClass, Class... componentClasses) {
              return convertCollection(null, src, destClass, componentClasses);
          }
  
          protected abstract Class getComponentClass(Object src, Class destClass);
  
          protected MappingConfig initMapping(BeanMappingField context, Class srcClass, Class targetClass,
                                              Class[] componentClasses) {
              MappingConfig config = new MappingConfig();
              // 1. mapping配置中的映射
              // 2. 尝试处理下BeanCopy和BeanMap配置
              // 先找一次转化,可能是原始类型
              // 多级数组映射暂不考虑，TMD太复杂了，需要客户端自定义转化器
              config.convertor = ConvertorHelper.getInstance().getConvertor(srcClass, targetClass);
              if (config.convertor != null) {
                  if (componentClasses != null && componentClasses.length > 1) {// 处理嵌套的componentClass传递
                      Class[] newComponentClasses = new Class[componentClasses.length - 1];
                      config.componentClasses = newComponentClasses;
                      System.arraycopy(componentClasses, 1, newComponentClasses, 0, componentClasses.length - 1);// 拷贝n-1的长度
                  }
              } else {
                  try {
  
                      if (context != null) {// 如果存在上下文，说明是mapping内部递归调用
                          BeanMappingObject object = context.getNestObject();
                          if (object == null) {
                              String nestname = context.getNestName();
                              if (StringUtils.isNotEmpty(nestname)) {
                                  object = BeanMappingConfigHelper.getInstance().getBeanMappingObject(nestname);
                                  config.beanMapping = new BeanMapping(object);
                              } else {
                                  config.beanMapping = BeanMapping.create(srcClass, targetClass);
                              }
                          } else {
                              config.beanMapping = new BeanMapping(object);
                          }
                      } else {
                          config.beanMapping = BeanMapping.create(srcClass, targetClass);
                      }
                  } catch (BeanMappingException e) {
                      // 处理下分支2
                      boolean isSrcMap = Map.class.isAssignableFrom(srcClass);
                      boolean isTargetMap = Map.class.isAssignableFrom(targetClass);
                      if (isSrcMap && isTargetMap) { // 如果都为Map对象
                          config.isMap = true;
                      } else if (isSrcMap) {
                          config.beanMap = BeanMap.create(targetClass);
                          config.populate = true;
                      } else if (isTargetMap) {
                          config.beanMap = BeanMap.create(srcClass);
                          config.populate = false;
                      } else {
                          config.beanCopy = BeanCopy.create(srcClass, targetClass); // 默认进行类型转化
                      }
  
                  }
              }
              return config;
          }
  
          protected Object doMapping(Object src, Class targetClass, MappingConfig config) {
              Object newObj = null;
              if (config.convertor != null) {
                  if (config.componentClasses != null && config.convertor instanceof CollectionConvertor) {
                      newObj = ((CollectionConvertor) config.convertor).convertCollection(null, src, targetClass,
                                                                                          config.componentClasses); // 处理递归嵌套
                  } else {
                      newObj = config.convertor.convert(src, targetClass);
                  }
  
              } else {
                  if (config.isMap) {
                      newObj = createMap(targetClass);
                      ((Map) newObj).putAll((Map) src);
                  } else {
                      newObj = ReflectionHelper.newInstance(targetClass);
                      if (config.beanMapping != null) {
                          config.beanMapping.mapping(src, newObj);
                      } else if (config.beanCopy != null) {
                          config.beanCopy.copy(src, newObj);
                      } else if (config.beanMap != null) {
                          if (config.populate) {
                              config.beanMap.populate(newObj, (Map) src);
                          } else {
                              newObj = config.beanMap.describe(src);
                          }
                      }
                  }
              }
  
              return newObj;
          }
  
          protected Map createMap(Class destClass) {
              if (destClass == Map.class || destClass == HashMap.class) {
                  return new HashMap();
              }
  
              if (destClass == TreeMap.class) {
                  return new TreeMap();
              }
  
              if (destClass == LinkedHashMap.class) {
                  return new LinkedHashMap();
              }
  
              throw new BeanMappingException("Unsupported Map: [" + destClass.getName() + "]");
  
          }
  
          protected Collection createCollection(Class destClass) {
              if (destClass == List.class || destClass == ArrayList.class) {
                  return new ArrayList(); // list默认为ArrayList
              }
  
              if (destClass == LinkedList.class) {
                  return new LinkedList();
              }
  
              if (destClass == Vector.class) {
                  return new Vector();
              }
  
              if (destClass == Set.class || destClass == HashSet.class) {
                  return new HashSet(); // set默认为HashSet
              }
  
              if (destClass == LinkedHashSet.class) {
                  return new LinkedHashSet();
              }
  
              if (destClass == TreeSet.class) {
                  return new TreeSet();
              }
  
              throw new BeanMappingException("Unsupported Collection: [" + destClass.getName() + "]");
          }
  
          protected void arraySet(Object src, Class compoentType, int i, Object value) {
              Array.set(src, i, value);
          }
  
          protected Object arrayGet(Object src, Class compoentType, int i) {
              return Array.get(src, i);
          }
      }
  
      /**
       * Collection -> Collection 转化
       */
      public static class CollectionToCollection extends BaseCollectionConvertor {
  
          public Object convertCollection(BeanMappingField context, Object src, Class destClass,
                                          Class... componentClasses) {
              if (Collection.class.isAssignableFrom(src.getClass()) && Collection.class.isAssignableFrom(destClass)) { // 必须都是Collection
                  Collection collection = (Collection) src;
                  Collection target = createCollection(destClass);
  
                  boolean isInit = false;
                  MappingConfig config = null;
  
                  Class componentClass = null;
                  if (componentClasses != null && componentClasses.length >= 1) {
                      componentClass = componentClasses[0];
                  }
  
                  boolean isForceMapping = false; // 如果不存在上线文，默认不做强制类型转化
                  if (context != null) {
                      isForceMapping = (StringUtils.isNotEmpty(context.getNestName()) || context.getNestObject() != null);// 如果存在定义映射规则，则强制进行映射处理
                  }
  
                  for (Iterator iter = collection.iterator(); iter.hasNext();) {
                      Object item = iter.next();
                      Class componentSrcClass = item.getClass();
  
                      if (isForceMapping || componentClass != null && componentSrcClass != componentClass) {
                          if (isInit == false) {
                              isInit = true;
                              config = initMapping(context, componentSrcClass, componentClass, componentClasses);
                          }
  
                          // 添加为mapping convertor
                          target.add(doMapping(item, componentClass, config));
                      } else {
                          target.add(item);
                      }
                  }
                  return target;
              }
  
              throw new BeanMappingException("Unsupported convert: [" + src + "," + destClass.getName() + "]");
          }
  
          @Override
          protected Class getComponentClass(Object src, Class destClass) {
              if (Collection.class.isAssignableFrom(src.getClass()) && Collection.class.isAssignableFrom(destClass)) { // 必须都是Collection
                  Collection collection = (Collection) src;
                  for (Iterator iter = collection.iterator(); iter.hasNext();) {
                      Object item = iter.next();
                      if (item != null) {
                          return item.getClass();
                      }
                  }
              }
  
              return null;
          }
      }
  
      /**
       * array -> array 转化
       */
      public static class ArrayToArray extends BaseCollectionConvertor {
  
          public Object convertCollection(BeanMappingField context, Object src, Class destClass,
                                          Class... componentClasses) {
              if (src.getClass().isArray() && destClass.isArray()) { // 特殊处理下数组
                  int size = Array.getLength(src);
                  Class componentSrcClass = src.getClass().getComponentType();
                  Class componentDestClass = destClass.getComponentType();
                  MappingConfig config = null;
                  Object[] objs = (Object[]) Array.newInstance(componentDestClass, size);
  
                  Class componentClass = null;
                  if (componentClasses != null && componentClasses.length >= 1) {
                      componentClass = componentClasses[0];
                  }
  
                  if (componentDestClass != componentClass) {
                      throw new BeanMappingException("error ComponentClasses config for [" + componentDestClass.getName()
                                                     + "] to [" + componentDestClass.getName() + "]");
                  }
                  boolean isForceMapping = false; // 如果不存在上线文，默认不做强制类型转化
                  if (context != null) {
                      isForceMapping = (StringUtils.isNotEmpty(context.getNestName()) || context.getNestObject() != null);// 如果存在定义映射规则，则强制进行映射处理
                  }
  
                  if (isForceMapping || componentClass != null && componentSrcClass != componentClass) { // 需要进行类型转化
                      config = initMapping(context, componentSrcClass, componentDestClass, componentClasses);
                  }
                  for (int i = 0; i < size; i++) {
                      Object obj = arrayGet(src, componentSrcClass, i);
                      if (config != null) { // 需要进行类型转化
                          Object newObj = doMapping(obj, componentDestClass, config);
                          arraySet(objs, componentDestClass, i, newObj);
                      } else {
                          arraySet(objs, componentDestClass, i, obj);
                      }
                  }
                  return objs;
              }
  
              throw new BeanMappingException("Unsupported convert: [" + src + "," + destClass.getName() + "]");
          }
  
          @Override
          protected Class getComponentClass(Object src, Class destClass) {
              if (src.getClass().isArray() && destClass.isArray()) { // 特殊处理下数组
                  return src.getClass().getComponentType();
              }
              return null;
          }
      }
  
      /**
       * array -> Collection 转化
       */
      public static class ArrayToCollection extends BaseCollectionConvertor {
  
          public Object convertCollection(BeanMappingField context, Object src, Class destClass,
                                          Class... componentClasses) {
              if (src.getClass().isArray() && Collection.class.isAssignableFrom(destClass)) { // 特殊处理下数组
                  Collection target = createCollection(destClass);
                  int size = Array.getLength(src);
                  Class componentSrcClass = src.getClass().getComponentType();
  
                  MappingConfig config = null;
                  Class componentClass = null;
                  if (componentClasses != null && componentClasses.length >= 1) {
                      componentClass = componentClasses[0];
                  }
  
                  boolean isForceMapping = false; // 如果不存在上线文，默认不做强制类型转化
                  if (context != null) {
                      isForceMapping = (StringUtils.isNotEmpty(context.getNestName()) || context.getNestObject() != null);// 如果存在定义映射规则，则强制进行映射处理
                  }
  
                  if (isForceMapping || componentClass != null && componentSrcClass != componentClass) { // 处理下类型转化
                      config = initMapping(context, componentSrcClass, componentClass, componentClasses);
                  }
  
                  for (int i = 0; i < size; i++) {
                      Object obj = arrayGet(src, componentSrcClass, i);
                      if (config != null) { // 需要进行类型转化
                          Object newObj = doMapping(obj, componentClass, config);
                          target.add(newObj);
                      } else {
                          target.add(obj);
                      }
                  }
                  return target;
              }
  
              throw new BeanMappingException("Unsupported convert: [" + src + "," + destClass.getName() + "]");
          }
  
          @Override
          protected Class getComponentClass(Object src, Class destClass) {
              if (src.getClass().isArray() && Collection.class.isAssignableFrom(destClass)) { // 特殊处理下数组
                  return src.getClass().getComponentType();
              }
  
              return null;
          }
  
      }
  
      /**
       * Collection -> array 转化
       */
      public static class CollectionToArray extends BaseCollectionConvertor {
  
          public Object convertCollection(BeanMappingField context, Object src, Class destClass,
                                          Class... componentClasses) {
              if (Collection.class.isAssignableFrom(src.getClass()) && destClass.isArray()) {
                  Collection collection = (Collection) src;
                  Class componentDestClass = destClass.getComponentType();
                  Object objs = Array.newInstance(componentDestClass, collection.size());
  
                  boolean isInit = false;
                  MappingConfig config = null;
                  Class componentClass = null;
                  if (componentClasses != null && componentClasses.length >= 1) {
                      componentClass = componentClasses[0];
                  }
  
                  if (componentDestClass != componentClass) {
                      throw new BeanMappingException("error ComponentClasses config for [" + componentDestClass.getName()
                                                     + "] to [" + componentDestClass.getName() + "]");
                  }
  
                  boolean isForceMapping = false; // 如果不存在上线文，默认不做强制类型转化
                  if (context != null) {
                      isForceMapping = (StringUtils.isNotEmpty(context.getNestName()) || context.getNestObject() != null);// 如果存在定义映射规则，则强制进行映射处理
                  }
  
                  int i = 0;
                  for (Iterator iter = collection.iterator(); iter.hasNext();) {
                      Object item = iter.next();
                      Class componentSrcClass = item.getClass();
                      if (isForceMapping || componentClass != null && componentSrcClass != componentDestClass) {
                          if (isInit == false) {
                              config = initMapping(context, componentSrcClass, componentDestClass, componentClasses);
                          }
  
                          Object newObj = doMapping(item, componentDestClass, config);
                          arraySet(objs, componentDestClass, i, newObj);
                      } else {
                          arraySet(objs, componentDestClass, i, item);
                      }
                      i = i + 1;
                  }
                  return objs;
  
              }
  
              throw new BeanMappingException("Unsupported convert: [" + src + "," + destClass.getName() + "]");
          }
  
          @Override
          protected Class getComponentClass(Object src, Class destClass) {
              if (Collection.class.isAssignableFrom(src.getClass()) && destClass.isArray()) {
                  return destClass.getComponentType();// 以目标地址为准
              }
  
              return null;
          }
      }
  
  }
  
  class MappingConfig {
  
      Convertor   convertor        = null;
      BeanMapping beanMapping      = null;
      BeanCopy    beanCopy         = null;
      BeanMap     beanMap          = null;
      boolean     populate         = false;
      boolean     isMap            = false;
      Class[]     componentClasses = null;
  
  }
  