All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gitee.beiding.template_excel.ValueHandler Maven / Gradle / Ivy

Go to download

使用模板快速提取excel文件中的数据为数据实体,或者使用模板将数据实体渲染成excel

There is a newer version: 3.18.1-RELEASE
Show newest version
package com.gitee.beiding.template_excel;


import java.lang.reflect.*;
import java.util.*;


/*

    根据变量名称构建H对象,H对象维护数据的上下级关系

    例如
        a.list[i].d

        H(a)->H(list[i])->H(d)

    H对象在处理的过程中,会先给叶子节点赋值,然后从叶子

 */
class ValueHandler {

    private Map> entityMapping;

    //属性的setter方法
    private Map setterMap = new HashMap<>();


    void setEntityMapping(Map> entityMapping) {
        this.entityMapping = new HashMap<>();

        Set names = new HashSet<>();

        //首先将当前元素放入
        entityMapping.forEach((k, c) -> {
            String name = k.replaceAll("(?<=\\[)[^\\[\\]]*(?=])", "").replaceAll("[\n \t]*", "");
            this.entityMapping.put(name, c);
            names.add(name);
        });


        for (String name : names) {
            putAndHandleFiledType(name, this.entityMapping.get(name));
        }

    }


    //分析setter方法
    private void putAndHandleFiledType(String name, Class type) {

        Class c = this.entityMapping.get(name);

        //如果类型已经存在就使用已经存在的类型作为解析依据
        if (c == null) {
            this.entityMapping.put(name, type);
        } else {
            type = c;
        }


        Map map = settterMethodMap(type);

        //解析类中的所有变量
        for (Field field : fields(type)) {
            String fn = field.getName();

            //计算setter方法
            String setterMethodName = setterName(fn);

            try {


                Method method = map.get(setterMethodName);

                if (method != null) {

                    //如果是列表只能是List
                    if (field.getType() == List.class) {
                        Type genericType = field.getGenericType();

                        //判断是否是具有参数的
                        if (genericType instanceof ParameterizedType) {
                            Type[] types = ((ParameterizedType) genericType).getActualTypeArguments();
                            if (types.length == 1) {
                                Type t = types[0];
                                String typeName = t.getTypeName();
                                Class aClass = Class.forName(typeName);
                                String subN = name + "." + fn + "[]";

                                //放入setter方法
                                setterMap.put(subN, method);
                                putAndHandleFiledType(subN, aClass);
                            }
                        }

                    } else {
                        String subN = name + "." + fn;
                        setterMap.put(subN, method);
                        putAndHandleFiledType(subN, field.getType());
                    }
                }
            } catch (Exception ignore) {
            }
        }

    }


    private static Map settterMethodMap(Class clazz) {
        Map map = new HashMap<>();
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            if (method.getName().startsWith("set")) {
                map.put(method.getName(), method);
            }
        }
        return map;
    }

    private static String setterName(String s) {
        String setterMethodName = "set" + s.substring(0, 1).toUpperCase();
        if (s.length() > 1) {
            setterMethodName += s.substring(1);
        }
        return setterMethodName;
    }

    private static List fields(Class cls) {
        List list = new ArrayList<>();
        while (cls != null && cls != Object.class) {
            Field[] fields = cls.getDeclaredFields();
            list.addAll(Arrays.asList(fields));
            cls = cls.getSuperclass();
        }
        return list;
    }


    private static interface ValueHanle {
        Object hanle(String t);
    }

    public static Map hanleMap = new HashMap<>();

    static {
        hanleMap.put(Integer.class, text -> (Integer) Double.valueOf(text).intValue());
        hanleMap.put(int.class, text -> (Integer) Double.valueOf(text).intValue());
        hanleMap.put(Character.class, text -> (Character) Character.highSurrogate(Double.valueOf(text).intValue()));
        hanleMap.put(char.class, text -> (Character) Character.highSurrogate(Double.valueOf(text).intValue()));
        hanleMap.put(Long.class, text -> (Long) Double.valueOf(text).longValue());
        hanleMap.put(long.class, text -> (Long) Double.valueOf(text).longValue());
        hanleMap.put(Double.class, text -> Double.valueOf(text));
        hanleMap.put(double.class, text -> Double.valueOf(text));
        hanleMap.put(Float.class, text -> (Float) Double.valueOf(text).floatValue());
        hanleMap.put(float.class, text -> (Float) Double.valueOf(text).floatValue());
        hanleMap.put(Boolean.class, text -> Boolean.valueOf(text));
        hanleMap.put(boolean.class, text -> Boolean.valueOf(text));
        hanleMap.put(Short.class, text -> (Short) Double.valueOf(text).shortValue());
        hanleMap.put(short.class, text -> (Short) Double.valueOf(text).shortValue());

        //hanleMap.put(String.class, text -> text);

        hanleMap.put(Date.class, text -> {
            try {
                return Config.getDataFormat().parse(text);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        hanleMap.put(Calendar.class, text -> {
            try {
                Calendar instance = Calendar.getInstance();
                instance.setTime(Config.getDataFormat().parse(text));
                return instance;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    //需要将数据处理为一个map
    Map handle(Map> map) {


        //根节点
        Root root = new Root();

        List leafs = new ArrayList<>();

        map.forEach((k, v) -> {

            H l = root;

            String[] split = k.split("\\.");

            StringBuilder n = new StringBuilder();

            //找到最后一个节点
            for (String s : split) {
                l = l.getSub(s);
                n.append(s);
                l.mappingTypeExp = n.toString().replaceAll("(?<=\\[)[^\\[\\]]*(?=])", "");
                n.append(".");
            }


            l.valueHolders = v;

            Class aClass = entityMapping.get(l.mappingTypeExp);

            if (aClass != null) {

                ValueHanle hanle = hanleMap.get(aClass);
                if (hanle != null) {
                    v.forEach(d -> {
                        Object value = d.getValue();
                        if (value != null) {
                            String text = (String) value;
                            d.setValue(hanle.hanle(text));
                        }
                    });
                }
            }


            leafs.add(l);

        });

        //遍历所有叶子节点
        for (H leaf : leafs) {
            leaf.transmit();
        }

        return root.r;
    }

    private class Root extends H {

        private Map r = new HashMap<>();

        @Override
        void transmit() {
            for (H value : subs.values()) {
                int sum = 0;
                for (ValueHolder holder : value.valueHolders) {
                    sum += holder.getRow();
                }
                value.forward(r, sum);
            }
        }
    }

    private class H {

        private String name;

        private String setterMethodName;

        void setName(String name) {
            this.name = name;
            this.setterMethodName = setterName(name);
        }

        private String exp;

        //用于映射实体的表达式
        private String mappingTypeExp;

        //变化的自变量,如果存在表明是一个数组元素
        private String independent;

        //父级节点
        private H parent;

        //模板中变量数通常不多
        Map subs;

        //值占位符
        private List valueHolders;

        H getSub(String exp) {
            if (subs == null) {
                subs = new HashMap<>();
            }

            return subs.computeIfAbsent(exp, k -> {
                H h = new H();
                StringUtils.SubStringResult string = StringUtils.pairingSubString(exp, 0, '[', ']');
                if (string == null) {
                    h.setName(exp);
                    h.exp = exp;
                } else {
                    String name = exp.substring(0, string.getStart());
                    String ind = exp.substring(string.getStart() + 1, string.getEnd() - 1);
                    h.setName(name);

                    //TODO 将数组中的自变量擦除
                    h.exp = exp;
                    h.independent = ind;
                }
                h.parent = H.this;
                return h;
            });
        }

        //下一轮的开始索引位置
        private int index = 0;

        private List findValue(int span) {
            int i;
            List r = new ArrayList<>();
            int sum = 0;
            for (i = index; i < valueHolders.size(); i++) {
                ValueHolder holder = valueHolders.get(i);
                r.add(holder.getValue());
                sum += holder.getRow();
                if (sum == span) {
                    i++;
                    break;
                } else if (sum > span) {
                    //TODO sum只能小于span或者等于
                    throw new RuntimeException("数组元素无法对齐");
                }
            }
            index = i;
            return r;
        }

        private Set subExps;

        //接受后继节点反向调用
        void back(H sub) {
            if (subExps == null) {
                subExps = new HashSet<>(subs.keySet());
            }
            subExps.remove(sub.exp);
            //如果处理完成
            if (subExps.size() == 0) {
                transmit();
            }

        }


        //分析得到对齐
        private List handleAlignArray() {


            Map rowSpanMap = new HashMap<>();

            boolean hasNotArray = false;

            boolean hasArray = false;

            int allRow = 0;

            Set arrayAllRowSet = new HashSet<>();

            for (H value : subs.values()) {
                //如果不是数组元素
                if (value.independent == null) {
                    hasNotArray = true;
                    for (int i = 0; i < value.valueHolders.size(); i++) {
                        Integer integer = rowSpanMap.get(i);
                        if (integer == null) {
                            int row = value.valueHolders.get(i).getRow();
                            rowSpanMap.put(i, row);
                            allRow += row;
                        } else {
                            if (value.valueHolders.get(i).getRow() != integer) {
                                throw new RuntimeException("数据无法对齐");
                            }
                        }
                    }
                } else {
                    hasArray = true;
                    int all = 0;
                    for (ValueHolder holder : value.valueHolders) {
                        all += holder.getRow();
                    }
                    arrayAllRowSet.add(all);
                }
            }

            if (hasNotArray) {
                if (hasArray) {
                    for (Integer integer : arrayAllRowSet) {
                        if (integer != allRow) {
                            throw new RuntimeException("数据无法对齐");
                        }
                    }
                }

                List integers = new ArrayList<>();

                rowSpanMap.forEach((k,v)->{
                    integers.add(k, v);
                });

                return integers;
            } else {

                if (hasArray) {
                    if (arrayAllRowSet.size() > 1) {
                        throw new RuntimeException("数据无法对齐");
                    } else {
                        if (arrayAllRowSet.size() == 0) {
                            return Collections.emptyList();
                        } else {
                            for (Integer integer : arrayAllRowSet) {
                                return Collections.singletonList(integer);
                            }
                        }
                    }
                } else {
                    return Collections.emptyList();
                }

            }

            throw new RuntimeException("不可预料的位置");

        }


        //整合所有直接子节点,创建自己的节点
        private void handleValueHolder() {//这里的判断是不正确的

            List list = handleAlignArray();

            valueHolders = new LinkedList<>();

            Class aClass = entityMapping.get(mappingTypeExp);

            if (aClass == null) {
                for (Integer row : list) {
                    valueHolders.add(new ValueHolder(new HashMap(), row));
                }

            } else {
                for (Integer row : list) {
                    try {
                        Object o = aClass.newInstance();
                        valueHolders.add(new ValueHolder(o, row));
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }

/*
            //放入所有子元素
            Map sumRowMap = new HashMap<>();
            Map indexMap = new HashMap<>();

            for (H h : subs.values()) {
                sumRowMap.put(h, 0);
                indexMap.put(h, 0);
            }


            while (true) {

                int maxSum = 0;

                //该元素占用的单元格长度
                int row = 0;

                boolean flag = false;

                //找一个索引
                for (H h : subs.values()) {

                    //找到它对应的索引
                    Integer index = indexMap.get(h);

                    //获取跨越的行数
                    ValueHolder holder = h.valueHolders.get(index);

                    int nextIndex = index + 1;

                    //更新该位置的索引
                    indexMap.put(h, nextIndex);

                    //当前累加的总行数
                    int currentSum = sumRowMap.get(h) + holder.getRow();
                    sumRowMap.put(h, currentSum);

                    if (currentSum > maxSum) {
                        maxSum = currentSum;
                        row = holder.getRow();

                        //表明已经到达某个元素的终点,可以结束了
                        if (nextIndex == h.valueHolders.size()) {
                            flag = true;
                        }
                    }


                }


                for (H h : subs.values()) {
                    Integer sum = sumRowMap.get(h);
                    if (sum < maxSum) {

                        int i = indexMap.get(h);
                        for (; true; i++) {
                            if (i >= h.valueHolders.size()) {
                                throw new RuntimeException("无法对齐元素");
                            }
                            ValueHolder holder = h.valueHolders.get(i);
                            sum += holder.getRow();
                            if (sum == maxSum) {
                                i++;
                                sumRowMap.put(h, maxSum);
                                break;
                            }
                        }
                        indexMap.put(h, i);

                    }
                }


                if (valueHolders == null) {
                    valueHolders = new LinkedList<>();
                }


                //TODO 判断是否具有实体映射,如果有实体映射就放入创建一个实体映射,否则放入一个HashMap

                Class aClass = entityMapping.get(mappingTypeExp);
                if (aClass == null) {
                    valueHolders.add(new ValueHolder(new HashMap(), row));
                } else {
                    try {
                        Object o = aClass.newInstance();
                        valueHolders.add(new ValueHolder(o, row));
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }


                //判断是否已经处理到最后了

                if (flag) {

                    //遍历一遍判断所有数据是否全部对齐
                    for (H value : subs.values()) {
                        Integer index = indexMap.get(value);
                        if (index != value.valueHolders.size()) {
                            throw new RuntimeException("数据无法对齐");
                        }
                    }

                    break;
                }

            }*/
        }


        //触发传递
        void transmit() {
            if (subs != null) {
                handleValueHolder();
                //告知自己的正向节点中数组元素,进行必要的合并
                for (ValueHolder holder : valueHolders) {
                    for (H value : subs.values()) {
                        value.forward(holder.getValue(), holder.getRow());
                    }
                }
            }

            if (parent != null) {
                parent.back(this);
            }

        }

        void forward(Object f, int row) {

            if (independent == null) {

                List list = findValue(row);

                if (list.size() != 1) {
                    System.err.println("从给定的行数找到的元素数量不满足数量唯一:" + list.size());
                }

                if (f instanceof Map) {
                    Map map = (Map) f;
                    map.put(name, list.get(0));

                } else {
                    try {
                        Object o = list.get(0);

                        Method m = setterMap.get(mappingTypeExp);
                        if (m == null) {
                            throw new RuntimeException("未找到setter方法:" + mappingTypeExp);
                        }

                        //Method method = f.getClass().getMethod(setterMethodName, o.getClass());
                        m.invoke(f, o);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }

            } else {
                List list = findValue(row);
                if (f instanceof Map) {
                    Map map = (Map) f;
                    map.put(name, list);

                } else {
                    try {
                        /*Method method = f.getClass().getMethod(setterMethodName, List.class);
                        method.invoke(f, list);

                        */
                        Method m = setterMap.get(mappingTypeExp);
                        if (m == null) {
                            throw new RuntimeException("未找到setter方法:" + mappingTypeExp);
                        }
                        m.invoke(f, list);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }

        }


    }

}