ProductSaveAction.java

package com.mycim.webapp.actions.product;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.i18n.I18nUtils;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.utils.MiscUtils;
import com.mycim.framework.utils.beans.PropertyUtils;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.MapUtils;
import com.mycim.framework.utils.lang.math.NumberUtils;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.bas.NamedObject;
import com.mycim.valueobject.bas.Relation;
import com.mycim.valueobject.consts.*;
import com.mycim.valueobject.prp.*;
import com.mycim.valueobject.sys.Facility;
import com.mycim.webapp.Constants;
import com.mycim.webapp.WebUtils;
import com.mycim.webapp.actions.PrpSetupAction;
import com.mycim.webapp.forms.ProductInfoForm;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.Override;
import java.util.*;

/**
 * 产品定义
 *
 * @author sandy
 * @version 6.0.0
 * @date 2019/9/5
 **/
public class ProductSaveAction extends PrpSetupAction {

    @Override
    public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        request.setAttribute("PRODUCTSAP", "");
        ProductInfoForm productInfoForm = (ProductInfoForm) form;
        productInfoForm.setDebondOperationId("");
        productInfoForm.setDebondProductId("");
        productInfoForm.setDebondToOperationId("");
        productInfoForm.setOperationSuccess("");
        productInfoForm.setProcessId("");
        productInfoForm.setMaterialId("");
        productInfoForm.setSpecialOperationId("");
        productInfoForm.setSubconOperationId("");
        productInfoForm.setSapphireId("");

        String id = "";
        if ((request.getParameter(Constants.MODIFY_KEY) != null) &&
                request.getParameter(Constants.MODIFY_KEY).equals("Y")) {
            id = productInfoForm.getInstanceId();

        } else if (WebUtils.getParameterBoolean(Constants.NAV_KEY, request)) {
            productInfoForm.setTransId(Constants.CREATE_KEY);
            request.removeAttribute("PRODUCTSAP");
            request.removeAttribute(SessionNames.ITEM_KEY);
            request.removeAttribute("technologys");
            request.removeAttribute("sapphires");
            request.removeAttribute("debondProducts");
            request.removeAttribute("objectType");
            return (mapping.findForward("create"));
        } else {
            id = StringUtils.trimToUpperCase(productInfoForm.getInstanceId());
        }

        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(id, getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn), ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);
        PropertyUtils.copyProperties(productInfoForm, item);

        if (item.getSubproductFlag() != null) {
            if (item.getSubproductFlag().equalsIgnoreCase("1")) {
                productInfoForm.setSubproductFlag("on");
            } else {
                productInfoForm.setSubproductFlag("off");
            }
        } else {
            productInfoForm.setSubproductFlag("off");
        }

        if (StringUtils.isNotBlank(item.getItemOwner())) {
            productInfoForm.setUserId(getInstanceId(new Long(item.getItemOwner())));
        }

        request.setAttribute(SessionNames.ITEM_KEY, item);

        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();
        List<Map<String, String>> materials = new ArrayList<>();
        List<Map<String, Object>> specialSteplList = new ArrayList<>();
        List<Map<String, Object>> subconStepList = new ArrayList<>();

        if (item.getInstanceRrn() <= 0) {
            productInfoForm.setTransId(Constants.CREATE_KEY);

            request.setAttribute("technologys", technologys);
            request.setAttribute("sapphires", sapphires);
            request.setAttribute("debondProducts", debondProducts);
            request.setAttribute("objectType", item.getObjectType());
            productInfoForm.setMaterialList(materials);
            productInfoForm.setSpecialSteplList(specialSteplList);
            productInfoForm.setSubconSteplList(subconStepList);

            return (mapping.findForward("create"));
        }

        //处理是否是从基本信息界面发起的请求,而不是其他 tab
        if (!WebUtils.getParameterBoolean("homePage", request)) {
            productInfoForm.setNpwType(item.getAttribute3());
        }
        //判断NPWproduct 和 普通 product 是否对应菜单
        if ((StringUtils.isBlank(item.getAttribute3()) &&
                StringUtils.equalsIgnoreCase(productInfoForm.getNpwType(), Constants.NPW_TYPE)) ||
                (StringUtils.isBlank(productInfoForm.getNpwType()) &&
                        StringUtils.equalsIgnoreCase(item.getAttribute3(), Constants.NPW_TYPE))) {
            productInfoForm.setInstanceId("");
            request.setAttribute("errorMsgAlert", I18nUtils.getMessage("product.cant_edit_this_menu",
                                                                       "Product:{} not allowed to edit in " + "this " +
                                                                               "menu! ", item.getInstanceId()));
            return init(mapping, form, request, response);
        }

        item.setProductBins(this.getProductBinsByItem(item));
        technologys = this.getProductTechnologysByItem(item);
        item.setProductTechnologys(technologys);
        //reticleGroups = this.getProductReticleGroupsByItem(item);
        //item.setProductReticleGroups(reticleGroups);

        // 根据产品类型清除Bonding, carrier wafer,chip;因为有可能changeProductType之后,没有点击modify之前添加了绑定关系;
        List<String> productTypes = sysService.getRefFileKey(ReferenceDetailNames.MAIN_PRODUCT_TYPE, StringUtils.EMPTY);
        if (productTypes != null && productTypes.contains(item.getObjectType())) {
            productInfoForm.setBondFlag(TRUE);
            sapphires = this.getProductSapphireListByItem(item);
            long wflMouRrn = getInstanceRrn("MOVEOUT_AUTOBONDED_STD", facilityRrn, ObjectList.WFL_KEY);
            setFlowSeqAndDesc(facilityRrn, item, sapphires, wflMouRrn);

            debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
            List<Map<String, Object>> reworkDebond = prpService.getReworkDebondInfo(facilityRrn, debondProducts);
            prpService.sortReworkDebondList(reworkDebond);
            prpService.repeadDebondFilter(reworkDebond);
            wflMouRrn = getInstanceRrn("MOVEOUT_AUTODEBONDED_STD", facilityRrn, ObjectList.WFL_KEY);
            setFlowSeqAndDesc(facilityRrn, item, debondProducts, wflMouRrn);
            //prpService.setFlowSeqANdDescFilterMultiple(facilityRrn, item, debondProducts, wflMouRrn);
            debondProducts.addAll(reworkDebond);
        } else {
            productInfoForm.setBondFlag(FALSE);
            Relation relation = new Relation(item.getInstanceRrn(), null, LinkTypeList.PRODUCT_TO_SAPPHIRES);
            relation.setTransId(Constants.DELETE_KEY);
            relation.setTransPerformedby(LocalContext.getUserId());

            productService.deleteProductRelation(relation);
            relation = new Relation(item.getInstanceRrn(), null, LinkTypeList.PRODUCT_TO_DEBOND);
            relation.setTransPerformedby(LocalContext.getUserId());
            relation.setTransId(Constants.DELETE_KEY);

            productService.deleteProductRelation(relation);

            request.removeAttribute("sapphires");
            request.removeAttribute("debondProducts");
        }

        materials = getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn());
        specialSteplList = getSpecialSteps(item.getInstanceRrn());
        subconStepList = prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn));

        request.setAttribute("initTechnologys", technologys);
        request.setAttribute("technologys", technologys);
        request.setAttribute("sapphires", sapphires);
        request.setAttribute("debondProducts", debondProducts);
        request.setAttribute("objectType", item.getObjectType());

        productInfoForm.setMaterialList(materials);
        productInfoForm.setSpecialSteplList(specialSteplList);
        productInfoForm.setSubconSteplList(subconStepList);
        productInfoForm.setSumLoopCount(prpService.getProductSumLoopCount(item.getInstanceRrn()));
        request.setAttribute(SessionNames.ITEM_KEY, item);
        productInfoForm.setTransId(Constants.MODIFY_KEY);
        return (mapping.findForward("modify"));
    }

    public ActionForward create(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();
        String language = I18nUtils.getCurrentLanguage().toString();
        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Assert.isFalse(StringUtils.isEmpty(theform.getInstanceId()),
                       Errors.create().key(MessageIdList.PRODUCT_EMPTY_ID).content("Product id empty").build());
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        Assert.isFalse(
                getInstanceRrn(theform.getInstanceId(), LocalContext.getFacilityRrn(), ObjectList.PRODUCT_KEY) > 0,
                Errors.create().key(MessageIdList.PRODUCT_INVALID_SAME).content("已存在的ID").build());
        item = (Item) getInstance(item);

        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));
        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));
        item.setRoleRrn(null);
        String userId = theform.getUserId();
        Assert.isTrue(StringUtils.isNotBlank(userId),
                      Errors.create().content("Product Owner can not be empty!").build());
        long userRrn = getInstanceRrn(userId, getNamedSpace(ObjectList.USER_KEY, facilityRrn), ObjectList.USER_KEY);
        Assert.isFalse(userRrn <= 0, Errors.create().key(MessageIdList.USER_MISSING_RRN).content("UserId 不存在").build());
        item.setItemOwner(String.valueOf(userRrn));
        long rrn = 0;

        if (theform.getProductFamilyId() != null && !theform.getProductFamilyId().equalsIgnoreCase("")) {
            rrn = this.getInstanceRrn(theform.getProductFamilyId().toUpperCase(),
                                      this.getNamedSpace(ObjectList.PRODUCTFAMILY_KEY, facilityRrn),
                                      ObjectList.PRODUCTFAMILY_KEY);
            Assert.isFalse(rrn <= 0, Errors.create().content("Product Family").build());
            item.setProductFamilyRrn(new Long(rrn));
        }

        if (!theform.getProductEngineerId().equalsIgnoreCase("")) {
            rrn = this.getInstanceRrn(theform.getProductEngineerId().toUpperCase(),
                                      this.getNamedSpace(ObjectList.USERGROUP_KEY, facilityRrn),
                                      ObjectList.USERGROUP_KEY);
            Assert.isFalse(rrn <= 0, Errors.create().key(MessageIdList.PRODUCT_PRODUCT_ENGINEER_MISSING)
                                           .content("product engineer not find").build());
            item.setProductEngineerRrn(new Long(rrn));
        }
        item.setHoldOnLowYield(theform.getHoldOnLowYield());
        item.setSubproductFlag(MiscUtils.parseCheckBox(theform.getSubproductFlag()));
        item.setStoreUom(theform.getStoreUom());
        item.setTransId(Constants.CREATE_KEY);
        item.setProductBins(new ArrayList());
        // avoid to copy error id
        item.setInstanceId(StringUtils.trimToUpperCase(theform.getInstanceId()));
        item.setProductTechnologys(technologys);
        item.setInstanceDesc(theform.getInstanceDesc());
        item.setObjectType(theform.getObjectType());
        item.setObjectSubtype(theform.getObjectSubtype());
        item.setSumLoopCount(theform.getSumLoopCount());
        item.setAttribute3(theform.getNpwType());
        int row = prpService.getProductFamilyByItem(item);

        if (row > 0) {
            prpService.changeProductFamilyByItem(item);
        }
        for (Iterator iterator = technologys.iterator(); iterator.hasNext(); ) {
            Map temp = (Map) iterator.next();
            ProcessPlanning processPlanning = new ProcessPlanning(MapUtils.getString(temp, "instanceid"),
                                                                  getNamedSpace(ObjectList.WFL_KEY, facilityRrn),
                                                                  ObjectList.WFL_KEY);
            processPlanning = (ProcessPlanning) this.getInstance(processPlanning);
            Map technologyMap2 = new HashMap();
            technologyMap2.put("productrrn", new Long(item.getInstanceRrn()));
            technologyMap2.put("processrrn", new Long(processPlanning.getInstanceRrn()));
            technologyMap2.put("defaultflag", MapUtils.getString(temp, "default"));
            technologyMap2.put("transId", Constants.ADD_KEY);
            technologyMap2.put("transPerformedby", LocalContext.getUserId());
            insertProductTechnology(technologyMap2);
        }
        process(item);
        updateSubTechnologyRelation(theform, item);

        if (item.getSubproductFlag() != null) {
            if (item.getSubproductFlag().equalsIgnoreCase("1")) {
                theform.setSubproductFlag("on");
            } else {
                theform.setSubproductFlag("off");
            }
        } else {
            theform.setSubproductFlag("off");
        }

        theform.setTransId(Constants.MODIFY_KEY);
        //theform.setOperationSuccess("true");
        technologys = this.getProductTechnologysByItem(item);
        request.setAttribute("technologys", technologys); //工艺流程信息
        sapphires = this.getProductSapphireListByItem(item);
        request.setAttribute("sapphires", sapphires);//可用Bonding
        debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        request.setAttribute("debondProducts", debondProducts);//可用Debond
        theform.setInstanceId(item.getInstanceId());
        request.setAttribute(SessionNames.ITEM_KEY, item);
        WebUtils.setSuccessMsg(request);
        return (mapping.findForward("modify"));

    }

    public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();

        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);


        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));

        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));

        item.setTransId(Constants.DELETE_KEY);
        theform.setInstanceId(null);

        // 如果产品做了lot plan或lot history中有记录,则不允许删除产品
        boolean allowDeleteProductFlag = prpService.allowDeleteProduct(item.getInstanceRrn());
        Assert.isTrue(allowDeleteProductFlag,
                      Errors.create().key(MessageIdList.PRODUCT_USE_CANNOT_DELETE).content("产品正在使用,不允许删除").build());
        process(item);

        // 将与产品关联的东西都删除relation
        Relation relation = new Relation(item.getInstanceRrn(), null, null);
        relation.setTransPerformedby(LocalContext.getUserId());
        relation.setTransId(TransactionNames.DELETE_KEY);
        baseService.deleteRelation(relation);
        prpService.deleteProductMaterialRelation(relation);//删除与物料的新表关系
        if (theform.getSubTechnologyRrn() != null && theform.getSubTechnologyRrn() > 0) {
            relation = new Relation(theform.getSubTechnologyRrn(), item.getInstanceRrn(),
                                    LinkTypeList.SUBTECHNOLOGY_PRODUCT_KEY);
            baseService.deleteRelation(relation);
            theform.setSubTechnologyRrn(null);
        }
        //request.setAttribute("deletedFlag", "1");
        ProductInfoForm deleteForm = new ProductInfoForm();
        deleteForm.setNpwType(theform.getNpwType());
        deleteForm.setTransId(Constants.CREATE_KEY);
        request.setAttribute("productInfoForm", deleteForm);
        request.removeAttribute(SessionNames.ITEM_KEY);

        technologys = this.getProductTechnologysByItem(item);
        request.setAttribute("technologys", technologys); //工艺流程信息
        sapphires = this.getProductSapphireListByItem(item);
        request.setAttribute("sapphires", sapphires);//可用Bonding
        debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        request.setAttribute("debondProducts", debondProducts);//可用Debond

        WebUtils.setSuccessMsg(request);
        return mapping.findForward(Constants.MODIFY_KEY);

    }

    public ActionForward addTechnology(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                       HttpServletResponse response) throws Exception {
        ProductInfoForm theform = (ProductInfoForm) form;

        theform.setOperationSuccess("");

        Long facilityRrn = LocalContext.getFacilityRrn();

        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);

        item.setTransPerformedby(LocalContext.getUserId());

        // Do Check
        List technologyList = this.getProductTechnologysByItem(item);
        Assert.isFalse(technologyList.size() > 0,
                       Errors.create().key(MessageIdList.PRODUCT_CANNOT_ADD_PROCESS).content("一个产品只能添加一个流程").build());
        // boolean expression = prpService.checkProductTechnologysPermission(item.getInstanceRrn());  权限check下面代码会check,没有必要重复check
        // Assert.isTrue(expression, Errors.create().key(MessageIdList.PROCESS_NO_PERMISSION_VIEW).content(
        //         "There is a process under the product, but you do not have " + "permission to view").build());

        String id = StringUtils.trimToUpperCase(theform.getProcessId());
        ProcessPlanning processPlanning = new ProcessPlanning(id, getNamedSpace(ObjectList.WFL_KEY, facilityRrn),
                                                              ObjectList.WFL_KEY);

        processPlanning = (ProcessPlanning) this.getInstance(processPlanning);

        Assert.isFalse(processPlanning == null || processPlanning.getInstanceRrn() <= 0,
                       Errors.create().key("process.process_missing").build());

        checkProcessDisabled(processPlanning.getInstanceRrn());

        String processRrns = securityService.getProcessRrnWithPermission(LocalContext.getUserRrn());
        String dataPermissionFlag = LocalContext.get(DATA_PERMISSION_KEY);
        //检查当前用户是否有权限操作该流程
        Assert.isFalse(StringUtils.equals(dataPermissionFlag, "1") &&
                               !StringUtils.contains(processRrns, processPlanning.getInstanceRrn() + ""),
                       Errors.create().key(MessageIdList.PRODUCT_NO_PERMISSION)
                             .content("No permission to add this process!").build());
        //INCOMING类型只能绑定INCOMING类型流程
        if (StringUtils.equalsIgnoreCase("INCOMING", item.getObjectType())) {
            Assert.isTrue(StringUtils.equalsIgnoreCase(item.getObjectType(), processPlanning.getFlagType()),
                          Errors.create().key(MessageIdList.PRODUCT_INCOMINGTYPEBONDERROR)
                                .content("Incoming product can only add incoming process").build());
        } else {
            Assert.isFalse(StringUtils.equalsIgnoreCase("INCOMING", processPlanning.getFlagType()),
                           Errors.create().key(MessageIdList.PRODUCT_NOINCOMINGTYPEBONDERROR)
                                 .content("Can not add incoming process").build());
        }
        //check npw类型是否对应
        Assert.isTrue(StringUtils.equalsIgnoreCase(item.getAttribute3(), processPlanning.getAttribute3()),
                      Errors.create().key(MessageIdList.PRODUCT_CANT_ADD_THIS_PROCESS)
                            .content("This type of process cannot be applied to this product!").build());

        // Do Add Process action
        String defaultFlag = "";

        if (theform.getProcessFlag() != null && StringUtils.equalsIgnoreCase(theform.getProcessFlag(), "on")) {
            defaultFlag = "Y";
        } else {
            defaultFlag = "N";
        }

        ProductAddTechnologyDto productAddTechnologyDto = new ProductAddTechnologyDto();

        productAddTechnologyDto.setProductId(item.getInstanceId());
        productAddTechnologyDto.setProcessId(StringUtils.trimToUpperCase(theform.getProcessId()));
        productAddTechnologyDto.setDefaultFlag(defaultFlag);

        productService.addTechnologyRelation(productAddTechnologyDto);

        Map job = new HashMap();
        job.put("PRODUCT_RRN", item.getInstanceRrn() + "");
        job.put("PROCESS_RRN", processPlanning.getInstanceRrn() + "");
        invokeProcessScheduler(job);

        // Build page data and return to page.
        theform.setTransId("modify");

        // clear search field
        theform.setProcessId(null);
        theform.setProcessFlag(null);
        if (item.getSubproductFlag() != null) {
            if (item.getSubproductFlag().equalsIgnoreCase("1")) {
                theform.setSubproductFlag("on");
            } else {
                theform.setSubproductFlag("off");
            }
        } else {
            theform.setSubproductFlag("off");
        }

        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));

        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));

        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));//物料信息

        technologyList = this.getProductTechnologysByItem(item);
        request.setAttribute("technologys", technologyList); //工艺流程信息

        List sapphires = this.getProductSapphireListByItem(item);
        request.setAttribute("sapphires", sapphires);//可用Bonding

        List debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        request.setAttribute("debondProducts", debondProducts);//可用Debond

        if (checkMultipath(technologyList, item.getInstanceId())) {
            request.setAttribute("multipathFlag", "true");
        }
        WebUtils.setSuccessMsg(request);
        return mapping.findForward(Constants.MODIFY_KEY);
    }

    public ActionForward deleteTechnology(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                          HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();

        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        String del_rrn = request.getParameter("instancerrn");
        technologys = this.getProductTechnologysByItem(item);
        Iterator its = technologys.iterator();

        while (its.hasNext()) {
            HashMap mapp = (HashMap) its.next();
            if (((String) mapp.get("instancerrn")).equalsIgnoreCase(del_rrn)) {

                ProductDeleteTechnologyDto productDeleteTechnologyDto = new ProductDeleteTechnologyDto();

                productDeleteTechnologyDto.setProductRrn(item.getInstanceRrn());
                productDeleteTechnologyDto.setProcessRrn(new Long(del_rrn));
                productDeleteTechnologyDto.setTransPerformedBy(LocalContext.getUserId());

                productService.deleteTechnologyRelation(productDeleteTechnologyDto);

                its.remove();
                break;
            }
        }
        theform.setTransId("modify");

        if (item.getSubproductFlag() != null) {
            if (item.getSubproductFlag().equalsIgnoreCase("1")) {
                theform.setSubproductFlag("on");
            } else {
                theform.setSubproductFlag("off");
            }
        } else {
            theform.setSubproductFlag("off");
        }

        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));//特殊工步
        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));//物料信息
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));//外包加工

        technologys = this.getProductTechnologysByItem(item);
        request.setAttribute("technologys", technologys); //工艺流程信息
        sapphires = this.getProductSapphireListByItem(item);
        request.setAttribute("sapphires", sapphires);//可用Bonding
        debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        request.setAttribute("debondProducts", debondProducts);//可用Debond
        return mapping.findForward(Constants.MODIFY_KEY);
    }

    public ActionForward addMaterial(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                     HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();

        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);

        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        String materialId = StringUtils.trimToUpperCase(theform.getMaterialId());

        Assert.isFalse(StringUtils.isEmpty(materialId),
                       Errors.create().key(MessageIdList.PRODUCT_MATERIALID_IS_EMPTY).content("material id is empty")
                             .build());
        NamedObject material = baseService.getNamedObject(
                new NamedObject(materialId, getNamedSpace(ObjectList.ITEM_KEY, facilityRrn), ObjectList.ITEM_KEY));

        Assert.isFalse(material == null || material.getInstanceRrn() <= 0,
                       Errors.create().key(MessageIdList.PRODUCT_MATERIALID_IS_EMPTY).content("material id is empty")
                             .build());

        String defaultFlag;
        if ("on".equalsIgnoreCase(theform.getMaterialFlag())) {
            defaultFlag = "Y";
        } else {
            defaultFlag = "N";
        }
        material.setTransId(Constants.ADDMEMBER_KEY);
        material.setTransPerformedby(LocalContext.getUserId());

        prpService.addProductAndMaterialRelation(item.getInstanceRrn(), material, defaultFlag);

        theform.setMaterialId("");
        theform.setTransId(Constants.MODIFY_KEY);

        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));//特殊工步
        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));//物料信息
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));//外包加工

        technologys = this.getProductTechnologysByItem(item);
        request.setAttribute("technologys", technologys); //工艺流程信息
        sapphires = this.getProductSapphireListByItem(item);
        request.setAttribute("sapphires", sapphires);//可用Bonding
        debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        request.setAttribute("debondProducts", debondProducts);//可用Debond
        return mapping.findForward(Constants.MODIFY_KEY);
    }

    public ActionForward deleteMaterial(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                        HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();

        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);

        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        long delMaterialRrn = WebUtils.getParameterLong("materialRrn", request);

        if (delMaterialRrn >= 0) {
            Relation relation = new Relation(item.getInstanceRrn(), delMaterialRrn,
                                             LinkTypeList.PRODUCT_TO_MATERIAL_KEY);
            relation.setTransId(Constants.REMOVEMEMBER_KEY);
            relation.setTransPerformedby(LocalContext.getUserId());
            prpService.deleteProductMaterialRelation(relation);
        }

        theform.setTransId(Constants.MODIFY_KEY);

        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));//特殊工步
        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));//物料信息
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));//外包加工

        technologys = this.getProductTechnologysByItem(item);
        request.setAttribute("technologys", technologys); //工艺流程信息
        sapphires = this.getProductSapphireListByItem(item);
        request.setAttribute("sapphires", sapphires);//可用Bonding
        debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        request.setAttribute("debondProducts", debondProducts);//可用Debond
        return mapping.findForward(Constants.MODIFY_KEY);
    }

    public ActionForward addSpecialStep(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                        HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();

        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);

        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        String specialStepId = StringUtils.trimToUpperCase(theform.getSpecialOperationId());
        Assert.isFalse(StringUtils.isEmpty(specialStepId),
                       Errors.create().key(MessageIdList.PRODUCT_STEPID_IS_EMPTY).content("step id is empty").build());

        //Map infoMap = BeanUtils.copyBeanToMap(theform);
        Map<String, Object> infoMap = new HashMap<String, Object>();
        infoMap.put("specialRouteRrn", theform.getSpecialRouteRrn());
        infoMap.put("specialProcessRrn", theform.getSpecialProcessRrn());
        infoMap.put("specialOperationRrn", theform.getSpecialOperationRrn());

        prpService.addProductForSpecialSteps(item.getInstanceRrn(), infoMap);

        theform.setSpecialOperationId(StringUtils.EMPTY);
        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));//特殊工步
        theform.setTransId(Constants.MODIFY_KEY);
        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));//物料信息
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));//外包加工

        technologys = this.getProductTechnologysByItem(item);
        request.setAttribute("technologys", technologys); //工艺流程信息
        sapphires = this.getProductSapphireListByItem(item);
        request.setAttribute("sapphires", sapphires);//可用Bonding
        debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        request.setAttribute("debondProducts", debondProducts);//可用Debond
        return mapping.findForward(Constants.MODIFY_KEY);
    }

    public ActionForward deleteSpecialStep(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                           HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();

        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();

        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);

        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        long delStepRrn = WebUtils.getParameterLong("operationRrn", request);
        if (delStepRrn >= 0) {
            Relation relation = new Relation(item.getInstanceRrn(), delStepRrn,
                                             LinkTypeList.PRODUCT_TO_MATERIAL_MAPPING_KEY);
            baseService.deleteRelation(relation);
        }
        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));//特殊工步
        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));//物料信息
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));//外包加工

        technologys = this.getProductTechnologysByItem(item);
        request.setAttribute("technologys", technologys); //工艺流程信息
        sapphires = this.getProductSapphireListByItem(item);
        request.setAttribute("sapphires", sapphires);//可用Bonding
        debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        request.setAttribute("debondProducts", debondProducts);//可用Debond

        theform.setTransId(Constants.MODIFY_KEY);
        return mapping.findForward(Constants.MODIFY_KEY);
    }

    public ActionForward addSubconStep(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                       HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();

        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);

        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        String subconStepId = StringUtils.trimToUpperCase(theform.getSubconOperationId());
        Assert.isFalse(StringUtils.isEmpty(subconStepId),
                       Errors.create().key(MessageIdList.PRODUCT_STEPID_IS_EMPTY).content("step id empty").build());

        // 获取流程版本号,要和望远镜获取的方式一致!
        int processVer = prpService
                .getLastAvaliableProcessVersion(item.getInstanceRrn(), theform.getSubconProcessRrn());
        boolean isFirstStepInProcess = prpService
                .isFirstStepInProcess(item.getInstanceRrn(), theform.getSubconProcessRrn(), processVer,
                                      theform.getSubconRouteRrn(), theform.getSubconOperationRrn());
        Assert.isFalse(isFirstStepInProcess,
                       Errors.create().key(MessageIdList.PRODUCT_STEPID_CANNOT_BE_FIRSTSTEP).content("工步不能在流程第一步!")
                             .build());

        //Map infoMap = BeanUtils.copyBeanToMap(theform);
        Map<String, Object> infoMap = new HashMap<String, Object>();
        infoMap.put("subconRouteRrn", theform.getSubconRouteRrn());
        infoMap.put("subconProcessRrn", theform.getSubconProcessRrn());
        infoMap.put("subconOperationRrn", theform.getSubconOperationRrn());
        prpService.addProductForSubconStep(item.getInstanceRrn(), infoMap);

        theform.setSubconOperationId(StringUtils.EMPTY);
        theform.setTransId(Constants.MODIFY_KEY);

        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));//特殊工步
        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));//物料信息
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));//外包加工

        technologys = this.getProductTechnologysByItem(item);
        request.setAttribute("technologys", technologys); //工艺流程信息
        sapphires = this.getProductSapphireListByItem(item);
        request.setAttribute("sapphires", sapphires);//可用Bonding
        debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        request.setAttribute("debondProducts", debondProducts);//可用Debond
        return mapping.findForward(Constants.MODIFY_KEY);
    }

    public ActionForward deleteSubconStep(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                          HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();

        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);

        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        long delStepRrn = WebUtils.getParameterLong("operationRrn", request);
        if (delStepRrn >= 0) {
            Relation relation = new Relation(item.getInstanceRrn(), delStepRrn, LinkTypeList.PRODUCT_TO_SUBCON);
            relation.setTransPerformedby(LocalContext.getUserId());
            relation.setTransId(TransactionNames.DELETE_KEY);
            productService.deleteProductRelation(relation);
        }

        theform.setTransId(Constants.MODIFY_KEY);

        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));//特殊工步
        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));//物料信息
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));//外包加工

        technologys = this.getProductTechnologysByItem(item);
        request.setAttribute("technologys", technologys); //工艺流程信息
        sapphires = this.getProductSapphireListByItem(item);
        request.setAttribute("sapphires", sapphires);//可用Bonding
        debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        request.setAttribute("debondProducts", debondProducts);//可用Debond

        return mapping.findForward(Constants.MODIFY_KEY);
    }

    public ActionForward addSapphire(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                     HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();

        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);

        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));

        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));

        Collection showAllProducts;
        String id;
        String linkType = LinkTypeList.PRODUCT_TO_SAPPHIRES;
        long operationRrn;
        long processRrn;
        String flowSeq;
        String operationId;
        String operationDesc;
        String attributeData3;
        String attributeData4;

        showAllProducts = this.getProductSapphireListByItem(item);
        id = StringUtils.trimToUpperCase(request.getParameter("sapphireId"));
        operationRrn = WebUtils.getParameterLong("operationRrn", request);
        operationId = theform.getOperationId();
        flowSeq = theform.getFlowSeq();
        operationDesc = theform.getOperationDesc();
        processRrn = theform.getProcessRrn();
        // attributeData3 存取是否bond的flag for bond step
        if (StringUtils.equalsIgnoreCase(theform.getConsumeFlag(), "on")) {
            attributeData3 = "Y";
        } else {
            attributeData3 = "N";
        }
        // attributeData4 存取是否new lot的flag for bond step
        if (StringUtils.equalsIgnoreCase(theform.getConsumeFlag(), "on") &&
                StringUtils.equalsIgnoreCase(theform.getNewLotFlag(), "on")) {
            attributeData4 = "Y";
        } else {
            attributeData4 = "N";
        }

        Assert.isFalse(StringUtils.isBlank(id) || StringUtils.isBlank(operationId),
                       Errors.create().key(MessageIdList.PRODUCT_PRODUCT_AND_STEP_IS_EMPTY)
                             .content("product id " + "and " + "operation " + "id is " + "empty").build());
        // validate product type for adding
        NamedObject obj = new NamedObject(id, getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                                          ObjectList.PRODUCT_KEY);
        obj = baseService.getNamedObject(obj);
        long bondProductRrn = obj.getInstanceRrn();

        validateLinkProduct(theform, facilityRrn, I18nUtils.getCurrentLanguage().toString(), id, operationId, obj,
                            bondProductRrn);
        String bondingTag = theform.getBondingTag();

        Assert.isFalse(StringUtils.isBlank(bondingTag),
                       Errors.create().key(MessageIdList.BOND_BONDING_TAG_EMPTY)
                             .content("bondingTag is empty!").build());
        item.setTransPerformedby(LocalContext.getUserId());
        boolean addFlag = true;
        if (showAllProducts != null) {
            java.util.Iterator it = showAllProducts.iterator();
            while (it.hasNext()) {
                HashMap map = (HashMap) it.next();
                if (((String) map.get("instanceid")).equalsIgnoreCase(id)) {
                    addFlag = false;
                    break;
                }
            }
        } else {
            showAllProducts = new ArrayList();
        }

        Relation temp = new Relation();
        temp.setFromRrn(item.getInstanceRrn());
        temp.setLinkType(linkType);
        Integer sequenceNumber = baseService.getMaxSeqOfRelation(temp) + 1;

        if (addFlag) {
            Map map = new HashMap();
            map.put("instancerrn", "" + bondProductRrn);
            map.put("instanceid", obj.getInstanceId());
            map.put("instancedesc", obj.getInstanceDesc());
            map.put("stepId", operationId);
            map.put("flowSeq", flowSeq);
            map.put("operationDesc", operationDesc);
            map.put("attributedata3", attributeData3);
            map.put("attributedata4", attributeData4);

            map.put("dedondToStep", theform.getDebondToOperationId());
            // map.put("dedondToFlowSeq", theform.getDebondToFlowSeq());

            Relation relation = new Relation(item.getInstanceRrn(), bondProductRrn, linkType);
            relation.setTransId(TransactionNames.CREATE_KEY);
            relation.setTransPerformedby(LocalContext.getUserId());
            relation.setSequenceNumber(sequenceNumber);
            relation.setAttributedata1("" + operationRrn);// 工步
            relation.setAttributedata2("" + processRrn);// 流程
            relation.setAttributedata3(attributeData3);// 流程
            relation.setAttributedata4(attributeData4);// 流程
            relation.setAttributedata5(StringUtils.trimToUpperCase(bondingTag));
            relation.setLastUpdatedUser(LocalContext.getUserRrn());
            productService.addProductRelation(relation);

            showAllProducts.add(map);
        }

        theform.setTransId("modify");

        theform.setSapphireId(null);
        request.setAttribute("sapphires", showAllProducts);
        theform.setOperationId(null);
        theform.setConsumeFlag(null);
        theform.setNewLotFlag(null);

        init(mapping, theform, request, response);
        return mapping.findForward(Constants.MODIFY_KEY);
    }

    public ActionForward deleteSapphire(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                        HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();

        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);

        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));

        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));



        String linkType = LinkTypeList.PRODUCT_TO_SAPPHIRES;
        Collection showAllProducts;
        String delRrn = WebUtils.getParameter("instancerrn", request);


        showAllProducts = this.getProductSapphireListByItem(item);

        prpService.isAllowDelBondOrDebond(facilityRrn, item.getInstanceId(), I18nUtils.getCurrentLanguage());

        Iterator its = showAllProducts.iterator();
        while (its.hasNext()) {
            HashMap mapp = (HashMap) its.next();
            if (((String) mapp.get("instancerrn")).equalsIgnoreCase(delRrn)) {
                Relation deleteRelation = new Relation(item.getInstanceRrn(), new Long(delRrn), linkType);
                deleteRelation.setTransId(TransactionNames.DELETE_KEY);
                deleteRelation.setTransPerformedby(LocalContext.getUserId());
                deleteRelation.setLastUpdatedUser(LocalContext.getUserRrn());
                productService.deleteProductRelation(deleteRelation);

                its.remove();
                break;
            }
        }
        theform.setTransId("modify");
        init(mapping, theform, request, response);
        return mapping.findForward(Constants.MODIFY_KEY);
    }

    public ActionForward addDebond(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                   HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();

        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);

        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));

        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));

        Collection showAllProducts = new ArrayList();
        String id = StringUtils.EMPTY;
        String linkType = LinkTypeList.PRODUCT_TO_DEBOND;;
        long operationRrn = 0;
        long processRrn = 0;
        String flowSeq = StringUtils.EMPTY;
        String operationId = StringUtils.EMPTY;
        String operationDesc = StringUtils.EMPTY;
        String attributeData3 = StringUtils.EMPTY;
        String attributeData4 = StringUtils.EMPTY;
        String attributeData5 = StringUtils.EMPTY;

        int bondProductCount = prpService.getProductLinkCount(item, LinkTypeList.PRODUCT_TO_SAPPHIRES,theform.getDebondProductId());
        Assert.isTrue(bondProductCount > 0,
                       Errors.create().key(MessageIdList.PRODUCT_NOT_BONDING_PRODUCT)
                             .content("product id " + "not " + "bonding ").build());

        showAllProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);

        id = StringUtils.trimToUpperCase(request.getParameter("debondProductId"));
        operationRrn = WebUtils.getParameterLong("debondOperationRrn", request);
        operationId = theform.getDebondOperationId();
        flowSeq = theform.getDebondFlowSeq();
        operationDesc = theform.getDebondOperationDesc();
        processRrn = theform.getDebondProcessRrn();
        if (theform.getDebondToOperationRrn() != 0) {
            attributeData3 = String.valueOf(theform.getDebondToOperationRrn());
        }
        if (StringUtils.isNotEmpty(theform.getDebondToFlowSeq())) {
            attributeData5 = theform.getDebondToFlowSeq();
        }

        Assert.isFalse(StringUtils.isBlank(id) || StringUtils.isBlank(operationId),
                       Errors.create().key(MessageIdList.PRODUCT_PRODUCT_AND_STEP_IS_EMPTY)
                             .content("product id " + "and " + "operation " + "id is " + "empty").build());
        // validate product type for adding
        NamedObject obj = new NamedObject(id, getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                                          ObjectList.PRODUCT_KEY);
        obj = baseService.getNamedObject(obj);
        long bondProductRrn = obj.getInstanceRrn();

        validateLinkProduct(theform, facilityRrn, I18nUtils.getCurrentLanguage().toString(), id, operationId, obj,
                            bondProductRrn);


        item.setTransPerformedby(LocalContext.getUserId());
        boolean addFlag = true;
        if (showAllProducts != null) {
            java.util.Iterator it = showAllProducts.iterator();
            while (it.hasNext()) {
                HashMap map = (HashMap) it.next();
                if (((String) map.get("instanceid")).equalsIgnoreCase(id)) {
                    addFlag = false;
                    break;
                }
            }
        } else {
            showAllProducts = new ArrayList();
        }

        Relation temp = new Relation();
        temp.setFromRrn(item.getInstanceRrn());
        temp.setLinkType(linkType);
        Integer sequenceNumber = baseService.getMaxSeqOfRelation(temp) + 1;

        if (addFlag) {
            Map map = new HashMap();
            map.put("instancerrn", "" + bondProductRrn);
            map.put("instanceid", obj.getInstanceId());
            map.put("instancedesc", obj.getInstanceDesc());
            map.put("stepId", operationId);
            map.put("flowSeq", flowSeq);
            map.put("operationDesc", operationDesc);
            map.put("attributedata3", attributeData3);
            map.put("attributedata4", attributeData4);
            map.put("attributedata5", attributeData5);

            map.put("dedondToStep", theform.getDebondToOperationId());
            // map.put("dedondToFlowSeq", theform.getDebondToFlowSeq());


            Relation relation = new Relation(item.getInstanceRrn(), bondProductRrn, linkType);
            relation.setTransId(TransactionNames.CREATE_KEY);
            relation.setTransPerformedby(LocalContext.getUserId());
            relation.setSequenceNumber(sequenceNumber);
            relation.setAttributedata1("" + operationRrn);// 工步
            relation.setAttributedata2("" + processRrn);// 流程
            relation.setAttributedata3(attributeData3);// 流程
            relation.setAttributedata4(attributeData4);// 流程
            relation.setAttributedata5(attributeData5);// 流程
            relation.setLastUpdatedUser(LocalContext.getUserRrn());
            productService.addProductRelation(relation);

            showAllProducts.add(map);
        }

        theform.setTransId("modify");

        theform.setDebondProductId(null);
        //request.setAttribute("debondProducts", showAllProducts);
        theform.setDebondOperationId(null);
        theform.setDebondToOperationId(null);
        init(mapping, theform, request, response);
        return mapping.findForward(Constants.MODIFY_KEY);
    }

    public ActionForward deleteDebond(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                      HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();

        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);

        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));

        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));



        String linkType = StringUtils.EMPTY;
        Collection showAllProducts = new ArrayList();
        String delRrn = WebUtils.getParameter("instancerrn", request);

        linkType = LinkTypeList.PRODUCT_TO_DEBOND;
        showAllProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        prpService.isAllowDelBondOrDebond(facilityRrn, item.getInstanceId(), I18nUtils.getCurrentLanguage());

        Iterator its = showAllProducts.iterator();
        while (its.hasNext()) {
            HashMap mapp = (HashMap) its.next();
            if (((String) mapp.get("instancerrn")).equalsIgnoreCase(delRrn)) {
                Relation deleteRelation = new Relation(item.getInstanceRrn(), new Long(delRrn), linkType);
                deleteRelation.setTransId(TransactionNames.DELETE_KEY);
                deleteRelation.setTransPerformedby(LocalContext.getUserId());
                deleteRelation.setLastUpdatedUser(LocalContext.getUserRrn());
                productService.deleteProductRelation(deleteRelation);

                its.remove();
                break;
            }
        }
        theform.setTransId("modify");
        init(mapping, theform, request, response);
        return mapping.findForward(Constants.MODIFY_KEY);
    }

    public ActionForward modify(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();
        String language = I18nUtils.getCurrentLanguage().toString();
        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);
        //获取已经挂载的流程ID
        String id = StringUtils.trimToUpperCase(theform.getTechnology());
        ProcessPlanning processPlanning = new ProcessPlanning(id, getNamedSpace(ObjectList.WFL_KEY, facilityRrn),
                                                              ObjectList.WFL_KEY);
        //获取流程ID对应的产品类型
        processPlanning = (ProcessPlanning) this.getInstance(processPlanning);

        if (processPlanning.getInstanceRrn() > 0) {

            checkProcessDisabled(processPlanning.getInstanceRrn());

            String processRrns = securityService.getProcessRrnWithPermission(LocalContext.getUserRrn());
            String dataPermissionFlag = LocalContext.get(DATA_PERMISSION_KEY);
            //检查当前用户是否有权限操作该流程
            Assert.isFalse(StringUtils.equals(dataPermissionFlag, "1") &&
                                   !StringUtils.contains(processRrns, processPlanning.getInstanceRrn() + ""),
                           Errors.create().key(MessageIdList.PRODUCT_NO_PERMISSION)
                                 .content("No permission to add this process!").build());
            //INCOMING类型只能绑定INCOMING类型流程
            if (StringUtils.equalsIgnoreCase("INCOMING", item.getObjectType())) {
                Assert.isTrue(StringUtils.equalsIgnoreCase(theform.getObjectType(), processPlanning.getFlagType()),
                              Errors.create().key(MessageIdList.PRODUCT_INCOMINGTYPEBONDERROR)
                                    .content("{} process cannot be bound to an incoming type product.")
                                    .args(processPlanning.getFlagType()).build());
            }
            //其他产品类型转换为INCOMING类型需要看是否挂载非INCOMING流程
            else {
                Assert.isFalse(StringUtils.equalsIgnoreCase("INCOMING", theform.getObjectType()) &&
                                       !StringUtils.equalsIgnoreCase("INCOMING", processPlanning.getFlagType()),
                               (Errors.create().key(MessageIdList.PRODUCT_INCOMINGTYPEBONDERROR)
                                      .content("{} process cannot be bound to an " + "incoming type product."))
                                       .args(processPlanning.getFlagType()).build());
            }
        }
        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        item.setRoleRrn(null);
        String userId = theform.getUserId();
        Assert.isTrue(StringUtils.isNotBlank(userId),
                      Errors.create().content("Product Owner can not be empty!").build());
        long userRrn = getInstanceRrn(userId, getNamedSpace(ObjectList.USER_KEY, facilityRrn), ObjectList.USER_KEY);
        Assert.isFalse(userRrn <= 0, Errors.create().key(MessageIdList.USER_MISSING_RRN).content("用户未找到").build());
        item.setItemOwner(String.valueOf(userRrn));

        long rrn = 0;

        if (theform.getProductFamilyId() != null && !theform.getProductFamilyId().equalsIgnoreCase("")) {
            rrn = this.getInstanceRrn(theform.getProductFamilyId().toUpperCase(),
                                      this.getNamedSpace(ObjectList.PRODUCTFAMILY_KEY, facilityRrn),
                                      ObjectList.PRODUCTFAMILY_KEY);
            Assert.isFalse(rrn <= 0, Errors.create().content("Product Family not find").build());
            item.setProductFamilyRrn(new Long(rrn));
        }

        if (!theform.getProductEngineerId().equalsIgnoreCase("")) {
            rrn = this.getInstanceRrn(theform.getProductEngineerId().toUpperCase(),
                                      this.getNamedSpace(ObjectList.USERGROUP_KEY, facilityRrn),
                                      ObjectList.USERGROUP_KEY);

            Assert.isFalse(rrn <= 0, Errors.create().content("Product Engineer Group not find").build());
            item.setProductEngineerRrn(new Long(rrn));
        }
        item.setHoldOnLowYield(theform.getHoldOnLowYield());
        item.setSubproductFlag(MiscUtils.parseCheckBox(theform.getSubproductFlag()));
        item.setStoreUom(theform.getStoreUom());

        deleteProductLink(theform.getObjectType(), item, request);
        theform.setSapphireId(StringUtils.EMPTY);
        theform.setOperationId(StringUtils.EMPTY);
        item.setTransId(Constants.MODIFY_KEY);

        item.setInstanceDesc(theform.getInstanceDesc());
        item.setObjectType(theform.getObjectType());
        item.setObjectSubtype(theform.getObjectSubtype());
        item.setSumLoopCount(theform.getSumLoopCount());
        process(item);
        updateSubTechnologyRelation(theform, item);

        if (item.getSubproductFlag() != null) {
            if (item.getSubproductFlag().equalsIgnoreCase("1")) {
                theform.setSubproductFlag("on");
            } else {
                theform.setSubproductFlag("off");
            }
        } else {
            theform.setSubproductFlag("off");
        }

        theform.setTransId(Constants.MODIFY_KEY);
        //theform.setOperationSuccess("true");
        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));
        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));

        technologys = this.getProductTechnologysByItem(item);
        request.setAttribute("technologys", technologys); //工艺流程信息
        sapphires = this.getProductSapphireListByItem(item);
        request.setAttribute("sapphires", sapphires);//可用Bonding
        debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        request.setAttribute("debondProducts", debondProducts);//可用Debond
        WebUtils.setSuccessMsg(request);
        return mapping.findForward(Constants.MODIFY_KEY);

    }

    public ActionForward changeObjectType(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                          HttpServletResponse response) throws Exception {
        List technologys = new ArrayList();
        List sapphires = new ArrayList();
        List debondProducts = new ArrayList();
        ProductInfoForm theform = (ProductInfoForm) form;
        theform.setOperationSuccess("");
        Long facilityRrn = LocalContext.getFacilityRrn();
        Item item = new Item(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                             ObjectList.PRODUCT_KEY);
        item = (Item) getInstance(item);


        Map technologyMap = new HashMap();
        technologyMap.put("productrrn", new Long(item.getInstanceRrn()));

        Map reticleGroupMap = new HashMap();
        reticleGroupMap.put("productrrn", new Long(item.getInstanceRrn()));

        item.setTransPerformedby(LocalContext.getUserId());

        theform.setMaterialList(getProductAndMaterialRelationForShowByProductRrn(item.getInstanceRrn()));

        theform.setSpecialSteplList(getSpecialSteps(item.getInstanceRrn()));
        theform.setSubconSteplList(prpService.getSubconSteps(item.getInstanceRrn(), new Facility(facilityRrn)));

        List<String> productTypes = sysService.getRefFileKey(ReferenceDetailNames.MAIN_PRODUCT_TYPE, StringUtils.EMPTY);
        if (productTypes != null && productTypes.contains(theform.getObjectType())) {
            theform.setBondFlag(TRUE);
        } else {
            theform.setBondFlag(FALSE);
        }
        if (ObjectList.DUMMY.equals(theform.getObjectType()) && theform.getSumLoopCount() == 0) {
            //dummy类型产品默认可使用次数为1
            theform.setSumLoopCount(1);
        }

        technologys = this.getProductTechnologysByItem(item);
        request.setAttribute("technologys", technologys); //工艺流程信息
        sapphires = this.getProductSapphireListByItem(item);
        request.setAttribute("sapphires", sapphires);//可用Bonding
        debondProducts = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_DEBOND);
        request.setAttribute("debondProducts", debondProducts);//可用Debond

        request.setAttribute(SessionNames.ITEM_KEY, item);

        if (item.getInstanceRrn() <= 0) {
            theform.setTransId(Constants.CREATE_KEY);
            return (mapping.findForward("modify"));
        } else {
            theform.setTransId("modify");
            return (mapping.findForward("modify"));
        }

    }

    public Map<String, Object> getProcess(Map map, HttpServletRequest request) throws Exception {

        String debondProductId = MapUtils.getString(map, "debondProductId");

        Map processInfo = getDefaultProcess(
                getInstanceRrn(debondProductId, LocalContext.getFacilityRrn(), ObjectList.PRODUCT_KEY));

        return processInfo;
    }

    private void updateSubTechnologyRelation(ProductInfoForm theform, Item item) {
        long facilityRrn = LocalContext.getFacilityRrn();
        Relation relation = null;
        if (StringUtils.isNotBlank(theform.getSubTechnologyId())) {
            long subTechnologyRrn = getInstanceRrn(theform.getSubTechnologyId(), facilityRrn,
                                                   ObjectList.SUB_TECHNOLOGY);
            Assert.isFalse(subTechnologyRrn <= 0,
                           Errors.create().key(MessageIdList.SUBTECHNOLOGY_NOT_ID).content("It is not subTechnology!")
                                 .build());
            if (item.getInstanceRrn() <= 0) {
                item.setInstanceRrn(
                        getInstanceRrn(theform.getInstanceId(), LocalContext.getFacilityRrn(), ObjectList.PRODUCT_KEY));
            }
            relation = new Relation(subTechnologyRrn, item.getInstanceRrn(), LinkTypeList.SUBTECHNOLOGY_PRODUCT_KEY);
            relation.setTransPerformedby(LocalContext.getUserId());
            if (theform.getSubTechnologyRrn() == null || theform.getSubTechnologyRrn() <= 0) {
                relation.setTransId(TransactionNames.CREATE_KEY);
                baseService.insertRelation(relation);
            } else if (subTechnologyRrn != theform.getSubTechnologyRrn()) {
                relation.setTransId(TransactionNames.MODIFY_KEY);
                baseService.updateRelationFromRrn(relation);
            }
            theform.setSubTechnologyRrn(relation.getFromRrn());
        } else if (theform.getSubTechnologyRrn() != null && theform.getSubTechnologyRrn() > 0) {
            relation = new Relation(theform.getSubTechnologyRrn(), item.getInstanceRrn(),
                                    LinkTypeList.SUBTECHNOLOGY_PRODUCT_KEY);
            relation.setTransPerformedby(LocalContext.getUserId());
            relation.setTransId(TransactionNames.DELETE_KEY);
            baseService.deleteRelation(relation);
            theform.setSubTechnologyRrn(null);
        }
    }

    private void invokeProcessScheduler(Map job) {
        //todo
        //SchedulerHelper.createProcessScheduler(job);
    }

    private void setFlowSeqAndDesc(Long facilityRrn, Item item, Collection linkProducts,
                                   long wflMouRrn) throws Exception {
        if (linkProducts != null && linkProducts.size() > 0) {
            long flowContextRrn = getInstanceRrn(ContextNames.RESEQUENCE_CONTEXT, facilityRrn, ObjectList.CONTEXT_KEY);
            long descContextRrn = getInstanceRrn(ContextNames.PROCESS_OPERATION_DESC_CONTEXT, facilityRrn,
                                                 ObjectList.CONTEXT_KEY);

            Iterator it = linkProducts.iterator();
            Map conditionMap;
            while (it.hasNext()) {
                Map m = (HashMap) it.next();

                conditionMap = new HashMap();
                conditionMap.put("productRrn", item.getInstanceRrn());
                conditionMap.put("processRrn", MapUtils.getLongValue(m, "attributedata2"));
                conditionMap.put("operationRrn", MapUtils.getLongValue(m, "attributedata1"));
                conditionMap.put("flowContextRrn", flowContextRrn);
                conditionMap.put("descContextRrn", descContextRrn);
                conditionMap.put("wflMouRrn", wflMouRrn);
                conditionMap.put("processVersion",
                                 prpService.getLastProcessVersion(MapUtils.getLongValue(m, "attributedata2")));// 最新激活版本

                String flowSeq = prpService.getFlowSeqForBondOperation(conditionMap);
                String operationDesc = prpService.getOperationDescForBondOperation(conditionMap);
                m.put("flowSeq", flowSeq);
                m.put("operationDesc", operationDesc);
                m.put("dedondToStep", getInstanceId(MapUtils.getLongValue(m, "attributedata3")));
                m.put("dedondToFlowSeq", MapUtils.getString(m, "attributedata5"));
            }
        }
    }

    private void deleteProductLink(String objectType, Item item, HttpServletRequest request) throws Exception {
        // changeObjectType时,需要check是否需要删除产品的类型对应的关联,比如GLASS类型的产品才能绑定carrierWafer和chip, 当类型变成其他的就需要删除
        if (!StringUtils.equalsIgnoreCase(item.getObjectType(), objectType)) {// 改变了类型
            List<String> productTypes = sysService
                    .getRefFileKey(ReferenceDetailNames.MAIN_PRODUCT_TYPE, StringUtils.EMPTY);
            if (productTypes != null && productTypes.contains(item.getObjectType())) {
                Relation relation = new Relation(item.getInstanceRrn(), null, LinkTypeList.PRODUCT_TO_SAPPHIRES);

                relation.setTransId(Constants.DELETE_KEY);
                relation.setTransPerformedby(LocalContext.getUserId());
                productService.deleteProductRelation(relation);

                relation = new Relation(item.getInstanceRrn(), null, LinkTypeList.PRODUCT_TO_DEBOND);

                relation.setTransId(Constants.DELETE_KEY);
                relation.setTransPerformedby(LocalContext.getUserId());
                productService.deleteProductRelation(relation);

                request.removeAttribute("sapphires");
                request.removeAttribute("debondProducts");
            }
        }
    }

    private void validateLinkProduct(ProductInfoForm theform, Long facility, String language, String id,
                                     String operationId, NamedObject obj, long bondProductRrn) throws Exception {
        long operationRrn = getInstanceRrn(operationId, facility, ObjectList.OPERATION_KEY);
        Operation oper = prpService.getOperation(operationRrn);
        Assert.isFalse(StringUtils.equals(oper.getMvouWflId(), "MOVEOUT_AUTODEBONDED_STD") &&
                               StringUtils.isBlank(theform.getDebondToOperationId()),
                       Errors.create().key(MessageIdList.PRODUCT_DEBOND_STEP_IS_EMPTY).content("debond step empty")
                             .build());

        Assert.isTrue(obj != null && obj.getInstanceRrn() > 0,
                      Errors.create().key(MessageIdList.PRODUCT_PRODUCT_MISSING).content("product not find").build());
        // 1. 查询能BONDing的产品类型,只有类表值$$MAIN_PRODUCT_TYPE设置的主产品才能BOND产品
        List<String> mainProductTypes = sysService
                .getRefFileKey(ReferenceDetailNames.MAIN_PRODUCT_TYPE, StringUtils.EMPTY);

        // 2. 看数据库目前产品类型是什么,不能只是看界面,因为界面上有可能是改了之后但是没有保存到数据库
        NamedObject dbObj = new NamedObject(theform.getInstanceId(), getNamedSpace(ObjectList.PRODUCT_KEY, facility),
                                            ObjectList.PRODUCT_KEY);
        dbObj = baseService.getNamedObject(dbObj);

        // 3.如果是glass类型的产品, 只能BOND类表值设置的$$GLASS_BOND_PRODUCT_TYPE的产品类型
        // boolean isBondFlag = validateProductType(language, obj.getObjectType(), mainProductTypes,
        // dbObj.getObjectType());

        boolean isBondFlag = true;
        Assert.isTrue(isBondFlag, Errors.create().key(MessageIdList.PRODUCT_OBJECTTYPE_UPDATE)
                                        .content("此类型产品不能BOND/DEBOND此类型产品 如需绑定 请先修改产品类型!").build());
        // 验证主产品和附产品是否有相同的bond step
        Map defaultProcess = getDefaultProcess(bondProductRrn);
        Assert.isFalse(MapUtils.getBooleanValue(defaultProcess, "noBondProcess"),
                       Errors.create().key(MessageIdList.PRODUCT_PRODUCT_NOT_BOND_PROCESS).content("产品没有绑定流程请检查!")
                             .build());
        long defaultProcessRrn = MapUtils.getLongValue(defaultProcess, "instancerrn");
        String defaultProcessId = MapUtils.getString(defaultProcess, "instanceid");

        Map matchingRules = new HashMap();
        matchingRules.put("productRrn", bondProductRrn);
        matchingRules.put("processRrn", defaultProcessRrn);
        matchingRules.put("qryActiveOrFrozenVersionFlag", 'Y');


        String bondProductId = baseService.getNamedObjectId(bondProductRrn);
        // 获取最新的process 和 context 都 active的version
        ProductSpecInfo productSpecInfo = specService
                .getLatestActivatedProductSpecItemInfo(bondProductRrn, defaultProcessRrn);
        boolean expression = Objects.isNull(productSpecInfo) || productSpecInfo.getProcessVersion() <= 0;
        Assert.isFalse(expression,
                       Errors.create().key(MessageIdList.PRODUCT_HAVA_NOT_AVALIABLE_VERSION).content("没有可用的流程版本!")
                             .build());

        // 暂时只看主线的bond工步,debond不用check是否有相同的step
        List<Long> stepsOfProcess = buildSteps(
                prpService.getWorkFlowTree(defaultProcessRrn, productSpecInfo.getProcessVersion(), matchingRules),
                null);
        Assert.isFalse(StringUtils.equals(oper.getMvouWflId(), "MOVEOUT_AUTOBONDED_STD") &&
                               (!stepsOfProcess.contains(operationRrn)),
                       Errors.create().key(MessageIdList.PRODUCT_PROCESS_HASNOT_STEP).content("产品的流程没有此工步 请检查!")
                             .build());
    }

    private Map<String, Object> getDefaultProcess(long productRrn) throws Exception {
        // instancerrn ---processrrn; instanceid--processid
        Map<String, Object> defaultProcess = new HashMap<String, Object>();
        ArrayList technologys = (ArrayList) prpService.getProductTechnologys(productRrn);
        if (technologys != null && technologys.size() > 0) {
            defaultProcess = (Map<String, Object>) technologys.get(0);
            Iterator it = technologys.iterator();
            while (it.hasNext()) {
                Map<String, Object> technology = (Map<String, Object>) it.next();
                if (StringUtils.equals(MapUtils.getString(technology, "default"), "1")) {
                    defaultProcess = technology;
                    break;
                }
            }
        } else {
            defaultProcess.put("noBondProcess", true);
        }
        return defaultProcess;
    }

    private List<Long> buildSteps(List wflTree, String fliterCondition) throws Exception {
        List<Long> filterSteps = new ArrayList<Long>();
        for (int i = 0; i < wflTree.size(); i++) {
            String[] treeNodes = (String[]) wflTree.get(i);
            if ("1".equals(treeNodes[7])) {
                long operationRrn = NumberUtils.toLong(treeNodes[4], 0);
                Operation oper = prpService.getOperation(operationRrn);
                if (StringUtils.isNotBlank(fliterCondition) &&
                        (!StringUtils.equals(oper.getMvouWflId(), fliterCondition))) {
                    continue;
                }

                filterSteps.add(operationRrn);
            }
        }
        return filterSteps;
    }

    private Boolean checkMultipath(List<Map> technologyList, String productId) {
        Boolean multipathFlag = Boolean.FALSE;
        for (Map map : technologyList) {
            String processId = MapUtils.getString(map, "instanceid");
            Integer processVersion = MapUtils.getInteger(map, "avaliableProcessVersion");
            Long processRrn = MapUtils.getLong(map, "instancerrn");
            List<String> productIds = new ArrayList<>();
            productIds.add(productId);
            multipathFlag = specService.checkMultipath(processId, processRrn, processVersion, productIds);
            if (multipathFlag) {
                break;
            }
        }

        return multipathFlag;
    }
}