/*
 * $Id: CollectionUtil.java,v 1.1 2016/07/23 01:54:21 wangqx Exp $
 */
package cn.com.liandisys.ycjt.ggcx.common.util;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import cn.com.liandisys.ycjt.ggcx.common.constant.CommonConstant;

/**
 * 集合常用操作辅助类
 */
@SuppressWarnings("unchecked")
public class CollectionUtil extends CollectionUtils {

    /**
     * 判断数组中是否存在该对象,比较时用object.equals()进行的
     * @param objects 对象数组
     * @param target 目标对象
     * @return 是否存在
     */
    public static boolean contanis(Object[] objects, Object target) {

        if (objects == null || target == null) {
            return false;
        }
        for (Object element : objects) {
            if (target.equals(element)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断集合中是否存在该对象,比较时用object.equals()进行的
     * @param list 对象集合
     * @param target 目标对象
     * @return 是否存在
     */
    public static boolean contanis(List<?> list, Object target) {

        if (list == null || target == null) {
            return false;
        }
        for (Object element : list) {
            if (target.equals(element)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断两个集合中的内容是否相等，顺序要严格相同
     * @param listA
     * @param listB
     */
    public static boolean hasSameElement(List<?> listA, List<?> listB) {

        if (listA == listB)
            return true;
        if (listA.size() != listB.size())
            return false;
        for (int i = 0; i < listA.size(); i++) {
            if (listA.get(i) == listB.get(i))
                continue;
            // 如果两者都不为空
            if (listA.get(i) != null && listB.get(i) != null) {
                if (!listA.get(i).equals(listB.get(i))) {
                    return false;
                }
            } else {// 其中一个为空，一个不为空
                return false;
            }
        }
        return true;
    }

    /**
     * 集合拷贝
     * @param sourceList 源
     * @return 目标
     */
    public static <T> List<T> copy(List<T> sourceList) {

        List<T> distList = new ArrayList<T>();
        for (int i = 0; i < sourceList.size(); i++) {
            distList.add(sourceList.get(i));
        }
        return distList;
    }

    /**
     * 判断两个集合时候有交集
     * @param fristList 被比较的第一个集合
     * @param secondList 被比较的第二个集合
     * @return 
     */
    public static boolean hasLeastOneElement(List<String> fristList, List<String> secondList) {

        //如果任意一个集合的为空或者元素个数为0则返回false
        if (fristList == null || fristList.size() == 0 || secondList == null || secondList.size() == 0) {
            return false;
        }
        //循环比较
        for (String element : fristList) {
            if (secondList.contains(element)) {
                return true;
            }
        }
        return false;
    }

    /** 提取集合中bean的属性，转化为Set */
    public static <T> Set<T> fetchBeanProp2Set(Collection<?> beans, String propName, Class<T> propCls)
            throws Exception {

        Set<T> tSet = new LinkedHashSet<T>();
        if (CollectionUtil.isEmpty(beans) || StringUtils.isEmpty(propName))
            return tSet;

        String mthName = "get" + Character.toUpperCase(propName.charAt(0)) + propName.substring(1);
        /* 转换为包装类 */
        if (propCls.isPrimitive())
            propCls = (Class<T>) CommonConstant.BASE_TYPE_WRAPPER_TYPE_MAP.get(propCls);
        Method getMth = beans.iterator().next().getClass().getMethod(mthName);

        for (Object bean : beans) {
            if (null != bean) {
                Object val = getMth.invoke(bean);
                if (val == null)
                    continue;
                Class<?> valCls = val.getClass();
                if (valCls.isPrimitive())
                    valCls = CommonConstant.BASE_TYPE_WRAPPER_TYPE_MAP.get(valCls); //转换为包装类

                if (!valCls.equals(propCls))
                    continue;
                if (!tSet.contains(val))
                    tSet.add((T) val);
            }
        }

        return tSet;
    }

    public static <T> Set<T> arrayToSet(T[] tArray) {

        return new LinkedHashSet<T>(Arrays.asList(tArray));
    }

    /** 提取集合中bean的属性，转化为List */
    public static <T> List<T> fetchBeanProp2List(Collection<?> beans, String propName, Class<T> propCls)
            throws Exception {

        List<T> tList = new ArrayList<T>();
        if (CollectionUtil.isEmpty(beans) || StringUtils.isEmpty(propName))
            return tList;

        String mthName = "get" + Character.toUpperCase(propName.charAt(0)) + propName.substring(1);
        /* 转换为包装类 */
        if (propCls.isPrimitive())
            propCls = (Class<T>) CommonConstant.BASE_TYPE_WRAPPER_TYPE_MAP.get(propCls);
        Method getMth = beans.iterator().next().getClass().getMethod(mthName);

        for (Object bean : beans) {
            if (null != bean) {
                Object val = getMth.invoke(bean);
                if (val == null)
                    continue;
                Class<?> valCls = val.getClass();
                if (valCls.isPrimitive())
                    valCls = CommonConstant.BASE_TYPE_WRAPPER_TYPE_MAP.get(valCls); //转换为包装类

                if (!valCls.equals(propCls))
                    continue;

                if (!tList.contains(val))
                    tList.add((T) val);
            }
        }

        return tList;
    }

    /** 转换beanList到Map，使用指定bean的prop作为key。 */
    public static <K, V> Map<K, V> toMap(List<V> beanList, String keyPropName, Class<K> keyPropCls) throws Exception {

        Map<K, V> map = new LinkedHashMap<K, V>();
        if (CollectionUtils.isEmpty(beanList) || StringUtils.isEmpty(keyPropName))
            return map;

        String mthName = "get" + Character.toUpperCase(keyPropName.charAt(0)) + keyPropName.substring(1);
        if (keyPropCls.isPrimitive())
            keyPropCls = (Class<K>) CommonConstant.BASE_TYPE_WRAPPER_TYPE_MAP.get(keyPropCls);
        Method getMth = beanList.get(0).getClass().getMethod(mthName);

        for (V v : beanList) {
            if (null != v) {
                Object val = getMth.invoke(v);
                if (val == null)
                    continue;
                Class<?> valCls = val.getClass();
                if (valCls.isPrimitive())
                    valCls = CommonConstant.BASE_TYPE_WRAPPER_TYPE_MAP.get(valCls); //转换为包装类

                if (!valCls.equals(keyPropCls))
                    continue;
                if (map.containsKey(val))
                    continue;
                map.put((K) val, v);
            }
        }

        return map;
    }

    /** 转换beanList到Map，使用指定bean的props分别作为key和value。 */
    public static <K, V> Map<K, V> toMap(List<?> beanList, String keyPropName, Class<K> keyPropCls,
            String valuePropName, Class<V> valuePropCls) throws Exception {

        Map<K, V> map = new LinkedHashMap<K, V>();
        if (CollectionUtils.isEmpty(beanList) || StringUtils.isEmpty(keyPropName))
            return map;

        String getKeyMthName = "get" + Character.toUpperCase(keyPropName.charAt(0)) + keyPropName.substring(1);
        if (keyPropCls.isPrimitive())
            keyPropCls = (Class<K>) CommonConstant.BASE_TYPE_WRAPPER_TYPE_MAP.get(keyPropCls);

        String getValueMthName = "get" + Character.toUpperCase(valuePropName.charAt(0)) + valuePropName.substring(1);
        if (valuePropCls.isPrimitive())
            valuePropCls = (Class<V>) CommonConstant.BASE_TYPE_WRAPPER_TYPE_MAP.get(valuePropCls);
        Method getKeyMth = beanList.get(0).getClass().getMethod(getKeyMthName);
        Method getValueMth = beanList.get(0).getClass().getMethod(getValueMthName);

        for (Object bean : beanList) {
            if (null != bean) {
                Object keyVal = getKeyMth.invoke(bean);
                if (keyVal == null)
                    continue;
                Class<?> keyValCls = keyVal.getClass();
                if (keyValCls.isPrimitive())
                    keyValCls = CommonConstant.BASE_TYPE_WRAPPER_TYPE_MAP.get(keyValCls); //转换为包装类

                if (!keyValCls.equals(keyPropCls))
                    continue;
                if (map.containsKey(keyVal))
                    continue;

                Object valueVal = getValueMth.invoke(bean);
                if (valueVal == null)
                    continue;
                Class<?> valueValCls = valueVal.getClass();
                if (valueValCls.isPrimitive())
                    valueValCls = CommonConstant.BASE_TYPE_WRAPPER_TYPE_MAP.get(valueValCls);
                if (!valueValCls.equals(valuePropCls))
                    continue;

                map.put((K) keyVal, (V) valueVal);
            }
        }

        return map;
    }

    /** 转换beanList到ListMap，使用指定bean的prop作为key。 */
    public static <K, V> Map<K, List<V>> toListMap(List<V> beanList, String keyPropName, Class<K> keyPropCls)
            throws Exception {

        Map<K, List<V>> map = new LinkedHashMap<K, List<V>>();
        if (CollectionUtils.isEmpty(beanList) || StringUtils.isEmpty(keyPropName))
            return map;

        String mthName = "get" + Character.toUpperCase(keyPropName.charAt(0)) + keyPropName.substring(1);
        if (keyPropCls.isPrimitive())
            keyPropCls = (Class<K>) CommonConstant.BASE_TYPE_WRAPPER_TYPE_MAP.get(keyPropCls);
        Method getMth = beanList.get(0).getClass().getMethod(mthName);

        for (V v : beanList) {
            if (null != v) {
                Object val = getMth.invoke(v);
                Class<?> valCls = val.getClass();
                if (valCls.isPrimitive())
                    valCls = CommonConstant.BASE_TYPE_WRAPPER_TYPE_MAP.get(valCls); //转换为包装类

                if (!valCls.equals(keyPropCls))
                    continue;
                if (!map.containsKey(val))
                    map.put((K) val, new ArrayList<V>());
                map.get(val).add(v);
            }
        }

        return map;
    }
}