EdcQueryManagerImpl.java

package com.mycim.server.wip.manager.impl;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.exception.SystemIllegalArgumentException;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.CollectionUtils;
import com.mycim.framework.utils.lang.collections.MapUtils;
import com.mycim.framework.utils.lang.math.NumberUtils;
import com.mycim.server.base.manager.NamedObjectManager;
import com.mycim.server.ctx.exec.manager.EdcLotContextManager;
import com.mycim.server.edc.manager.DataCollectionRuleManager;
import com.mycim.server.edc.manager.ParameterRuleManager;
import com.mycim.server.edc.manager.ParameterSetManager;
import com.mycim.server.system.manager.ReferenceFileManager;
import com.mycim.server.wip.dao.EdcQueryDAO;
import com.mycim.server.wip.manager.*;
import com.mycim.utils.ChartNamingRule;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.bas.NamedObject;
import com.mycim.valueobject.consts.ActionPointList;
import com.mycim.valueobject.consts.EDCConst;
import com.mycim.valueobject.consts.HoldCodeNames;
import com.mycim.valueobject.consts.ReferenceDetailNames;
import com.mycim.valueobject.edcspc.*;
import com.mycim.valueobject.edcspc.responseModel.ParameterRuleDetailResponse;
import com.mycim.valueobject.edcspc.rule.CollectionRule;
import com.mycim.valueobject.edcspc.rule.CollectionRuleFactory;
import com.mycim.valueobject.edcspc.rule.SpecialRule;
import com.mycim.valueobject.ems.Equipment;
import com.mycim.valueobject.prp.EdcLotContextValue;
import com.mycim.valueobject.sys.ReferenceFileDetail;
import com.mycim.valueobject.wip.BatchLotStore;
import com.mycim.valueobject.wip.Lot;
import com.mycim.valueobject.wip.Unit;
import com.mycim.valueobject.wip.dto.ParameterDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author Johnson.Wang
 * @version 6.0.0
 * @date 2019/9/27
 **/
@Service
@Transactional
public class EdcQueryManagerImpl implements EdcQueryManager {

    @Autowired
    private NamedObjectManager namedObjectManager;

    @Autowired
    private EdcQueryDAO edcQueryDAO;

    @Autowired
    private UnitQueryManager unitQueryManager;

    @Autowired
    private LotQueryManager lotQueryManager;

    @Autowired
    private EdcLotContextManager edcLotContextManager;

    @Autowired
    private ParameterSetManager parameterSetManager;

    @Autowired
    private DataCollectionRuleManager dataCollectionRuleManager;

    @Autowired
    private ParameterRuleManager parameterRuleManager;

    @Autowired
    private OcapQueryManager ocapQueryManager;

    @Autowired
    private DiffBatchQueryManager diffBatchQueryManager;

    @Autowired
    private ReferenceFileManager referenceFileManager;

    @Override
    public double getParamValByCondition(long lotRrn, long operationRrn, long productRrn, long processRrn,
                                         long parameterRrn, String puType) {
        return edcQueryDAO.getParamValByCondition(lotRrn, operationRrn, productRrn, processRrn, parameterRrn, puType);
    }

    @Override
    public List<ParameterSetVersion> getParameterSetWithMonitorLot(Lot lot, Equipment equipment) {
        Long parameterSetRrn = null;
        List parameterSetVersions = null;
        List<BatchLotStore> list = diffBatchQueryManager.getBatchStoreListByLot(lot.getLotRrn());
        if (CollectionUtils.isNotEmpty(list)) {
            for (BatchLotStore bonding : list) {
                Long toLotRrn = bonding.getLotRrn();
                Lot toLot = lotQueryManager.getLot(toLotRrn);
                EdcLotContextValue edcLotContextValue = edcLotContextManager
                        .getEdcLotContextValue(toLot, equipment, ActionPointList.MOVEOUT_KEY);
                if (edcLotContextValue != null && edcLotContextValue.getParameterSetRrn() != null) {
                    if (parameterSetRrn == null) {
                        parameterSetRrn = edcLotContextValue.getParameterSetRrn();
                        parameterSetVersions = parameterSetManager
                                .buildParameterSetInfo(toLot, equipment, ActionPointList.MOVEOUT_KEY);
                    } else if (parameterSetRrn.longValue() != edcLotContextValue.getParameterSetRrn().longValue()) {
                        throw new SystemIllegalArgumentException(
                                Errors.create().content("Batch lots not the same edcplan.").build());
                    }
                }
            }
        }
        return parameterSetVersions;
    }

    /**
     * 获取可用的规则
     *
     * @param unitList
     * @param parameterRrn
     * @return
     */
    @Override
    public CollectionRule getAvailableDataCollectionRule(List<Unit> unitList, Long parameterRrn) {
        List<DataCollectionRule> collectionRules = dataCollectionRuleManager.getDataCollectionRules(parameterRrn);
        Assert.isFalse(collectionRules.size() == 0,
                       Errors.create().key(MessageIdList.RULE_MISSING).content("规则不存在!").build());

        CollectionRule collectionRule = null;
        for (DataCollectionRule dataCollectionRule : collectionRules) {
            collectionRule = new CollectionRuleFactory(dataCollectionRule, unitList).getAndCheckAvailableRule();
            if (collectionRule != null) {
                return collectionRule;
            }
        }

        return null;
    }

    /**
     * 获取可用的规则
     *
     * @param unitList
     * @param parameterRrn
     * @return
     */
    @Override
    public CollectionRule getAvailableDataCollectionRule(Long facilityRrn, Long lotRrn, Map<String, Object> matchMap,
                                                         List<Unit> unitList, Long parameterRrn) {

        List<DataCollectionRule> collectionRules = getDataCollectionRules(matchMap, parameterRrn);

        Long eqptRrn = MapUtils.getLongValue(matchMap, EDCConst.CollectionRuleMatchKey.EQPT_RRN.getMatchKey());
        Long productRrn = MapUtils.getLongValue(matchMap, EDCConst.CollectionRuleMatchKey.PRODUCT_RRN.getMatchKey());

        String remeasureUnitIds = ocapQueryManager.getRemeasureUnitIds(facilityRrn, lotRrn, parameterRrn);

        CollectionRule collectionRule = null;
        boolean newRuleFlag = false;
        String ruleId = "";
        for (DataCollectionRule dataCollectionRule : collectionRules) {
            if (StringUtils.isNotEmpty(remeasureUnitIds)) {
                dataCollectionRule.setRuleId(EDCConst.CollectionRuleEnum.OCAP.toString());
                dataCollectionRule.setCollectionRule(EDCConst.CollectionRuleEnum.OCAP.toString());
                dataCollectionRule.setWaferSample(remeasureUnitIds);
                newRuleFlag = true;
            } else if (StringUtils.equals(EDCConst.CollectionRuleEnum.SEARCHSTEP.toString(),
                                          dataCollectionRule.getCollectionRule())) {
                newRuleFlag = true;
            } else {
                ruleId = dataCollectionRule.getRuleId();
                // 只能是1-25的正整数
                if (NumberUtils.isParsable(ruleId) && !StringUtils.contains(ruleId, ".")) {
                    // ruleId 是数字,使用新规则处理(新规则的处理,实际上是将规则重新构建成special模式的数据结构)
                    int units = NumberUtils.toInt(ruleId);
                    if (units > 0 && units < 26) {
                        newRuleFlag = buildDataCollectionRuleToSpecial(eqptRrn, productRrn, parameterRrn,
                                                                       unitList.size(), units, dataCollectionRule);
                    }
                }
            }

            if (newRuleFlag) {
                collectionRule = new CollectionRuleFactory(dataCollectionRule, unitList).getAndCheckAvailableRule();
                if (collectionRule != null) {
                    return collectionRule;
                }
            }
        }
        return null;
    }


    /**
     * 获取规则
     *
     * @param unitList
     * @param parameterSetRrn
     * @param parameterSetVersion
     * @param parameterRrn
     * @return
     */
    @Override
    public CollectionRule getDataCollectionRule(List<Unit> unitList, Long parameterSetRrn, Integer parameterSetVersion,
                                                Long parameterRrn) {
        List<DataCollectionRule> collectionRules = dataCollectionRuleManager
                .getDataCollectionRules(parameterSetRrn, parameterSetVersion, parameterRrn);

        CollectionRule collectionRule = null;
        for (DataCollectionRule dataCollectionRule : collectionRules) {
            collectionRule = new CollectionRuleFactory(dataCollectionRule, unitList).getDataCollectionRule();
            if (collectionRule != null) {
                return collectionRule;
            }
        }

        return null;
    }

    /**
     * 获取当前参数集当前版本当前参数的数据采集规则
     *
     * @param matchMap
     * @param parameterRrn
     * @return
     */
    @Override
    public List<DataCollectionRule> getDataCollectionRules(Map<String, Object> matchMap, Long parameterRrn) {
        List<DataCollectionRule> dataCollectionRules = dataCollectionRuleManager.getDataCollectionRules(parameterRrn);
        if (dataCollectionRules == null) {
            dataCollectionRules = new ArrayList<>();
        }

        buildId4MatchMap(matchMap);
        for (DataCollectionRule dataCollectionRule : dataCollectionRules) {
            String collectionRule = dataCollectionRule.getCollectionRule();
            if (ParameterRule.ParameterRuleType.SPECIAL.getValue().equals(collectionRule)) {
                WaferSelectionMain mainCondition = new WaferSelectionMain();
                mainCondition.setEqptId(
                        MapUtils.getStringCheckNull(matchMap, EDCConst.CollectionRuleMatchKey.EQPT_ID.getMatchKey()));

                List<ParameterRuleDetailResponse> details = dataCollectionRuleManager
                        .getSpecialRuleDetailByRule(dataCollectionRule.getRuleRrn());
                dataCollectionRule.setRuleDetail(details);
            }
            dataCollectionRule.setCollectionRule(ParameterRule.ParameterRuleType.parseCollectionRule(collectionRule));
        }

        return dataCollectionRules;
    }

    @Override
    public List<Map<String, Object>> getAllDataCollectionPointInfoByDcolRrn(Long dcolRrn) {
        List<Map<String, Object>> result = edcQueryDAO.getAllDataCollectionPointInfoByDcolRrn(dcolRrn);
        if (CollectionUtils.isEmpty(result)) {
            result = Collections.emptyList();
        }
        return result;
    }

    @Override
    public List<Parameter> getLotEdcInfoList(Lot lot, Equipment equipment) {
        List<Parameter> paramList = new ArrayList<Parameter>();

        EdcLotContextValue edcLotContextValue = edcLotContextManager
                .getEdcLotContextValue(lot, equipment, ActionPointList.MOVEOUT_KEY);

        Long parameterSetRrn = edcLotContextValue.getParameterSetRrn();

        if (parameterSetRrn == null || parameterSetRrn.longValue() <= 0) {
            return null;
        }

        //1.获取parameter
        List<ParameterSetVersion> parameterSetVersions = parameterSetManager
                .getActiveParameterSetVersion(parameterSetRrn);

        for (ParameterSetVersion parameterSetVersion : parameterSetVersions) {
            List<Parameter> parameters = (List<Parameter>) parameterSetVersion.getParameters();
            for (Parameter parameter : parameters) {
                Map<String, Object> matchMap = new HashMap<String, Object>();
                matchMap.put(EDCConst.CollectionRuleMatchKey.FACILITY_RRN.getMatchKey(), lot.getFacilityRrn());
                matchMap.put(EDCConst.CollectionRuleMatchKey.EQPT_RRN.getMatchKey(), equipment.getInstanceRrn());
                matchMap.put(EDCConst.CollectionRuleMatchKey.PRODUCT_RRN.getMatchKey(), lot.getProductRrn());
                matchMap.put(EDCConst.CollectionRuleMatchKey.RECIPE_RRN.getMatchKey(), lot.getRecipeLogicalRrn());

                List<Unit> unitsList = unitQueryManager.getUnitList(lot.getLotRrn());

                CollectionRule collectionRule = getAvailableDataCollectionRule(lot.getFacilityRrn(), lot.getLotRrn(),
                                                                               matchMap, unitsList,
                                                                               parameter.getInstanceRrn());

                if (collectionRule != null) {
                    parameter.setSelectedUnitIds(collectionRule.getSelectedUnitIds());
                    parameter.setSelectedUnitPositions(collectionRule.getSelectedUnitPositions());
                }
                paramList.add(parameter);
            }
        }
        return paramList;
    }

    @Override
    public String getChartOwnerHoldCode(List<ParameterDto> parameters) {
        String holdCode = HoldCodeNames.PIE_PIE_ENG;
        if (CollectionUtils.isEmpty(parameters)) {
            return holdCode;
        }
        String parameterId = parameters.get(0).getParameterId();
        String code = ChartNamingRule.getCodeRepresentedAsModule(parameterId);
        String owner = referenceFileManager.getRefValue(ReferenceDetailNames.SPC_CHART_OWNER, code);
        if (StringUtils.isBlank(owner)) {
            return holdCode;
        }

        NamedObject holdCodeNmdObj = namedObjectManager.getNamedObject("$HOLD_CODE", namedObjectManager.getNamedSpace(
                LocalContext.getFacilityRrn(), ObjectList.SUB_TECHNOLOGY), ObjectList.REFERENCE_FILE_KEY);
        if (holdCodeNmdObj == null) { //数据库数据安全校验
            return holdCode;
        }
        long holdCodeRrn = holdCodeNmdObj.getInstanceRrn();
        if (holdCodeRrn <= 0) {//rrn 合法校验
            return holdCode;
        }
        //通过rrn 找到明细
        List<ReferenceFileDetail> referenceFileDetails = referenceFileManager.getRefFileValues(holdCodeRrn);
        if (CollectionUtils.isEmpty(referenceFileDetails)) { //detail 合法校验
            return holdCode;
        }
        //按照需求规则拼接
        String chartOwnerHoldCode = String.format("%s_%s_ENG", owner, owner);

        //找出按照规则设置的 hold code 信息
        ReferenceFileDetail referenceFileDetail = referenceFileDetails.stream()
                                                                      .filter((e) -> StringUtils.equalsIgnoreCase(
                                                                              e.getKey1Value(),
                                                                              chartOwnerHoldCode))
                                                                      .findFirst().orElse(null);
        if (referenceFileDetail == null) {//没有设置 hold code
            return holdCode;
        }

        holdCode = chartOwnerHoldCode;

        return holdCode;
    }

    /**
     * 匹配新规则,返回抽片位置数组
     */
    public String[] getNewRuleSelectedWafer(Long eqptRrn, Long productRrn, Long parameterRrn, int units, int waferQty) {
        String eqptId = namedObjectManager.getInstanceId(eqptRrn);
        String prodId = namedObjectManager.getInstanceId(productRrn);
        String paramId = namedObjectManager.getInstanceId(parameterRrn);

        // param的匹配有点特殊,因为chart的导入创建的parameter id中会在第二位自动添加一个M,
        // 手动在MES中添加的不会有M
        // 所以匹配的时候两种情况都考虑
        String relation = ChartNamingRule.getChartRuleRelationByParameterId(paramId);

        List<NewParameterRule> ruleList = parameterRuleManager.getNewRulesByMatch(eqptId, prodId, relation, units);
        NewParameterRule rule = new NewParameterRule();
        if (CollectionUtils.isNotEmpty(ruleList)) {
            if (ruleList.size() > 0) {
                // 产品是否已优先匹配
                boolean productMatchFlag = false;

                // 设备是否已优先匹配
                boolean eqptMatchFlag = false;
                int prodMaxLen = 0;
                for (NewParameterRule r : ruleList) {
                    if (r.getProductId().length() > prodMaxLen && StringUtils.equals(eqptId, r.getEqptId()) &&
                            !StringUtils.equals("*", r.getProductId())) {
                        rule = r;
                        break;
                    }
                    if (r.getProductId().length() > prodMaxLen && !StringUtils.equals("*", r.getProductId())) {
                        prodMaxLen = r.getProductId().length();
                        rule = r;
                        productMatchFlag = true;
                    }
                    if (StringUtils.equals(eqptId, r.getEqptId())) {
                        if (!productMatchFlag) {
                            rule = r;
                            eqptMatchFlag = true;
                        }
                    }
                    if (!productMatchFlag && !eqptMatchFlag) {
                        rule = r;
                    }
                }

                String selectedWafers = rule.getActuallyChooseWafers(waferQty);
                if (StringUtils.isNotBlank(selectedWafers)) {
                    return StringUtils.split(selectedWafers, ",");
                }
            }
        }
        return new String[0];
    }

    private void buildId4MatchMap(Map<String, Object> matchMap) {
        Long eqptRrn = MapUtils.getLongValue(matchMap, EDCConst.CollectionRuleMatchKey.EQPT_RRN.getMatchKey());
        Long productRrn = MapUtils.getLongValue(matchMap, EDCConst.CollectionRuleMatchKey.PRODUCT_RRN.getMatchKey());
        Long recipeRrn = MapUtils.getLongValue(matchMap, EDCConst.CollectionRuleMatchKey.RECIPE_RRN.getMatchKey());

        matchMap.put(EDCConst.CollectionRuleMatchKey.EQPT_ID.getMatchKey(), namedObjectManager.getInstanceId(eqptRrn));
        matchMap.put(EDCConst.CollectionRuleMatchKey.PRODUCT_ID.getMatchKey(),
                     namedObjectManager.getInstanceId(productRrn));
        matchMap.put(EDCConst.CollectionRuleMatchKey.RECIPE_ID.getMatchKey(),
                     namedObjectManager.getInstanceId(recipeRrn));
    }

    /**
     * 匹配新规则,将新规则数据结构重构为SPECIAL模式
     *
     * @param eqptRrn            机台
     * @param productRrn         批次product
     * @param parameterRrn       chart
     * @param waferQty           批次上的晶圆数
     * @param units              要采集的片数
     * @param dataCollectionRule 参数,参数规则集合 信息
     * @return true 匹配上新规则,false 没有匹配上新规则
     */
    private boolean buildDataCollectionRuleToSpecial(long eqptRrn, long productRrn, long parameterRrn, int waferQty,
                                                     int units, DataCollectionRule dataCollectionRule) {
        String[] selectedWafers = getNewRuleSelectedWafer(eqptRrn, productRrn, parameterRrn, units, waferQty);
        if (selectedWafers != null && selectedWafers.length > 0) {
            List<ParameterRuleDetailResponse> ruleDetailList = buildNewRuleToSpecialRuleDetail(
                    dataCollectionRule.getRuleRrn(), waferQty, selectedWafers, units);
            dataCollectionRule.setRuleDetail(ruleDetailList);
            // 不论之前是什么模式,匹配上后,都重置为SPECIAL模式
            dataCollectionRule.setCollectionRule(ParameterRule.ParameterRuleType.SPECIAL.toString());
            dataCollectionRule.setCollectionRuleSequence(1);

            String waferSample = StringUtils.EMPTY;
            for (int i = 0; i < selectedWafers.length; i++) {
                int waferIndex = Integer.parseInt(selectedWafers[i]);
                waferSample += waferIndex + ",";
            }
            waferSample = StringUtils.removeLastChar(waferSample, ",");
            dataCollectionRule.setWaferSampleByNewParamRule(waferSample);
            return true;
        }
        return false;
    }

    private List<ParameterRuleDetailResponse> buildNewRuleToSpecialRuleDetail(long ruleRrn, int rangeEnd,
                                                                              String[] selectedWafer, int units) {
        ParameterRuleDetailResponse detail = new ParameterRuleDetailResponse();
        detail.setDetailSeq(1);
        detail.setQtyRangeEnd(rangeEnd);
        detail.setQtyRangeStart(1);
        detail.setRuleRrn(ruleRrn);

        String specialSelectedWafer = StringUtils.EMPTY;
        for (int i = 0; i < selectedWafer.length; i++) {
            int waferIndex = Integer.parseInt(selectedWafer[i]);
            if (waferIndex == 1) {
                specialSelectedWafer += SpecialRule.TOP_KEY + ",";
            } else {
                specialSelectedWafer += SpecialRule.TOP_KEY + "+" + (waferIndex - 1) + ",";
            }
        }
        specialSelectedWafer = StringUtils.removeLastChar(specialSelectedWafer, ",");

        detail.setSelectedWafer(specialSelectedWafer);
        detail.setWaferNum(units);

        List<ParameterRuleDetailResponse> list = new ArrayList<ParameterRuleDetailResponse>();
        list.add(detail);
        return list;
    }


}