package com.cf.imes.module.executor.util.fileConversion.admin.files.xml;

import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.shaded.com.google.common.base.Function;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
import com.cf.imes.module.executor.dal.dataobject.plate.PlateGoodDO;
import com.cf.imes.module.executor.dal.mysql.plate.PlateGoodMapper;
import com.cf.imes.module.executor.enums.DataTypeEnum;
import com.cf.imes.module.executor.enums.DictTypeConstants;
import com.cf.imes.module.executor.enums.OrderTypeEnum;
import com.cf.imes.module.executor.util.fileConversion.admin.ToolUtil;
import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.*;
import com.cf.imes.module.system.api.dict.DictDataApi;
import com.cf.imes.module.system.api.dict.dto.DictDataRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Supplier;

import static com.cf.imes.module.infra.enums.ErrorCodeConstants.FILE_OUTPUT_ERROR;

@Slf4j
@Component
public class XMLUtil {

    final String TYPE_ERR = "---< %s数据类型有误 >---";
    final String POSITIVE_ERR = "---< %s数据需为正数 >---";
    final String LONG_ERR = "---< %s数据长度不符合（共8位整数位5位，小数位3位） >---";
    final String IS_NULL = "---< %s不能为空 >---";
    final String INVALID = "---< %s数据无效 >---";

    final String NOT_ASSIGNED = "未命名";
    final String NOT_ASSIGNED_CODE = "未命编号";


    final String ROOM_CODE = "roomCode";
    final String BODY_CODE = "boxCode";
    final String MODULE_CODE = "moduleCode";
    final String GROUP_CODE = "groupCode";
    final String PLATE_NOT_EXIST = "板材不存在，请先录入板材，在进行订单导入";

    @Resource
    private DictDataApi dictDataApi;

    @Resource
    private PlateGoodMapper plateGoodMapper;

    public static Object read(MultipartFile file, Class<?> clazz) throws IOException {


        byte[] firstThreeBytes = new byte[3];

        // 用字符缓冲流获取XML文件内容

        InputStream inputStream = file.getInputStream();
        inputStream.read(firstThreeBytes, 0, 3);
//        if (firstThreeBytes[0] == (byte) 0xEF && firstThreeBytes[1] == (byte) 0xBB && firstThreeBytes[2] == (byte) 0xBF) {
//            // 跳过 BOM
//            inputStream.skip(3);
//        }
        try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            StringBuffer builder = new StringBuffer();
            String line;
            while ((line = br.readLine()) != null) {
                builder.append(line);
            }

            // XML转为JAVA对象

            return XmlBuilder.xmlStrToOject(clazz, builder.toString());
        } catch (IOException e) {
            log.error("Error reading the file: " + file.getOriginalFilename(), e);
        } catch (Exception e) {
            log.error("Error parsing the XML to an OrderXmlVO object", e);
        }

        return null;
    }

    public static void writeErr(HttpServletResponse response, String xmlStr, String name) {
        // 设置响应头
        response.setContentType("application/xml; charset=UTF-8");
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name, StandardCharsets.UTF_8));

        // 获取输出流
        try (Writer writer = new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8)) {

            // 输出 XML 数据
            writer.write(xmlStr);
            writer.flush();
        } catch (IOException e) {
            throw new ServiceException(FILE_OUTPUT_ERROR, name);
        }
    }

    private void setIfInvalid(Supplier<String> getter, Function<String, String> errorMessageFactory, Consumer<String> setter, boolean error) {
        String phone = getter.get();
        if (phone != null && !ToolUtil.validatePhoneNumber(phone)) {
            setter.accept(errorMessageFactory.apply(phone));
            error = false;
        }
    }
    private boolean validatePhoneNumbers(OrderXmlVO orderXmlVO) {
        boolean error = true;
        if (orderXmlVO.getCustomer() == null) {
            orderXmlVO.setCustomer("---< 客户名不能为空 >---");
            error = false;
        }
        setIfInvalid(orderXmlVO::getCustomerPhone, s -> "---< " + s + "客户电话格式错误 >---", orderXmlVO::setCustomerPhone, error);
        setIfInvalid(orderXmlVO::getDealerPhone, s -> "---< " + s + "经销商电话格式错误 >---", orderXmlVO::setDealerPhone, error);
        setIfInvalid(orderXmlVO::getSellerPhone, s -> "---< " + s + "业务员电话格式错误 >---", orderXmlVO::setSellerPhone, error);
        setIfInvalid(orderXmlVO::getDesignerPhone, s -> "---< " + s + "设计师电话格式错误 >---", orderXmlVO::setDesignerPhone, error);
        setIfInvalid(orderXmlVO::getAnalystPhone, s -> "---< " + s + "解单员电话格式错误 >---", orderXmlVO::setAnalystPhone, error);
        return error;
    }

    // 订单数据格式验证
    public XmlCheckVO changeDate(OrderXmlVO orderXmlVO, Long organId) {
        boolean error = validatePhoneNumbers(orderXmlVO);

        LocalDate orderDate = null;
        LocalDate deliverDate = null;
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        Map<String, Object> mapDate = ToolUtil.changeDate(orderXmlVO.getOrderDate(), formatter);
        Integer errorCode = (Integer) mapDate.get("error");
        if (orderXmlVO.getOrderDate() == null) {
            orderDate = LocalDate.now();
        } else {
            if (errorCode == -1) {
                orderXmlVO.setOrderDate("---< " + orderXmlVO.getOrderDate() + "订单日期格式错误 >---");
                error = false;
            } else {
                orderDate = (LocalDate) mapDate.get("date");
            }
        }
        mapDate = ToolUtil.changeDate(orderXmlVO.getDeliveryDate(), formatter);
        if (orderXmlVO.getDeliveryDate() == null) {
            deliverDate = orderDate.plus(30, ChronoUnit.DAYS);
        } else {
            if (errorCode == -1) {
                orderXmlVO.setDeliveryDate("---< " + orderXmlVO.getDeliveryDate() + "出货日期格式错误 >---");
                error = false;
            } else {
                deliverDate = (LocalDate) mapDate.get("date");
                if (orderDate != null && deliverDate.isBefore(orderDate)) {
                    deliverDate = orderDate.plus(30, ChronoUnit.DAYS);
                }
            }
        }
        OrderDO orderDO = new OrderDO();
        if (error) {
            assert orderDate != null;
            orderDO = OrderDO.builder()
                    .organId(organId)
                    .dataType(DataTypeEnum.FILE_IMPORT.getStatus())
                    .customer(orderXmlVO.getCustomer())
                    .customOrderNo(orderXmlVO.getOrderCode())
                    .dealer(orderXmlVO.getDealer())
                    .dealerPhoneNumber(orderXmlVO.getDealerPhone())
                    .address(orderXmlVO.getCustomerAddress())
                    .phoneNumber(orderXmlVO.getCustomerPhone())
                    .salesman(orderXmlVO.getSeller())
                    .splitter(orderXmlVO.getAnalyst())
                    .remark(orderXmlVO.getMemo())
                    .orderDate(orderDate.atStartOfDay())
                    .deliveryDate(deliverDate.atStartOfDay())
                    .orderType(OrderTypeEnum.MAIN_ORDER.getStatus())
                    .build();
        }

        // 订单信息验证
        return new XmlCheckVO(error, orderXmlVO, orderDO);
    }

    // 数据格式转换
    public Boolean checkVO(OrderXmlVO orderXmlVO) {
        long startTime = System.currentTimeMillis();
        AtomicBoolean error = new AtomicBoolean(true);

        // 创建一个 CompletableFuture 来表示所有任务的组合
        CompletableFuture<Void> allTasks = CompletableFuture.allOf(
                checkRoomAsync(orderXmlVO.getRoomXmlVOS(), error),
                checkModulesAsync(orderXmlVO.getModuleXmlVOS(), error),
                checkGroupsAsync(orderXmlVO.getGroupXmlVOS(), error),
                checkMaterialsAsync(orderXmlVO.getMaterialXmlVO(), error)
        );

        try {
            // 等待所有任务完成
            allTasks.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            return false; // 如果有异常发生，返回 false
        }

        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;

        System.out.println("方法运行耗时 xml: " + duration + " 毫秒");
        return error.get();
    }

    private CompletableFuture<Void> checkRoomAsync(RoomXmlVOS roomXmlVOS, AtomicBoolean error) {
        return CompletableFuture.runAsync(() -> {
            if (roomXmlVOS != null) {
                checkRoom(roomXmlVOS, error);
            }
        });
    }

    private CompletableFuture<Void> checkModulesAsync(ModuleXmlVOS moduleXmlVOS, AtomicBoolean error) {
        return CompletableFuture.runAsync(() -> {
            if (moduleXmlVOS != null) {
                checkModules(moduleXmlVOS, error);
            }
        });
    }

    private CompletableFuture<Void> checkGroupsAsync(GroupXmlVOS groupXmlVOS, AtomicBoolean error) {
        return CompletableFuture.runAsync(() -> {
            if (groupXmlVOS != null) {
                checkGroups(groupXmlVOS, error);
            }
        });
    }

    private CompletableFuture<Void> checkMaterialsAsync(MaterialXmlVO materialXmlVO, AtomicBoolean error) {
        return CompletableFuture.runAsync(() -> {
            if (materialXmlVO != null) {
                PlateXmlVOS plateXmlVOS = materialXmlVO.getPlateXmlVOS();

                Map<String, Object> map = extractPlateDate(plateXmlVOS);
                if (map != null) {
                    // 判断板块和归属code是否相匹配
                }

                if (plateXmlVOS != null && !plateXmlVOS.getPlateXmlVOList().isEmpty()) {
                    checkPlates(plateXmlVOS.getPlateXmlVOList(), error);
                }

                AccessoryXmlVO accessoryXmlVO = materialXmlVO.getAccessoryXmlVO(); // 配件
                if (accessoryXmlVO != null) {
                    checkEdgings(accessoryXmlVO.getEdgingXmlVOS(), error);
                    checkHardwares(accessoryXmlVO.getHardwareXmlVOS(), error);
                }

                AssemblieXmlVOS assemblieXmlVOS = materialXmlVO.getAssemblieXmlVOS(); // 组件
                if (assemblieXmlVOS != null && assemblieXmlVOS.getAssemblyXmlVOList() != null && !assemblieXmlVOS.getAssemblyXmlVOList().isEmpty()) {
                    checkAssemblies(assemblieXmlVOS, error);
                }
            }
        });
    }
//    public Boolean checkVO(OrderXmlVO orderXmlVO) {
//        long startTime = System.currentTimeMillis();
//        AtomicBoolean error = new AtomicBoolean(true);
//
//        RoomXmlVOS roomXmlVOS = orderXmlVO.getRoomXmlVOS();
//        if (roomXmlVOS != null) {
//            checkRoom(roomXmlVOS, error);
//        }
//
//        ModuleXmlVOS moduleXmlVOS = orderXmlVO.getModuleXmlVOS();
//        if (moduleXmlVOS != null) {
//            checkModules(moduleXmlVOS, error);
//        }
//
//        GroupXmlVOS grooveXmlVOS = orderXmlVO.getGroupXmlVOS();
//        if (grooveXmlVOS != null) {
//            checkGroups(grooveXmlVOS, error);
//        }
//
//        MaterialXmlVO materialXmlVO = orderXmlVO.getMaterialXmlVO();
//        if (materialXmlVO != null) {
//            PlateXmlVOS plateXmlVOS = materialXmlVO.getPlateXmlVOS();
//
//            Map<String, Object> map = extractPlateDate(plateXmlVOS);
//            if (map != null) {
//                // 判断板块和归属code是否相匹配
//            }
//
//            if (plateXmlVOS != null && !plateXmlVOS.getPlateXmlVOList().isEmpty()) {
//                checkPlates(plateXmlVOS.getPlateXmlVOList(), error);
//            }
//
//            AccessoryXmlVO accessoryXmlVO = materialXmlVO.getAccessoryXmlVO(); //配件
//            if (accessoryXmlVO != null) {
//                checkEdgings(accessoryXmlVO.getEdgingXmlVOS(), error);
//                checkHardwares(accessoryXmlVO.getHardwareXmlVOS(), error);
//            }
//
//            AssemblieXmlVOS assemblieXmlVOS = materialXmlVO.getAssemblieXmlVOS(); // 组件
//            if (assemblieXmlVOS != null && assemblieXmlVOS.getAssemblyXmlVOList() != null && !assemblieXmlVOS.getAssemblyXmlVOList().isEmpty()) {
//                checkAssemblies(assemblieXmlVOS, error);
//            }
//        }
//
//        long endTime = System.currentTimeMillis();
//        long duration = endTime - startTime;
//
//        System.out.println("方法运行耗时 xml: " + duration + " 毫秒");
//        return error.get();
//    }


    /**
     *
     * 非空判断，错误返回
     *
     * @param getter:
     * @param name: 字段错误名称
     * @param setter:
     * @param error: 错误赋值
     */
    private void isEmptyAndBack(Supplier<String> getter, String name, Consumer<String> setter, AtomicBoolean error) {
        String value = getter.get();
        if (StringUtils.isEmpty(value)) {
            setter.accept(String.format(IS_NULL, name));
            error.set(false);
        }
    }

    /**
     *
     * 非空判断，空赋初始值
     *
     * @param getter:
     * @param setter:
     * @param defaultValue: 赋值空值
     */

    private void isEmptyAndAdd(Supplier<String> getter, Consumer<String> setter, String defaultValue) {
        String value = getter.get();
        if (StringUtils.isEmpty(value)) {
            setter.accept(defaultValue);
        }
    }

    /**
     *
     * 数量类型+数量正数
     *
     * @param value:
     * @param name: 字段错误名称
     * @param setter:
     * @param targetType: 需要转换的数字类型
     * @param error: 错误赋值
     */
    private void positiveNumber(String value, String name, Consumer<String> setter, Class<?> targetType, AtomicBoolean error) {
        if (ToolUtil.convertToType(value, targetType)) {
            if (!ToolUtil.checkNumber(value)) {
                setter.accept(String.format(POSITIVE_ERR, name));
                error.set(false);
            }
        } else {
            setter.accept(String.format(TYPE_ERR, name));
            error.set(false);
        }

    }

    /**
     *
     * 数量类型+数量正数 + 返回值
     *
     * @param value:
     * @param name: 字段错误名称
     * @param setter:
     * @param targetType: 需要转换的数字类型
     * @param error: 错误赋值
     */
    private boolean positiveNumberAndBack(String value, String name, Consumer<String> setter, Class<?> targetType, AtomicBoolean error) {
        boolean index = error.get();
        if (ToolUtil.convertToType(value, targetType)) {
            if (!ToolUtil.checkNumber(value)) {
                setter.accept(String.format(POSITIVE_ERR, name));
                error.set(false);
                index = false;
            }
        } else {
            setter.accept(String.format(TYPE_ERR, name));
            error.set(false);
            index = false;
        }
        return index;
    }

    /**
     *
     * 数量类型+数量正数+数据长度
     *
     * @param value: 待校验数据
     * @param setter:
     * @param targetType: 数据类型
     * @param name: 字段错误名称
     * @param error: 错误赋值
     */
    private void positiveNumberSize(String value, Consumer<String> setter, Class<?> targetType, String name, Integer length, Integer decimalLength, AtomicBoolean error) {
        if (ToolUtil.convertToType(value, targetType)) {
            if (ToolUtil.checkNumber(value)) {
                if (!ToolUtil.checkPrecision(value, length, decimalLength)) {
                    setter.accept(String.format(LONG_ERR, name));
                    error.set(false);
                }
            } else {
                setter.accept(String.format(POSITIVE_ERR, name));
                error.set(false);
            }
        } else {
            setter.accept(String.format(TYPE_ERR, name));
            error.set(false);
        }
    }

    /**
     *
     * 非空错返+数量类型+数量正数
     *
     * @param getter:
     * @param name: 字段错误名称
     * @param setter:
     * @param targetType: 需要转换的数字类型
     * @param error: 错误赋值
     */
    private void isEmptyBackAndPositiveNumber(Supplier<String> getter, String name, Consumer<String> setter, Class<?> targetType, AtomicBoolean error) {
        String value = getter.get();
        if (StringUtils.isEmpty(value)) {
            setter.accept(String.format(IS_NULL, name));
            error.set(false);
        } else {
            positiveNumber(value, name, setter, targetType, error);
        }
    }

    /**
     *
     * 非空错返+数量类型+数量正数 + 返回值
     *
     * @param getter:
     * @param name: 字段错误名称
     * @param setter:
     * @param targetType: 需要转换的数字类型
     * @param error: 错误赋值
     */
    private boolean isEmptyBackAndPositiveNumberAndBack(Supplier<String> getter, String name, Consumer<String> setter, Class<?> targetType, AtomicBoolean error) {
        boolean index = error.get();
        String value = getter.get();
        if (StringUtils.isEmpty(value)) {
            setter.accept(String.format(IS_NULL, name));
            error.set(false);
            index = false;
        } else {
            index = positiveNumberAndBack(value, name, setter, targetType, error);
        }
        return index;
    }

    /**
     *
     * 非空错返 +数量类型+数量正数+数据长度
     *
     * @param getter:
     * @param name: 字段错误名称
     * @param setter:
     * @param targetType: 需要转换的数字类型
     * @param error: 错误赋值
     */
    private void isEmptyAndPositiveNumber(Supplier<String> getter, String name, Consumer<String> setter, Class<?> targetType, Integer length, Integer decimalLength, AtomicBoolean error) {
        String value = getter.get();
        if (StringUtils.isEmpty(value)) {
            setter.accept(String.format(IS_NULL, name));
            error.set(false);
        } else {
            positiveNumberSize(value, setter, targetType, name, length, decimalLength, error);
        }
    }

    /**
     *
     * 空值赋值 +数量类型+数量正数
     *
     * @param getter:
     * @param setter:
     * @param defaultValue: 赋值数据
     * @param targetType: 数据类型
     * @param name: 字段错误名称
     * @param error: 错误赋值
     */
    private void isEmptyAddAndPositiveNumber(Supplier<String> getter, Consumer<String> setter, String defaultValue, Class<?> targetType, String name, AtomicBoolean error) {
        String value = getter.get();
        if (StringUtils.isEmpty(value)) {
            setter.accept(defaultValue);
        } else {
            positiveNumber(value, name, setter, targetType, error);
        }
    }

    /**
     *
     * 空值赋值+数量类型+数量正数+数据长度
     *
     * @param getter:
     * @param setter:
     * @param defaultValue: 赋值数据
     * @param targetType: 数据类型
     * @param name: 字段错误名称
     * @param error: 错误赋值
     */
    private void isEmptyAddAndPositiveNumberSize(Supplier<String> getter, Consumer<String> setter, String defaultValue, Class<?> targetType, String name, Integer length, Integer decimalLength, AtomicBoolean error) {
        String value = getter.get();
        if (StringUtils.isEmpty(value)) {
            setter.accept(defaultValue);
        } else {
            positiveNumberSize(value, setter, targetType, name, length, decimalLength, error);
        }
    }

    /**
     *
     * 空值赋值+数量类型
     *
     * @param getter:
     * @param setter:
     * @param defaultValue: 赋值数据
     * @param targetType: 数据类型
     * @param name: 字段错误名称
     * @param error: 错误赋值
     */
    private void isEmptyAddAndNumber(Supplier<String> getter, Consumer<String> setter, String defaultValue, Class<?> targetType, String name, AtomicBoolean error) {
        String value = getter.get();
        if (StringUtils.isEmpty(value)) {
            setter.accept(defaultValue);
        } else {
            if (!ToolUtil.convertToType(value.trim(), targetType)) {
                setter.accept(String.format(TYPE_ERR, name));
                error.set(false);
            }
        }
    }

    /**
     *
     * 空值错返+数量类型
     *
     * @param getter:
     * @param setter:
     * @param targetType: 数据类型
     * @param name: 字段错误名称
     * @param error: 错误赋值
     */
    private void isEmptyBackAndNumber(Supplier<String> getter, Consumer<String> setter, Class<?> targetType, String name, AtomicBoolean error) {
        String value = getter.get();
        if (StringUtils.isEmpty(value)) {
            setter.accept(String.format(IS_NULL, name));
            error.set(false);
        } else {
            if (!ToolUtil.convertToType(value.trim(), targetType)) {
                setter.accept(String.format(TYPE_ERR, name));
                error.set(false);
            }
        }
    }

    /**
     *
     * 空值赋值+非空有效性判断
     *
     * @param getter:
     * @param setter:
     * @param dictTypeConstants: 字典标签
     * @param name: 字段错误名称
     * @param error: 错误赋值
     */
    private void isEmptyBackAndInvalid(Supplier<String> getter, Consumer<String> setter, String dictTypeConstants, String name, AtomicBoolean error) {
        String value = getter.get();
        if (StringUtils.isEmpty(value)) {
            setter.accept(String.format(IS_NULL, name));
            error.set(false);
        } else {
            DictDataRespDTO dictData = dictDataApi.parseDictData(dictTypeConstants, value.trim()).getData();
            if (dictData == null) {
                setter.accept(String.format(INVALID, name));
                error.set(false);
            }
        }
    }

    /**
     *
     * 空值返回+非空有效性判断
     *
     * @param getter:
     * @param setter:
     * @param defaultValue: 赋值数据
     * @param dictTypeConstants: 字典标签
     * @param name: 字段错误名称
     * @param error: 错误赋值
     */
    private void isEmptyAddAndInvalid(Supplier<String> getter, Consumer<String> setter, String defaultValue, String dictTypeConstants, String name, AtomicBoolean error) {
        String value = getter.get();
        if (StringUtils.isEmpty(value)) {
            setter.accept(defaultValue);
        } else {
            DictDataRespDTO dictData = dictDataApi.parseDictData(dictTypeConstants, value.trim()).getData();
            if (dictData == null) {
                setter.accept(String.format(INVALID, name));
                error.set(false);
            }
        }
    }

    /**
     *
     * 非空判断+数据类型+数据正数
     *
     * @param getter:
     * @param setter:
     * @param name: 字段错误名称
     * @param targetType: 数字类型
     * @param error: 错误赋值
     */
    private void notEmptyPositiveNumber(Supplier<String> getter, Consumer<String> setter, String name, Class<?> targetType, AtomicBoolean error) {
        String value = getter.get();
        if (!StringUtils.isEmpty(value)) { // 非空
            positiveNumber(value, name, setter, targetType, error);
        }
    }

    /**
     *
     * 非空判断 +数据类型+数据正数+数据长度
     *
     * @param getter:
     * @param setter:
     * @param name: 字段错误名称
     * @param targetType: 数字类型
     * @param error: 错误赋值
     */
    private void notEmptyPositiveNumberSize(Supplier<String> getter, Consumer<String> setter, String name, Class<?> targetType, Integer length, Integer decimalLength, AtomicBoolean error) {
        String value = getter.get();
        if (!StringUtils.isEmpty(value)) { // 非空
            positiveNumberSize(value, setter, targetType, name, length, decimalLength, error);
        }
    }

    //
    private void checkAssemblies(AssemblieXmlVOS assemblieXmlVOS, AtomicBoolean flag) {
        if (assemblieXmlVOS != null && assemblieXmlVOS.getAssemblyXmlVOList().size() > 0) {
            for (AssemblyXmlVO assemblyXmlVO : assemblieXmlVOS.getAssemblyXmlVOList()) {
                isEmptyAndBack(assemblyXmlVO::getName, "组件名称", assemblyXmlVO::setName, flag);
                isEmptyAndBack(assemblyXmlVO::getMaterial, "组件材质", assemblyXmlVO::setMaterial, flag);
                isEmptyAndBack(assemblyXmlVO::getColor, "组件颜色", assemblyXmlVO::setColor, flag);
                isEmptyBackAndPositiveNumber(assemblyXmlVO::getCount, "组件数量", assemblyXmlVO::setCount, Double.class, flag);
                isEmptyAndBack(assemblyXmlVO::getUnitCount, "组件数量单位", assemblyXmlVO::setUnitCount, flag);
                isEmptyAndAdd(assemblyXmlVO::getRoomCode, assemblyXmlVO::setRoomCode, NOT_ASSIGNED_CODE);
                isEmptyAndAdd(assemblyXmlVO::getRoomName, assemblyXmlVO::setRoomName, NOT_ASSIGNED);
                isEmptyAndAdd(assemblyXmlVO::getBoxCode, assemblyXmlVO::setBoxCode, NOT_ASSIGNED_CODE);
                isEmptyAndAdd(assemblyXmlVO::getBoxName, assemblyXmlVO::setBoxName, NOT_ASSIGNED);
            }
        }
    }

    private void checkHardwares(HardwareXmlVOS hardwareXmlVOS, AtomicBoolean flag) {
        if (hardwareXmlVOS != null && hardwareXmlVOS.getHardwareXmlVOList().size() > 0) {
            for (HardwareXmlVO hardwareXmlVO : hardwareXmlVOS.getHardwareXmlVOList()) {
                isEmptyAndAdd(hardwareXmlVO::getRoomCode, hardwareXmlVO::setRoomCode, NOT_ASSIGNED_CODE);
                isEmptyAndAdd(hardwareXmlVO::getRoomName, hardwareXmlVO::setRoomName, NOT_ASSIGNED);
                isEmptyAndAdd(hardwareXmlVO::getBoxCode, hardwareXmlVO::setBoxCode, NOT_ASSIGNED_CODE);
                isEmptyAndAdd(hardwareXmlVO::getBoxName, hardwareXmlVO::setBoxName, NOT_ASSIGNED);
                isEmptyAndBack(hardwareXmlVO::getName, "五金名称", hardwareXmlVO::setName, flag);
                isEmptyAndBack(hardwareXmlVO::getMaterial, "五金材质", hardwareXmlVO::setMaterial, flag);
                isEmptyAndBack(hardwareXmlVO::getColor, "五金颜色", hardwareXmlVO::setColor, flag);
                isEmptyBackAndPositiveNumber(hardwareXmlVO::getCount, "五金数量", hardwareXmlVO::setCount, Double.class, flag);
                isEmptyAndBack(hardwareXmlVO::getUnitCount, "五金数量单位", hardwareXmlVO::setUnitCount, flag);
                isEmptyAndBack(hardwareXmlVO::getUnit, "五金单位", hardwareXmlVO::setUnit, flag);
            }
        }
    }

    private void checkEdgings(EdgingXmlVOS edgingXmlVOS, AtomicBoolean flag) {
        if (edgingXmlVOS != null && edgingXmlVOS.getEdgingXmlVOList().size() > 0) {
            for (EdgingXmlVO edgingXmlVO : edgingXmlVOS.getEdgingXmlVOList()) {
                isEmptyAndAdd(edgingXmlVO::getRoomCode, edgingXmlVO::setRoomCode, NOT_ASSIGNED_CODE);
                isEmptyAndAdd(edgingXmlVO::getRoomName, edgingXmlVO::setRoomName, NOT_ASSIGNED);
                isEmptyAndAdd(edgingXmlVO::getBoxCode, edgingXmlVO::setBoxCode, NOT_ASSIGNED_CODE);
                isEmptyAndAdd(edgingXmlVO::getBoxName, edgingXmlVO::setBoxName, NOT_ASSIGNED);
                isEmptyAndBack(edgingXmlVO::getName, "封边条名称", edgingXmlVO::setName, flag);
                isEmptyAndBack(edgingXmlVO::getMaterial, "封边条材质", edgingXmlVO::setMaterial, flag);
                isEmptyAndBack(edgingXmlVO::getColor, "封边条颜色", edgingXmlVO::setColor, flag);
                isEmptyBackAndPositiveNumber(edgingXmlVO::getLength, "封边条长度", edgingXmlVO::setLength, Double.class, flag);
                isEmptyBackAndPositiveNumber(edgingXmlVO::getWidth, "封边条宽度", edgingXmlVO::setWidth, Double.class, flag);
                isEmptyBackAndPositiveNumber(edgingXmlVO::getThickness, "封边条厚度", edgingXmlVO::setThickness, Double.class, flag);
                isEmptyAddAndInvalid(edgingXmlVO::getUnit, edgingXmlVO::setUnit, "mm", DictTypeConstants.UNIT_LENGTH, "封边条长度单位", flag);
                isEmptyBackAndPositiveNumber(edgingXmlVO::getCount, "封边条数量", edgingXmlVO::setCount, Double.class, flag);
                isEmptyAddAndInvalid(edgingXmlVO::getUnitCount, edgingXmlVO::setUnitCount, "m", DictTypeConstants.UNIT_LENGTH, "封边条数量单位", flag);
            }
        }
    }

    // 房间数据格式验证
    public void checkRoom(RoomXmlVOS roomXmlVOS, AtomicBoolean flag) {
        notEmptyPositiveNumber(roomXmlVOS::getCount, roomXmlVOS::setCount, "房间数量", Integer.class, flag);

        for (RoomXmlVO room : roomXmlVOS.getRoomXmlVOList()) {
            isEmptyAndAdd(room::getCode, room::setCode, NOT_ASSIGNED_CODE);
            isEmptyAndAdd(room::getName, room::setName, NOT_ASSIGNED);

            isEmptyAddAndPositiveNumberSize(room::getHeight, room::setHeight, "0", Double.class, "房间高度", 8, 3, flag);
            isEmptyAddAndPositiveNumberSize(room::getLength, room::setLength, "0", Double.class, "房间长度", 8, 3, flag);
            isEmptyAddAndPositiveNumberSize(room::getWidth, room::setWidth, "0", Double.class, "房间宽度", 8, 3, flag);
            isEmptyAddAndPositiveNumber(room::getMultipleNumber, room::setMultipleNumber, "1", Integer.class, "房间成倍拆单数量", flag);
            isEmptyAddAndPositiveNumber(room::getMultipleNo, room::setMultipleNo, "1", Integer.class, "房间成倍拆单序号", flag);
            isEmptyAddAndNumber(room::getBasePointX, room::setBasePointX, "0", Double.class, "基点坐标X", flag);
            isEmptyAddAndNumber(room::getBasePointY, room::setBasePointY, "0", Double.class, "基点坐标Y", flag);
            isEmptyAddAndNumber(room::getBasePointZ, room::setBasePointZ, "0", Double.class, "基点坐标Z", flag);
            isEmptyAddAndNumber(room::getAxisXrotate, room::setAxisXrotate, "0", Double.class, "绕X轴旋转角度", flag);
            isEmptyAddAndNumber(room::getAxisYrotate, room::setAxisYrotate, "0", Double.class, "绕Y轴旋转角度", flag);
            isEmptyAddAndNumber(room::getAxisZrotate, room::setAxisZrotate, "0", Double.class, "绕Z轴旋转角度", flag);

            // 柜体数据格式验证
            if (room.getBoxXmlVOList() != null && !room.getBoxXmlVOList().isEmpty()) {
                checkBoxList(room.getBoxXmlVOList(), flag);

            }
        }
    }

    // 柜体数据格式验证
    public void checkBoxList(List<BoxXmlVO> boxXmlVOList, AtomicBoolean flag) {
        for (BoxXmlVO box : boxXmlVOList) {
            isEmptyAddAndPositiveNumberSize(box::getHeight, box::setHeight, "0", Double.class, "柜体高度", 8, 3, flag);
            isEmptyAddAndPositiveNumberSize(box::getLength, box::setLength, "0", Double.class, "柜体长度", 8, 3, flag);
            isEmptyAddAndPositiveNumberSize(box::getWidth, box::setWidth, "0", Double.class, "柜体宽度", 8, 3, flag);
            isEmptyAddAndPositiveNumber(box::getMultipleNumber, box::setMultipleNumber, "1", Integer.class, "柜体成倍拆单数量", flag);
            isEmptyAddAndPositiveNumber(box::getMultipleNo, box::setMultipleNo, "1", Integer.class, "柜体成倍拆单序号", flag);
            isEmptyAddAndNumber(box::getBasePointX, box::setBasePointX, "0", Double.class, "基点坐标X", flag);
            isEmptyAddAndNumber(box::getBasePointY, box::setBasePointY, "0", Double.class, "基点坐标Y", flag);
            isEmptyAddAndNumber(box::getBasePointZ, box::setBasePointZ, "0", Double.class, "基点坐标Z", flag);
            isEmptyAddAndNumber(box::getAxisXrotate, box::setAxisXrotate, "0", Double.class, "绕X轴旋转角度", flag);
            isEmptyAddAndNumber(box::getAxisYrotate, box::setAxisYrotate, "0", Double.class, "绕Y轴旋转角度", flag);
            isEmptyAddAndNumber(box::getAxisZrotate, box::setAxisZrotate, "0", Double.class, "绕Z轴旋转角度", flag);
            isEmptyAndAdd(box::getCode, box::setCode, NOT_ASSIGNED_CODE);
            isEmptyAndAdd(box::getName, box::setName, NOT_ASSIGNED);
        }
    }

    // 模块数据格式验证
    public void checkModules(ModuleXmlVOS moduleXmlVOS, AtomicBoolean flag) {
        notEmptyPositiveNumber(moduleXmlVOS::getCount, moduleXmlVOS::setCount, "模块数量", Integer.class, flag);

        if (moduleXmlVOS.getModuleXmlVOList() != null && moduleXmlVOS.getModuleXmlVOList().size() > 0) {
            checkModuleList(moduleXmlVOS.getModuleXmlVOList(), flag);
        }

    }

    // 模块数据格式验证
    public void checkModuleList(List<ModuleXmlVO> moduleXmlVOSList, AtomicBoolean flag) {
        for (ModuleXmlVO module : moduleXmlVOSList) {
            isEmptyAndAdd(module::getCode, module::setCode, NOT_ASSIGNED_CODE);
            isEmptyAndAdd(module::getName, module::setName, NOT_ASSIGNED);

            isEmptyAddAndPositiveNumberSize(module::getLength, module::setLength, "0", Double.class, "模块长度", 8, 3, flag);
            isEmptyAddAndPositiveNumberSize(module::getWidth, module::setWidth, "0", Double.class, "模块宽度", 8, 3, flag);
            isEmptyAddAndPositiveNumberSize(module::getHeight, module::setHeight, "0", Double.class, "模块高度", 8, 3, flag);
        }
    }

    // 加工组数据格式验证
    public void checkGroups(GroupXmlVOS groupXmlVOS, AtomicBoolean flag) {
        notEmptyPositiveNumber(groupXmlVOS::getCount, groupXmlVOS::setCount, "加工组数量", Integer.class, flag);

        if (groupXmlVOS.getGroupXmlVOList() != null && groupXmlVOS.getGroupXmlVOList().size() > 0) {
            checkGroupList(groupXmlVOS.getGroupXmlVOList(), flag);
        }
    }

    // 加工组数据格式验证
    public void checkGroupList(List<GroupXmlVO> groupXmlVOList, AtomicBoolean flag) {
        for (GroupXmlVO group : groupXmlVOList) {
            isEmptyAndAdd(group::getCode, group::setCode, NOT_ASSIGNED_CODE);
            isEmptyAndAdd(group::getName, group::setName, NOT_ASSIGNED);

            isEmptyAddAndPositiveNumberSize(group::getLength, group::setLength, "0", Double.class, "模块长度", 8, 3, flag);
            isEmptyAddAndPositiveNumberSize(group::getWidth, group::setWidth, "0", Double.class, "模块宽度", 8, 3, flag);
            isEmptyAddAndPositiveNumberSize(group::getHeight, group::setHeight, "0", Double.class, "模块高度", 8, 3, flag);

        }
    }

    // 板材数据格式验证
    public void checkPlates(List<PlateXmlVO> plateXmlVOList, AtomicBoolean flag) {
        for (PlateXmlVO plate : plateXmlVOList) {
            isEmptyAndBack(plate::getName, "板材名称", plate::setName, flag);
            isEmptyAndBack(plate::getMaterial, "板材材质", plate::setMaterial, flag);

            // 纹理有效性判断
            plate.setGrained(StringUtils.isEmpty(plate.getGrained()) ? "有" : plate.getGrained());
            isEmptyAddAndInvalid(plate::getGrained, plate::setGrained,  "有", DictTypeConstants.PLATE_TEXTURE_TYPE, "板材纹理", flag);
            isEmptyAddAndInvalid(plate::getCoating, plate::setCoating,  "双面", DictTypeConstants.COATING_TYPE, "板材设计饰面", flag);
            isEmptyAndPositiveNumber(plate::getLength, "板材长度", plate::setLength, Double.class, 5, 3, flag);
            isEmptyAndPositiveNumber(plate::getWidth, "板材宽度", plate::setWidth, Double.class, 5, 3, flag);
            isEmptyAndPositiveNumber(plate::getThickness, "板材厚度", plate::setThickness, Double.class, 5, 3, flag);
            notEmptyPositiveNumberSize(plate::getOddmentLength, plate::setOddmentLength, "余料长", Double.class, 5, 3, flag);
            notEmptyPositiveNumberSize(plate::getOddmentWidth, plate::setOddmentWidth, "余料宽", Double.class, 5, 3, flag);
            notEmptyPositiveNumberSize(plate::getOddmentThickness, plate::setOddmentThickness, "余料厚", Double.class, 5, 3, flag);
            isEmptyAddAndInvalid(plate::getOddment, plate::setOddment, "否", DictTypeConstants.ODDMENT_MARK, "板材是否余料标识", flag);
            isEmptyAddAndInvalid(plate::getUnitLength, plate::setUnitLength, "mm", DictTypeConstants.UNIT_LENGTH, "板块长度单位", flag);
            notEmptyPositiveNumber(plate::getArea, plate::setArea, "板块面积", Double.class, flag);
            isEmptyAddAndInvalid(plate::getUnitArea, plate::setUnitArea, "m²", DictTypeConstants.UNIT_AREA, "板块面积单位", flag);
            notEmptyPositiveNumber(plate::getCount, plate::setCount, "板块数量", Integer.class, flag);
            isPlateExists(plate, flag);

            if (plate.getBlockXmlVOS() != null) {
                checkBlocks(plate.getBlockXmlVOS(), flag);
            }
        }
    }

    // 板件是否存在判断，优先goodsId，没有判断（名称，材料，颜色，厚度，品牌（存在判断））
    private void isPlateExists(PlateXmlVO plate, AtomicBoolean flag) {
        PlateGoodDO plateGoodDO = null;
        List<PlateGoodDO> plateGoodDOs;
        if (StringUtils.isNotEmpty(plate.getItemCode())) { // 判断 goodsId
            plateGoodDOs = plateGoodMapper.selectGoodOne(plate.getItemCode(), OrganContextHolder.getOrganId());
        } else { // 判断（名称，材料，颜色，后端，品牌（存在判断））
            plateGoodDOs = plateGoodMapper.selectGood(plate.getMaterial(), plate.getCoatingObverse(),
                    BigDecimal.valueOf(Long.parseLong(plate.getThickness())),
                    plate.getBrand(),plate.getName(), OrganContextHolder.getOrganId());
        }

        if (!plateGoodDOs.isEmpty()) {
            plateGoodDO = plateGoodDOs.get(0);
        }

        if (plateGoodDO != null) {
            plate.setItemCode(plateGoodDO.getGoodsId());
        } else {
            plate.setItemCode(PLATE_NOT_EXIST);
            flag.set(false);
        }
    }
    // 小板数据格式验证
    public void checkBlocks(BlockXmlVOS blockXmlVOS, AtomicBoolean flag) {
        notEmptyPositiveNumber(blockXmlVOS::getCount, blockXmlVOS::setCount, "小板数量", Integer.class, flag);
        notEmptyPositiveNumber(blockXmlVOS::getArea, blockXmlVOS::setArea, "小板总面积", Double.class, flag);
        isEmptyAddAndInvalid(blockXmlVOS::getUnit, blockXmlVOS::setUnit, "m²", DictTypeConstants.UNIT_AREA, "小板总面积单位", flag);

        if (blockXmlVOS.getBlockXmlVOList() != null && !blockXmlVOS.getBlockXmlVOList().isEmpty()) {
            checkBlockList(blockXmlVOS.getBlockXmlVOList(), flag);
        }
    }

    // 板块数据格式验证
    public void checkBlockList(List<BlockXmlVO> blockXmlVOList, AtomicBoolean flag) {
        if (blockXmlVOList.isEmpty()) {
            return;
        }
        for (BlockXmlVO blockXmlVO : blockXmlVOList) {
            isEmptyAndAdd(blockXmlVO::getName, blockXmlVO::setName, NOT_ASSIGNED);
            isEmptyAddAndInvalid(blockXmlVO::getType, blockXmlVO::setType, "背板", DictTypeConstants.PLATE_TYPE, "板块类型", flag);
            isEmptyAddAndInvalid(blockXmlVO::getOpenDirection, blockXmlVO::setOpenDirection, "非门板", DictTypeConstants.DOOR_OPENING_DIRECTIONS, "板块开门方向", flag);
            isEmptyAddAndInvalid(blockXmlVO::getTexture, blockXmlVO::setTexture, "正纹", DictTypeConstants.GRAIN_TYPE, "板块设计纹路", flag);
            isEmptyAddAndInvalid(blockXmlVO::getLayoutFace, blockXmlVO::setLayoutFace, "随意面", DictTypeConstants.TYPOGRAPHY_TYPE, "板块排版面", flag);
            isEmptyAddAndInvalid(blockXmlVO::getCoatingType, blockXmlVO::setCoatingType, "双面", DictTypeConstants.COATING_TYPE, "板块设计饰面", flag);
            isEmptyAndPositiveNumber(blockXmlVO::getLength, "板块长度", blockXmlVO::setLength, Double.class, 5, 3, flag);
            isEmptyAndPositiveNumber(blockXmlVO::getWidth, "板块宽度", blockXmlVO::setWidth, Double.class, 5, 3, flag);
            isEmptyAndPositiveNumber(blockXmlVO::getThickness, "板块厚度", blockXmlVO::setThickness, Double.class, 5, 3, flag);
            isEmptyAndPositiveNumber(blockXmlVO::getCuttingLength, "板块开料长", blockXmlVO::setCuttingLength, Double.class, 5, 3, flag);
            isEmptyAndPositiveNumber(blockXmlVO::getCuttingWidth, "板块开料宽", blockXmlVO::setCuttingWidth, Double.class, 5, 3, flag);
            isEmptyAndPositiveNumber(blockXmlVO::getCuttingThickness, "板块开料厚", blockXmlVO::setCuttingThickness, Double.class, 5, 3, flag);
            isEmptyAndPositiveNumber(blockXmlVO::getRawLength, "板块胚料长", blockXmlVO::setRawLength, Double.class, 5, 3, flag);
            isEmptyAndPositiveNumber(blockXmlVO::getRawWidth, "板块胚料宽", blockXmlVO::setRawWidth, Double.class, 5, 3, flag);
            isEmptyAndPositiveNumber(blockXmlVO::getRawThickness, "板块胚料厚", blockXmlVO::setRawThickness, Double.class, 5, 3, flag);
            isEmptyAddAndInvalid(blockXmlVO::getUnit, blockXmlVO::setUnit, "mm", DictTypeConstants.UNIT_LENGTH, "小板长度单位", flag);
            isEmptyAddAndPositiveNumber(blockXmlVO::getMultipleNumber, blockXmlVO::setMultipleNumber, "1", Integer.class, "小板成倍拆单数量", flag);
            isEmptyAddAndPositiveNumber(blockXmlVO::getMultipleNo, blockXmlVO::setMultipleNo, "1", Integer.class, "小板成倍拆单序号", flag);
            isEmptyAddAndInvalid(blockXmlVO::getUnregular, blockXmlVO::setUnregular, "否", DictTypeConstants.IS_NOT_MARK, "板块是否异形数据", flag);
            isEmptyAddAndInvalid(blockXmlVO::getDrilling, blockXmlVO::setDrilling, "否", DictTypeConstants.IS_NOT_MARK, "板块是否钻孔数据", flag);
            isEmptyAddAndInvalid(blockXmlVO::getSlotting, blockXmlVO::setSlotting, "否", DictTypeConstants.IS_NOT_MARK, "板块是否挖槽数据", flag);

            isEmptyAndAdd(blockXmlVO::getRoomCode, blockXmlVO::setRoomCode, NOT_ASSIGNED_CODE);
            isEmptyAndAdd(blockXmlVO::getRoomName, blockXmlVO::setRoomName, NOT_ASSIGNED);
            isEmptyAndAdd(blockXmlVO::getBoxCode, blockXmlVO::setBoxCode, NOT_ASSIGNED_CODE);
            isEmptyAndAdd(blockXmlVO::getBoxName, blockXmlVO::setBoxName, NOT_ASSIGNED);

            isEmptyAddAndNumber(blockXmlVO::getBasePointX, blockXmlVO::setBasePointX, "0", Double.class, "小板基点坐标X", flag);
            isEmptyAddAndNumber(blockXmlVO::getBasePointY, blockXmlVO::setBasePointY, "0", Double.class, "小板基点坐标Y", flag);
            isEmptyAddAndNumber(blockXmlVO::getBasePointZ, blockXmlVO::setBasePointZ, "0", Double.class, "小板基点坐标Z", flag);
            isEmptyAddAndNumber(blockXmlVO::getAxisXrotate, blockXmlVO::setAxisXrotate, "0", Double.class, "小板绕X轴旋转角度", flag);
            isEmptyAddAndNumber(blockXmlVO::getAxisYrotate, blockXmlVO::setAxisYrotate, "0", Double.class, "小板绕Y轴旋转角度", flag);
            isEmptyAddAndNumber(blockXmlVO::getAxisZrotate, blockXmlVO::setAxisZrotate, "0", Double.class, "小板绕Z轴旋转角度", flag);



            if (blockXmlVO.getOutlineXmlVO() != null) {
                checkOutline(blockXmlVO.getOutlineXmlVO(), flag);
            }

            if (blockXmlVO.getCuttingOutlineXmlVO() != null) {
                checkCuttingOutline(blockXmlVO.getCuttingOutlineXmlVO(), flag);
            }

            if (blockXmlVO.getRawOutlineXmlVO() != null && blockXmlVO.getRawOutlineXmlVO().getPointXmlVOList() != null && !blockXmlVO.getRawOutlineXmlVO().getPointXmlVOList().isEmpty()) {
                checkRawOutline(blockXmlVO.getRawOutlineXmlVO(), flag);
            }

            if (blockXmlVO.getHoleXmlVOS() != null) {
                checkHoles(blockXmlVO.getHoleXmlVOS(), flag);
            }

            if (blockXmlVO.getGrooveXmlVOS() != null) {
                checkGrooves(blockXmlVO.getGrooveXmlVOS(), flag);
            }

            if (blockXmlVO.getIsletXmlVOS() != null && blockXmlVO.getIsletXmlVOS().getIsletXmlVOList() != null && !blockXmlVO.getIsletXmlVOS().getIsletXmlVOList().isEmpty()) {
                checkIslets(blockXmlVO.getIsletXmlVOS(), flag);
            }

            if (blockXmlVO.getCorrelationXmlVOS() != null) {
                checkCorrelations(blockXmlVO.getCorrelationXmlVOS(), flag);
            }

        }
    }

    private void checkCorrelations(CorrelationXmlVOS correlationXmlVOS, AtomicBoolean flag) {
        notEmptyPositiveNumber(correlationXmlVOS::getCount, correlationXmlVOS::setCount, "关联的配件数量", Integer.class, flag);

        if (correlationXmlVOS.getCorrelationXmlVOList() != null && !correlationXmlVOS.getCorrelationXmlVOList().isEmpty()) {
            for (CorrelationXmlVO correlationXmlVO : correlationXmlVOS.getCorrelationXmlVOList()) {
                if (StringUtils.isEmpty(correlationXmlVO.getItemCode())) {
                    isEmptyAndBack(correlationXmlVO::getName, "关联配件名称", correlationXmlVO::setName, flag);
                }
                isEmptyBackAndPositiveNumber(correlationXmlVO::getCount, "关联配件的数量", correlationXmlVO::setCount, Integer.class, flag);
            }
        }
    }

    private void checkIslets(IsletXmlVOS isletXmlVOS, AtomicBoolean flag) {
        boolean index = isEmptyBackAndPositiveNumberAndBack(isletXmlVOS::getCount, "孤岛数量 "+ isletXmlVOS.getCount(), isletXmlVOS::setCount, Integer.class, flag);

        if (index) {
            if (isletXmlVOS.getIsletXmlVOList() == null) {
                isletXmlVOS.setCount("---< 孤岛数量与孤岛列表数量不一致 >---");
                flag.set(false);
            } else if (isletXmlVOS.getIsletXmlVOList().size() > 0) {
                if (Integer.parseInt(isletXmlVOS.getCount()) != isletXmlVOS.getIsletXmlVOList().size()) {
                    isletXmlVOS.setCount("---< 孤岛数量与孤岛列表数量不一致 >---");
                    flag.set(false);
                } else {
                    for (IsletXmlVO isletXmlVO : isletXmlVOS.getIsletXmlVOList()) {
                        checkIslet(isletXmlVO, flag);
                    }
                }
            }
        }

    }

    private void checkIslet(IsletXmlVO isletXmlVO, AtomicBoolean flag) {
        isEmptyAndBack(isletXmlVO::getId, "孤岛ID", isletXmlVO::setId, flag);

        // 造型内孤岛 两个
        if (isletXmlVO.getPointXmlVOS() == null) {
            return;
        }

        PointXmlVOS pointXmlVOS = isletXmlVO.getPointXmlVOS();
        boolean index = isEmptyBackAndPositiveNumberAndBack(pointXmlVOS::getCount, "孤岛点阵数量 "+ pointXmlVOS.getCount(), pointXmlVOS::setCount, Integer.class, flag);


        if (index) {
            if (pointXmlVOS.getPointXmlVOList() == null) {
                pointXmlVOS.setCount("---< 孤岛点阵数量与孤岛点阵列表数量不一致 >---");
                flag.set(false);
            } else if (pointXmlVOS.getPointXmlVOList().size() > 0) {
                if (Integer.parseInt(pointXmlVOS.getCount()) != pointXmlVOS.getPointXmlVOList().size()) {
                    pointXmlVOS.setCount("---< 孤岛点阵数量与孤岛点阵列表数量不一致 >---");
                    flag.set(false);
                } else {
                    for (PointXmlVO pointXmlVO : pointXmlVOS.getPointXmlVOList()) {
                        checkPointRemoveZ(pointXmlVO, flag, "孤岛");
                    }
                }
            }
        }


    }

    private void checkHoles(HoleXmlVOS holeXmlVOS, AtomicBoolean flag) {
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCount, holeXmlVOS::setCount, "0", Integer.class, "孔数量 " + holeXmlVOS.getCount(), flag);
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCountFaceA, holeXmlVOS::setCountFaceA, "0", Integer.class, "正面垂直孔数量 " + holeXmlVOS.getCountFaceA(), flag);
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCountFaceB, holeXmlVOS::setCountFaceB, "0", Integer.class, "反面垂直孔数量 " + holeXmlVOS.getCountFaceB(), flag);
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCountSide, holeXmlVOS::setCountSide, "0", Integer.class, "水平侧孔数量 " + holeXmlVOS.getCountSide(), flag);
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCountSideL, holeXmlVOS::setCountSideL, "0", Integer.class, "左侧孔数量 " + holeXmlVOS.getCountSideL(), flag);
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCountSideR, holeXmlVOS::setCountSideR, "0", Integer.class, "右侧孔数量 " + holeXmlVOS.getCountSideR(), flag);
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCountSideU, holeXmlVOS::setCountSideU, "0", Integer.class, "上侧孔数量 " + holeXmlVOS.getCountSideU(), flag);
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCountSideD, holeXmlVOS::setCountSideD, "0", Integer.class, "下侧孔数量 " + holeXmlVOS.getCountSideD(), flag);
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCountBevelled, holeXmlVOS::setCountBevelled, "0", Integer.class, "斜孔数量 " + holeXmlVOS.getCountBevelled(), flag);
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCountLocking, holeXmlVOS::setCountLocking, "0", Integer.class, "偏心轮/锁定孔数量 " + holeXmlVOS.getCountLocking(), flag);
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCountBuildIn, holeXmlVOS::setCountBuildIn, "0", Integer.class, "预埋件/插入孔数量 " + holeXmlVOS.getCountBuildIn(), flag);
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCountHinge, holeXmlVOS::setCountHinge, "0", Integer.class, "铰链孔数量 " + holeXmlVOS.getCountHinge(), flag);
        isEmptyAddAndPositiveNumber(holeXmlVOS::getCountThrough, holeXmlVOS::setCountThrough, "0", Integer.class, "穿孔数量 " + holeXmlVOS.getCountThrough(), flag);

        if (holeXmlVOS.getHoleXmlVOList() != null && holeXmlVOS.getHoleXmlVOList().size() > 0) {
            for (HoleXmlVO holeXmlVO : holeXmlVOS.getHoleXmlVOList()) {
                checkHole(holeXmlVO, flag);
            }
        }
    }

    private void checkHole(HoleXmlVO holeXmlVO, AtomicBoolean flag) {
//        (holeXmlVO::getType, holeXmlVO::setType, DictTypeConstants.HOLE_FACE, "小板孔类型 ", flag);
        isEmptyBackAndInvalid(holeXmlVO::getDirection, holeXmlVO::setDirection, DictTypeConstants.HOLE_DIRECTION, "小板孔加工方向 ", flag);
        isEmptyBackAndPositiveNumber(holeXmlVO::getDiameter, "小板孔直径", holeXmlVO::setDiameter,  Double.class , flag);
        if (StringUtils.isNotEmpty(holeXmlVO.getType()) && holeXmlVO.getType().equals("沉头孔")) {
            isEmptyBackAndPositiveNumber(holeXmlVO::getDiameterInner,"当小板孔类型为沉头孔时，小板孔沉头孔内径", holeXmlVO::setDiameterInner, Double.class , flag);
            isEmptyBackAndPositiveNumber(holeXmlVO::getDepthInner, "当小板孔类型为沉头孔时，沉头孔的深度", holeXmlVO::setDepthInner, Double.class , flag);
        }
        isEmptyBackAndPositiveNumber(holeXmlVO::getDepth, "小板孔深度", holeXmlVO::setDepth, Double.class , flag);
        notEmptyPositiveNumber(holeXmlVO::getGroupNumber, holeXmlVO::setGroupNumber, "版面组号", Integer.class, flag);
        isEmptyAddAndNumber(holeXmlVO::getGroupXoffset, holeXmlVO::setGroupXoffset, "0", Double.class ,"孔组X坐标偏移", flag);
        isEmptyAddAndNumber(holeXmlVO::getGroupYoffset, holeXmlVO::setGroupYoffset, "0", Double.class ,"孔组Y坐标偏移", flag);
        isEmptyAddAndNumber(holeXmlVO::getGroupZoffset, holeXmlVO::setGroupZoffset, "0", Double.class ,"孔组Z坐标偏移", flag);
        isEmptyBackAndNumber(holeXmlVO::getStartX, holeXmlVO::setStartX,  Double.class ,"小板孔起点坐标X", flag);
        isEmptyBackAndNumber(holeXmlVO::getStartY, holeXmlVO::setStartY,  Double.class ,"小板孔起点坐标Y", flag);
        isEmptyBackAndNumber(holeXmlVO::getStartZ, holeXmlVO::setStartZ,  Double.class ,"小板孔起点坐标Z", flag);
        isEmptyBackAndNumber(holeXmlVO::getEndX, holeXmlVO::setEndX,  Double.class ,"小板孔终点坐标X", flag);
        isEmptyBackAndNumber(holeXmlVO::getEndY, holeXmlVO::setEndY,  Double.class ,"小板孔终点坐标Y", flag);
        isEmptyBackAndNumber(holeXmlVO::getEndZ, holeXmlVO::setEndZ,  Double.class ,"小板孔终点坐标Z", flag);
        notEmptyPositiveNumber(holeXmlVO::getToolStartRotateX, holeXmlVO::setToolStartRotateX, "小板孔起点旋转角度X", Double.class, flag);
        notEmptyPositiveNumber(holeXmlVO::getToolStartRotateY, holeXmlVO::setToolStartRotateY, "小板孔起点旋转角度Y", Double.class, flag);
        notEmptyPositiveNumber(holeXmlVO::getToolStartRotateZ, holeXmlVO::setToolStartRotateZ, "小板孔起点旋转角度Z", Double.class, flag);
        notEmptyPositiveNumber(holeXmlVO::getToolEndRotateX, holeXmlVO::setToolEndRotateX, "小板孔终点旋转角度X", Double.class, flag);
        notEmptyPositiveNumber(holeXmlVO::getToolEndRotateY, holeXmlVO::setToolEndRotateY, "小板孔终点旋转角度Y", Double.class, flag);
        notEmptyPositiveNumber(holeXmlVO::getToolEndRotateZ, holeXmlVO::setToolEndRotateZ, "小板孔终点旋转角度Z", Double.class, flag);

    }

    private void checkGrooves(GrooveXmlVOS grooveXmlVOS, AtomicBoolean flag) {
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCount, grooveXmlVOS::setCount, "0", Double.class, "造型/凹槽数量", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountFaceA, grooveXmlVOS::setCountFaceA, "0", Double.class, "正面造型/凹槽数量", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountFaceB, grooveXmlVOS::setCountFaceB, "0", Double.class, "反面造型/凹槽数量", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountSide, grooveXmlVOS::setCountSide, "0", Double.class, "侧面造型/凹槽数量", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountSideL, grooveXmlVOS::setCountSideL, "0", Double.class, "左侧造型/凹槽数量", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountSideR, grooveXmlVOS::setCountSideR, "0", Double.class, "右侧造型/凹槽数量", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountSideU, grooveXmlVOS::setCountSideU, "0", Double.class, "上侧造型/凹槽数量", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountSideD, grooveXmlVOS::setCountSideD, "0", Double.class, "下侧造型/凹槽数量", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountBevelled, grooveXmlVOS::setCountBevelled, "0", Double.class, "斜面造型/凹槽数量", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountRectangle, grooveXmlVOS::setCountRectangle, "0", Double.class, "矩形凹槽数量", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountThrough, grooveXmlVOS::setCountThrough, "0", Double.class, "挖穿造型/凹槽数量", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCount2V, grooveXmlVOS::setCount2V, "0", Double.class, "矩形凹槽数量", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVOS::getCount3D, grooveXmlVOS::setCount3D, "0", Double.class, "三维刀路(浮雕)数量", flag);


        if (grooveXmlVOS.getGrooveXmlVOList() != null && grooveXmlVOS.getGrooveXmlVOList().size() > 0) {
            for (GrooveXmlVO grooveXmlVO : grooveXmlVOS.getGrooveXmlVOList()) {
                checkGroove(grooveXmlVO, flag);
            }
        }
    }

    private void checkGroove(GrooveXmlVO grooveXmlVO, AtomicBoolean flag) {
        isEmptyAndBack(grooveXmlVO::getId, "凹槽信息ID", grooveXmlVO::setId, flag);

        // 父孤岛id
        isEmptyAndBack(grooveXmlVO::getType, "槽类型数据", grooveXmlVO::setType, flag);
        isEmptyBackAndInvalid(grooveXmlVO::getFace, grooveXmlVO::setFace, DictTypeConstants.HOLE_FACE, "槽加工面数据", flag);

        if (grooveXmlVO.getType().trim().equals("矩形槽")) {
            isEmptyAndBack(grooveXmlVO::getWidth, "当槽为矩形时，槽宽度", grooveXmlVO::setWidth, flag);
        }

        isEmptyAddAndPositiveNumber(grooveXmlVO::getWidth, grooveXmlVO::setWidth, "0", Double.class, "槽宽度", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVO::getLength, grooveXmlVO::setLength, "0", Double.class, "槽长度", flag);
        isEmptyBackAndPositiveNumber(grooveXmlVO::getDepth, "槽深度", grooveXmlVO::setDepth, Double.class, flag);
        isEmptyAddAndPositiveNumber(grooveXmlVO::getWidthExtend, grooveXmlVO::setWidthExtend, "0", Double.class, "槽宽度延长", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVO::getLengthExtend, grooveXmlVO::setLengthExtend, "0", Double.class, "槽长度延长", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVO::getDepthExtend, grooveXmlVO::setDepthExtend, "0", Double.class, "槽深度延长", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVO::getDirection, grooveXmlVO::setDirection, "0", Double.class, "造型/凹槽(边缘)的刀路方向", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVO::getMode, grooveXmlVO::setMode, "0", Double.class, "加工模式/方式", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVO::getRound, grooveXmlVO::setRound, "0", Double.class, "圆角半径", flag);

        if (grooveXmlVO.getType().trim().equals("路径槽") || grooveXmlVO.getType().trim().equals("折返路径槽")) {
            isEmptyAndBack(grooveXmlVO::getToolDiameter, "当槽为路径槽或是折返路径槽时，刀直径", grooveXmlVO::setToolDiameter, flag);

        }
        notEmptyPositiveNumber(grooveXmlVO::getToolDiameter, grooveXmlVO::setToolDiameter, "刀直径", Double.class, flag);
        isEmptyAddAndPositiveNumber(grooveXmlVO::getRedundance, grooveXmlVO::setRedundance, "0", Double.class, "刀路冗余量(偏移重叠量)", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVO::getTangentAngle, grooveXmlVO::setTangentAngle, "0", Double.class, "角度(二维刀路V型刀提角/清角用)", flag);
        isEmptyAddAndPositiveNumber(grooveXmlVO::getIsletCount, grooveXmlVO::setIsletCount, "0", Integer.class, "孤岛数量", flag);

        if (grooveXmlVO.getOutlineXmlVO() == null || grooveXmlVO.getOutlineXmlVO().getPointXmlVOList() == null || grooveXmlVO.getOutlineXmlVO().getPointXmlVOList().size() < 1) {
            grooveXmlVO.setResult("---< 原始造型(外)轮廓点阵列表不可为空 >---");
            flag.set(false);
        } else {
            for (PointXmlVO pointXmlVO : grooveXmlVO.getOutlineXmlVO().getPointXmlVOList()) {
                checkPoint(pointXmlVO, flag, "原始造型(外)轮廓");
            }
        }

        if (grooveXmlVO.getPointXmlVOS() == null || grooveXmlVO.getPointXmlVOS().getPointXmlVOList() == null || grooveXmlVO.getPointXmlVOS().getPointXmlVOList().size() < 1) {
            grooveXmlVO.setResult("---< 槽点坐标列表不可为空 >---");
            flag.set(false);
        } else {
            for (PointXmlVO pointXmlVO : grooveXmlVO.getPointXmlVOS().getPointXmlVOList()) {
                checkPoint(pointXmlVO, flag, "刀路点阵");
            }
        }

        if (grooveXmlVO.getOffsetLineXmlVOS() != null && grooveXmlVO.getOffsetLineXmlVOS().getOffsetLineXmlVOList() != null && !grooveXmlVO.getOffsetLineXmlVOS().getOffsetLineXmlVOList().isEmpty()) {
            for (OffsetLineXmlVO offsetLineXmlVO : grooveXmlVO.getOffsetLineXmlVOS().getOffsetLineXmlVOList()) {
                checkOffsetLine(offsetLineXmlVO, flag);
            }
        }
    }

    private void checkOffsetLine(OffsetLineXmlVO offsetLineXmlVO, AtomicBoolean flag) {
        isEmptyBackAndNumber(offsetLineXmlVO::getOffset, offsetLineXmlVO::setOffset, Double.class, "偏移值——正值右偏(外偏)、负值左偏(内偏)", flag);
        isEmptyBackAndPositiveNumber(offsetLineXmlVO::getDepth, "偏移刀路深度", offsetLineXmlVO::setDepth, Double.class, flag);
        isEmptyBackAndPositiveNumber(offsetLineXmlVO::getToolDiameter, "偏移刀路所用刀的直径", offsetLineXmlVO::setToolDiameter, Double.class, flag);
        isEmptyAddAndPositiveNumber(offsetLineXmlVO::getTangentAngle, offsetLineXmlVO::setTangentAngle, "0", Double.class, "角度(二维刀路V型刀提角/清角用)", flag);

    }

    private void checkRawOutline(RawOutlineXmlVO rawOutlineXmlVO, AtomicBoolean flag) {
        boolean index = isEmptyBackAndPositiveNumberAndBack(rawOutlineXmlVO::getCount, "小板坯料(精加工)轮廓点阵列表数量 "+ rawOutlineXmlVO.getCount(), rawOutlineXmlVO::setCount, Integer.class, flag);
        isEmptyBackAndNumber(rawOutlineXmlVO::getReferenceOffsetX, rawOutlineXmlVO::setReferenceOffsetX, Double.class, "相对于成品轮廓，基准点的X坐标偏移量" +rawOutlineXmlVO.getReferenceOffsetX() , flag);
        isEmptyBackAndNumber(rawOutlineXmlVO::getReferenceOffsetY, rawOutlineXmlVO::setReferenceOffsetY, Double.class, "相对于成品轮廓，基准点的Y坐标偏移量" +rawOutlineXmlVO.getReferenceOffsetY() , flag);


        if (rawOutlineXmlVO.getPointXmlVOList() != null && !rawOutlineXmlVO.getPointXmlVOList().isEmpty()) {
            if (index) {
                if (Integer.parseInt(rawOutlineXmlVO.getCount()) != rawOutlineXmlVO.getPointXmlVOList().size()) {
                    rawOutlineXmlVO.setCount("---< 小板坯料(精加工)点阵数量与实际数量不一致 >---");
                    flag.set(false);
                } else {
                    for (PointXmlVO pointXmlVO : rawOutlineXmlVO.getPointXmlVOList()) {
                        checkPointRemoveZ(pointXmlVO, flag, "坯料轮廓信息");
                    }
                }
            }
        }
    }

    private void checkCuttingOutline(CuttingOutlineXmlVO cuttingOutlineXmlVO, AtomicBoolean flag) {
        boolean index = isEmptyBackAndPositiveNumberAndBack(cuttingOutlineXmlVO::getCount, "小板开料轮廓点阵列表数量", cuttingOutlineXmlVO::setCount, Integer.class, flag);
        isEmptyBackAndNumber(cuttingOutlineXmlVO::getReferenceOffsetX, cuttingOutlineXmlVO::setReferenceOffsetX, Double.class, "小板开料轮廓参考点X坐标" , flag);
        isEmptyBackAndNumber(cuttingOutlineXmlVO::getReferenceOffsetY, cuttingOutlineXmlVO::setReferenceOffsetY, Double.class, "小板开料轮廓参考点Y坐标" , flag);


        if (cuttingOutlineXmlVO.getPointXmlVOList() != null && !cuttingOutlineXmlVO.getPointXmlVOList().isEmpty()) {
            if (index) {
                if (Integer.parseInt(cuttingOutlineXmlVO.getCount()) != cuttingOutlineXmlVO.getPointXmlVOList().size()) {
                    cuttingOutlineXmlVO.setCount("---< 小板轮廓点阵数量与实际数量不一致 >---");
                    flag.set(false);
                } else {
                    for (PointXmlVO pointXmlVO : cuttingOutlineXmlVO.getPointXmlVOList()) {
                        checkPointRemoveZ(pointXmlVO, flag, "开料成型轮廓信息");
                    }
                }
            }
        }
    }

    public void checkOutline(OutlineXmlVO outlineXmlVO, AtomicBoolean flag) {
        boolean index = isEmptyBackAndPositiveNumberAndBack(outlineXmlVO::getCount, "小板成品轮廓点阵列表数量", outlineXmlVO::setCount, Integer.class, flag);
        if (outlineXmlVO.getPointXmlVOList() == null && outlineXmlVO.getPointXmlVOList().isEmpty()) {
            outlineXmlVO.setCount("---< 小板轮廓点阵列表不可为空 >---");
            flag.set(false);
            return;
        }
        if (index) {
            if (Integer.parseInt(outlineXmlVO.getCount()) != outlineXmlVO.getPointXmlVOList().size()) {
                outlineXmlVO.setCount("---< 小板轮廓点阵数量与实际数量不一致 >---");
                flag.set(false);
                return;
            }


            for (PointXmlVO pointXmlVO : outlineXmlVO.getPointXmlVOList()) {
                isEmptyBackAndNumber(pointXmlVO::getPointX, pointXmlVO::setPointX, Double.class, "小板起点坐标X", flag);
                isEmptyBackAndNumber(pointXmlVO::getPointY, pointXmlVO::setPointY, Double.class, "小板起点坐标Y", flag);
                isEmptyBackAndNumber(pointXmlVO::getCurvature, pointXmlVO::setCurvature, Double.class, "小板轮廓边圆弧凹凸度", flag);
                isEmptyBackAndNumber(pointXmlVO::getRadius, pointXmlVO::setRadius, Double.class, "小板轮廓边圆弧半径", flag);

                checkEdging(pointXmlVO, flag);
//                    if (!(StringUtils.isEmpty(pointXmlVO.getItemCode()) && StringUtils.isEmpty(pointXmlVO.getEdgingName()) &&
//                            StringUtils.isEmpty(pointXmlVO.getEdgingColor()) && StringUtils.isEmpty(pointXmlVO.getEdgingMaterial()) &&
//                            (StringUtils.isEmpty(pointXmlVO.getEdgingThickness()) || pointXmlVO.getEdgingThickness().trim().equals("0")))) {
//                        if (StringUtils.isEmpty(pointXmlVO.getEdgingName())) {
//                            pointXmlVO.setEdgingName("封边条");
//                        }
//                        if (StringUtils.isEmpty(pointXmlVO.getItemCode())) {
//                            if (StringUtils.isEmpty(pointXmlVO.getEdgingColor()) || StringUtils.isEmpty(pointXmlVO.getEdgingMaterial())) {
//                                pointXmlVO.setItemCode("---< 当封边条没有物料编码时，封边条颜色、材质不可为空 >---");
//                                flag.set(false);
//                            }
//                        }
//                        isEmptyAddAndPositiveNumber(pointXmlVO::getEdgingThickness, pointXmlVO::setEdgingThickness, "0", Double.class, "封边条宽度", flag);
//                        isEmptyAddAndPositiveNumber(pointXmlVO::getEdgingExtend, pointXmlVO::setEdgingExtend, "0", Double.class, "封边条余量(两头各延长)", flag);
//
//                    }

                isEmptyAddAndPositiveNumber(pointXmlVO::getPreMilling, pointXmlVO::setPreMilling, "0", Double.class, "预铣/精修量", flag);
                isEmptyAddAndNumber(pointXmlVO::getScale, pointXmlVO::setScale, "0", Double.class, "延展/收缩量", flag);
                isEmptyAddAndPositiveNumber(pointXmlVO::getCount, pointXmlVO::setCount, "0", Double.class, "单边封边尺寸", flag);
                isEmptyAddAndPositiveNumber(pointXmlVO::getCountUnit, pointXmlVO::setCountUnit, "m", String.class, "封边条长度单位", flag);

            }
        }
    }

    // 板材中封边条的处理
    public void checkEdging(PointXmlVO pointXmlVO, AtomicBoolean flag) {
        if (!(StringUtils.isEmpty(pointXmlVO.getItemCode()) && StringUtils.isEmpty(pointXmlVO.getEdgingName()) &&
                StringUtils.isEmpty(pointXmlVO.getEdgingColor()) && StringUtils.isEmpty(pointXmlVO.getEdgingMaterial()) &&
                (StringUtils.isEmpty(pointXmlVO.getEdgingThickness()) || pointXmlVO.getEdgingThickness().trim().equals("0")))) {
            if (StringUtils.isEmpty(pointXmlVO.getEdgingName())) {
                pointXmlVO.setEdgingName("封边条");
            }
            if (StringUtils.isEmpty(pointXmlVO.getItemCode())) {
                if (StringUtils.isEmpty(pointXmlVO.getEdgingColor()) || StringUtils.isEmpty(pointXmlVO.getEdgingMaterial())) {
                    pointXmlVO.setItemCode("---< 当封边条没有物料编码时，封边条颜色、材质不可为空 >---");
                    flag.set(false);
                }
            }
            isEmptyAddAndPositiveNumber(pointXmlVO::getEdgingThickness, pointXmlVO::setEdgingThickness, "0", Double.class, "封边条宽度", flag);
            isEmptyAddAndPositiveNumber(pointXmlVO::getEdgingExtend, pointXmlVO::setEdgingExtend, "0", Double.class, "封边条余量(两头各延长)", flag);

        }
    }

    // point 验证
    private void checkPointRemoveZ(PointXmlVO pointXmlVO, AtomicBoolean flag, String name) {
        isEmptyBackAndNumber(pointXmlVO::getPointX, pointXmlVO::setPointX, Double.class, name + "起点X坐标", flag);
        isEmptyBackAndNumber(pointXmlVO::getPointY, pointXmlVO::setPointY, Double.class, name + "起点Y坐标", flag);
        isEmptyBackAndNumber(pointXmlVO::getCurvature, pointXmlVO::setCurvature, Double.class, name + "起点圆弧凹凸度", flag);
        isEmptyBackAndNumber(pointXmlVO::getRadius, pointXmlVO::setRadius, Double.class, name + "起点圆弧半径", flag);

    }

    private void checkPoint(PointXmlVO pointXmlVO, AtomicBoolean flag, String name) {
        checkPointRemoveZ(pointXmlVO, flag, name);
        isEmptyBackAndNumber(pointXmlVO::getPointZ, pointXmlVO::setPointZ, Double.class, name + "起点Z坐标", flag);

    }

    // 板件房间、柜体、模块、加工组数据抽取
    public Map<String ,Object> extractPlateDate(PlateXmlVOS plateXmlVOS) {
        Map<String, Object> map = new HashMap<>();
        if (plateXmlVOS.getPlateXmlVOList() == null || plateXmlVOS.getPlateXmlVOList().isEmpty()) {
            return null;
        }
        List<PlateXmlVO> plateXmlVOList = plateXmlVOS.getPlateXmlVOList();
        // 遍历
        for (PlateXmlVO plateXmlVO : plateXmlVOList) {
            if (plateXmlVO.getBlockXmlVOS() == null || plateXmlVO.getBlockXmlVOS().getBlockXmlVOList() == null || plateXmlVO.getBlockXmlVOS().getBlockXmlVOList().isEmpty()) {
                continue;
            }
            List<BlockXmlVO> blockXmlVOList = plateXmlVO.getBlockXmlVOS().getBlockXmlVOList();
            for (BlockXmlVO blockXmlVO : blockXmlVOList) {
                Map<String , String> code = new HashMap<>();
                code.put(ROOM_CODE, blockXmlVO.getRoomCode());
                code.put(BODY_CODE, blockXmlVO.getBoxCode());
                code.put(MODULE_CODE, blockXmlVO.getModuleCode());
                code.put(GROUP_CODE, blockXmlVO.getGroupCodes());
                map.put(blockXmlVO.getProductionCode(), code); // 生产编号
            }
        }
        return map;
    }
}
