EqpMonitorLotPlanAction.java

package com.mycim.webapp.actions.dmmlotplan;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.threadlocal.LocalContext;
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.framework.utils.lang.time.DateUtils;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.bas.NamedObject;
import com.mycim.valueobject.consts.VersionStatus;
import com.mycim.valueobject.npw.NpwConstants;
import com.mycim.valueobject.prp.*;
import com.mycim.valueobject.wip.Lot;
import com.mycim.webapp.Constants;
import com.mycim.webapp.actions.NpwSetupAction;
import com.mycim.webapp.forms.EqpMonitorWorkflowForm;
import com.mycim.workflow.valueobject.WorkflowLinkModel;
import com.mycim.workflow.valueobject.WorkflowStepModel;
import com.mycim.workflow.valueobject.WorkflowTemplateModel;
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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * DMM注册
 *
 * @author yanbing.chen
 * @date 2019/11/19
 * @since 1.8
 **/
public class EqpMonitorLotPlanAction extends NpwSetupAction {

    @Override
    public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        return mapping.findForward("setup");
    }

    public Map getDmmProcessList(EqpMonitorModel dmmModel) {
        String type = dmmModel.getModelType();
        String eqptId = dmmModel.getEquipmentId();
        long facilityRrn = LocalContext.getFacilityRrn();
        List<EqpMonitorModel> list = new ArrayList<>();

        long eqptRrn = getInstanceRrn(eqptId, getNamedSpace(ObjectList.ENTITY_KEY, facilityRrn), ObjectList.ENTITY_KEY,
                                      ObjectList.EQUIPMENT_KEY);
        if (eqptRrn > 0) {
            list = dmmService.getModelListByType(type, eqptRrn);
        }

        List resultList = new ArrayList();
        for (EqpMonitorModel model : list) {
            Map<String, String> map = new HashMap<>();
            map.put("modelRrn", model.getModelRrn() + "");
            map.put("DMMProcessId", model.getInstanceId());
            resultList.add(map);
        }

        Map map = new HashMap();
        map.put("resultInfo", resultList);
        if (resultList.size() == 1) {
            map.put("simple", "true");
        }
        return map;
    }

    public Map getCarrierLotId(Map transMap) {
        Long facilityRrn = LocalContext.getFacilityRrn();
        String carrierId = MapUtils.getString(transMap, "carrierId");
        Long carrierRrn = getInstanceRrn(carrierId, facilityRrn, ObjectList.ENTITY_KEY);
        List<String> lotsId = carrierService.getInUseCarrierLotIdList(carrierRrn);

        Map result = new HashMap();
        result.put("success", "true");
        if (lotsId.size() > 0) {
            result.put("resultInfo", lotsId.get(0));
        } else {
            result.put("resultInfo", "");
        }
        return result;
    }

    public ActionForward noaccount(ActionMapping mapping, EqpMonitorWorkflowForm theform, HttpServletRequest request,
                                   HttpServletResponse response) {
        return mapping.findForward("noaccount");
    }

    public Map getDmmSteps(EqpMonitorWorkflowForm theform) {

        Long modelRrn = theform.getModelRrn();
        List<EqpMonitorStep> list = dmmService.getDmmModelStepsInfo(modelRrn);

        List resultList = new ArrayList();
        for (EqpMonitorStep step : list) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("seq", step.getModelSeq());
            map.put("eqptId", step.getEqptId() == null ? "" : step.getEqptId());
            map.put("slot", step.getSlot() == null ? "" : step.getSlot());
            map.put("recipe", step.getRecipeId() == null ? "" : step.getRecipeId());
            map.put("parameterId", step.getParameterId() == null ? "" : step.getParameterId());
            map.put("formula", step.getCalculateFormula() == null ? "" : step.getCalculateFormula());
            map.put("spec", getLimitString(step.getLowerLimit(), step.getUpperLimit()));
            resultList.add(map);
        }

        Map result = new HashMap();
        result.put("resultInfo", resultList);
        return result;
    }

    public void registerDMM(Map transMap) {
        Long facilityRrn = LocalContext.getFacilityRrn();
        String user = LocalContext.getUserId();
        Long userRrn = LocalContext.getUserRrn();

        String carrierId = MapUtils.getString(transMap, "carrierId");
        Lot lot = lotQueryService.getLotByCarrierId(carrierId, facilityRrn);
        Assert.notNull(lot, Errors.create().key(MessageIdList.CARRIER_CARRIER_UNAVAILABLE)
                                  .content("Carrier is not available!").build());
        List<EqpMonitorLotBonDing> bondingList = dmmLotService.getDmmLotBonding(lot.getLotRrn());
        Assert.isFalse(bondingList.size() > 0, Errors.create().key(MessageIdList.LOT_USED_COMPANION_LOT).content(
                "The lot has been used as a companion lot and " + "cannot be registered.").build());
        String processId = MapUtils.getString(transMap, "dmmProcessId");
        String eqptId = MapUtils.getString(transMap, "eqptId");

        long eqptRrn = getInstanceRrn(eqptId, facilityRrn, ObjectList.ENTITY_KEY);
        Assert.isFalse(eqptRrn < 0,
                       Errors.create().key(MessageIdList.EQUIPMENT_ID_NOT_EXIST).content("Equipment ID does not exist!")
                             .build());

        long processRrn = getInstanceRrn(processId, facilityRrn, ObjectList.WFL_KEY);
        Assert.isFalse(processRrn <= 0,
                       Errors.create().key(MessageIdList.PROCESS_PROCESS_NOT_SELECTED).content("Process not selected!")
                             .build());

        String seqs = MapUtils.getString(transMap, "seqs");
        Assert.isFalse(StringUtils.isBlank(seqs),
                       Errors.create().key(MessageIdList.PROCESS_CANNOT_REGISTER_EMPTY_PROCESS)
                             .content("Cannot register an empty process!").build());

        validateRegisted(lot);

        Long modelRrn = NumberUtils.toLong(MapUtils.getString(transMap, "modelRrn"));

        EqpMonitorModel dmmModel = dmmService.getDMMModelByRrn(modelRrn);
        int version = dmmModel.getWorkflowVersion();

        Map<Long, EqpMonitorStep> stepMap = new HashMap<Long, EqpMonitorStep>();
        List<EqpMonitorStep> stepList = dmmService.getDmmModelStepsInfo(modelRrn);
        for (EqpMonitorStep step : stepList) {
            if (StringUtils.contains(seqs, step.getModelSeq() + "")) {
                stepMap.put(step.getWorkflowStepRrn(), step);
            }
        }

        Map<String, Object> condition = new HashMap<String, Object>();
        condition.put("user", user);
        condition.put("userRrn", userRrn);
        condition.put("facilityRrn", facilityRrn);
        condition.put("eqptId", eqptId);
        condition.put("stepMap", stepMap);

        dmmService.dmmRegister(lot, processRrn, version, condition);
    }

    public void registerNoAccount(Map transMap) {
        Long facilityRrn = LocalContext.getFacilityRrn();
        String user = LocalContext.getUserId();
        Long userRrn = LocalContext.getUserRrn();

        String eqptId = MapUtils.getString(transMap, "eqptId");
        long eqptRrn = getInstanceRrn(eqptId, facilityRrn, ObjectList.ENTITY_KEY);
        Assert.isFalse(eqptRrn <= 0,
                       Errors.create().key(MessageIdList.EQUIPMENT_ID_NOT_EXIST).content("Equipment ID does not exist!")
                             .build());

        String carrierId = MapUtils.getString(transMap, "carrierId");

        Lot lot = lotQueryService.getLotByCarrierId(carrierId, facilityRrn);
        Assert.notNull(lot, Errors.create().key(MessageIdList.CARRIER_CARRIER_UNAVAILABLE)
                                  .content("Carrier is not available!").build());
        List<EqpMonitorLotBonDing> bondingList = dmmLotService.getDmmLotBonding(lot.getLotRrn());
        Assert.isFalse(bondingList.size() > 0, Errors.create().key(MessageIdList.LOT_USED_COMPANION_LOT).content(
                "The lot has been used as a companion lot and " + "cannot be registered.").build());

        validateRecipe(MapUtils.getString(transMap, "recipe"), facilityRrn);

        validateRegisted(lot);
        EqpMonitorModel model = getNoAccountModel(facilityRrn, user, userRrn);
        Assert.notNull(model, Errors.create().content("初始化信息,稍后请重试").build());

        EqpMonitorStep step = new EqpMonitorStep();
        step.setStepRrn(getInstanceRrn("DMM-NO-ACCOUNT-STEP", facilityRrn, ObjectList.OPERATION_KEY));
        step.setModelRrn(model.getModelRrn());
        step.setModelSeq(1);
        step.setCreatedTime(user);
        step.setEqptId(eqptId);
        step.setSlot(MapUtils.getString(transMap, "slot"));
        step.setRecipeId(MapUtils.getString(transMap, "recipe"));

        List<EqpMonitorStep> stepList = new ArrayList<EqpMonitorStep>();
        stepList.add(step);
        dmmService.modifySteps(model.getModelRrn(), stepList);

        long processRrn = getInstanceRrn("DMM-NO-ACCOUNT-PROCESS", facilityRrn, ObjectList.WFL_KEY);

        Map<String, Object> condition = new HashMap<String, Object>();
        condition.put("user", user);
        condition.put("userRrn", userRrn);
        condition.put("facilityRrn", facilityRrn);
        condition.put("eqptId", eqptId);
        condition.put("noAccountStep", step);

        dmmService.dmmRegister(lot, processRrn, 1, condition);
        model.setModelType(MapUtils.getString(transMap, "modelType"));
        dmmService.updateDMMModel(model);
    }

    public ActionForward searchRegistLotsPage(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                              HttpServletResponse response) throws Exception {
        return mapping.findForward("searchRegistLots");
    }

    public Map searchRegistLots(ActionMapping mapping, EqpMonitorWorkflowForm theform, HttpServletRequest request,
                                HttpServletResponse response) {
        Long facilityRrn = LocalContext.getFacilityRrn();

        String eqptId = request.getParameter("eqptId");
        String dmmProcessId = request.getParameter("dmmProcessId");
        String carrierId = request.getParameter("carrierId");
        long objectRrn = getInstanceRrn(eqptId, getNamedSpace("ENTITY", facilityRrn), "ENTITY");
        Assert.isFalse(StringUtils.isNotBlank(eqptId) && objectRrn <= 0,
                       Errors.create().key(MessageIdList.EQUIPMENT_ID_NOT_EXIST).content("EQP ID is not exist!")
                             .build());

        long dmmProcessRrn = getInstanceRrn(dmmProcessId, facilityRrn, ObjectList.WFL_KEY);
        Assert.isFalse(StringUtils.isNotBlank(dmmProcessId) && dmmProcessRrn <= 0,
                       Errors.create().key(MessageIdList.DMMLOTPLAN_PROCESSID_NOT_CORRECT)
                             .content("Process Id not " + "correct").build());

        Long lotRrn = null;
        Lot lot = lotQueryService.getLotByCarrierId(carrierId, facilityRrn);
        if (lot != null) {
            lotRrn = lot.getLotRrn();
        }
        Assert.isFalse(StringUtils.isNotBlank(carrierId) && lotRrn == null,
                       Errors.create().key(MessageIdList.CARRIER_CASSETTE_ID_MISSING).content("No such Cassette ID!")
                             .build());

        List list = dmmLotService.getDMMLotSpecialStepsList(dmmProcessRrn, lotRrn, objectRrn);

        Map json = new HashMap();
        json.put("success", 1);
        json.put("results", list);
        return json;
    }

    private void validateRegisted(Lot lot) {

        EqpMonitorLotSpecialStep step = dmmLotService.getDMMLotSpecialStep(lot.getLotRrn());
        Assert.isFalse(step != null, Errors.create().key(MessageIdList.LOT_HAS_BEEN_REGISTERED)
                                           .content("The lot has been registered!").build());

        Assert.isFalse(dmmLotService.checkLotUseCount(lot.getLotRrn()),
                       Errors.create().key(MessageIdList.LOT_NOT_ENOUGH_TO_REGISTER)
                             .content("Not enough times to register").build());
    }

    private void validateRecipe(String recipeStr, Long facilityRrn) {
        String[] recipes = StringUtils.split(recipeStr, ",");
        for (String recipe : recipes) {
            long recipeRrn = getInstanceRrn(recipe, facilityRrn, ObjectList.RECIPE_KEY);
            Assert.isFalse(recipeRrn <= 0, Errors.create().content("recipe:{} 未定义").args(recipe).build());
        }

    }

    private EqpMonitorModel getNoAccountModel(Long facilityRrn, String user, Long userRrn) {
        String routeId = "DMM-NO-ACCOUNT-ROUTE";
        String namedSpace = getNamedSpace(ObjectList.WFL_KEY, facilityRrn);

        long routeRrn = getInstanceRrn(routeId, facilityRrn, ObjectList.WFL_KEY);
        if (routeRrn <= 0) {
            routeRrn = buildNoAccountProcess(facilityRrn, namedSpace, user, userRrn);
            return null;
        }

        EqpMonitorModel model = new EqpMonitorModel();
        model.setWorkflowRrn(routeRrn);
        model.setWorkflowVersion(1);
        model.setStatus(VersionStatus.ACTIVE_KEY);
        model.setCreatedUserId(user);
        model.setModelRrn(dmmService.insertDMMModel(model));
        return model;
    }

    private Long buildNoAccountProcess(Long facilityRrn, String namedSpace, String user, Long userRrn) {
        String processId = "DMM-NO-ACCOUNT-PROCESS";
        String routeId = "DMM-NO-ACCOUNT-ROUTE";
        String operationId = "DMM-NO-ACCOUNT-STEP";
        String operationEndId = "DMM-NO-ACCOUNT-STEP-END";

        // step-1 insert process
        ProcessPlanning processPlanning = new ProcessPlanning(processId, namedSpace, ObjectList.WFL_KEY);
        processPlanning.setObjectType(ObjectList.ROUTE_KEY);
        processPlanning.setObjectSubtype(ObjectList.PROCESS_KEY);
        processPlanning.setTransId(Constants.CREATE_KEY);
        processPlanning.setFlagType("DUMMY");
        processPlanning.setTransPerformedby("System");

        long processRrn = prpService.insertProcessPlanning(processPlanning);

        baseService.updateNamedObjectSystemUesd(processRrn, "1");
        processPlanning.setInstanceRrn(processRrn);
        processPlanning.setCurrentVersion(0);

        // step-2 insert route
        Route route = new Route(routeId, namedSpace, ObjectList.WFL_KEY);
        route.setObjectType(ObjectList.ROUTE_KEY);
        route.setObjectSubtype(ObjectList.PROCEDURE_KEY);
        route.setTransId(Constants.CREATE_KEY);
        route.setTransPerformedby("System");

        long routeRrn = prpService.insertRoute(route);
        baseService.updateNamedObjectSystemUesd(routeRrn, "1");
        route.setInstanceRrn(routeRrn);
        route.setCurrentVersion(0);

        // step-3 insert operations
        // 3-1 insert normal operation
        Operation operation = new Operation(operationId, namedSpace, ObjectList.OPERATION_KEY);
        operation.setObjectType("DUMMY");
        operation.setTransPerformedby(user);
        operation.setTransId(Constants.CREATE_KEY);
        operation.setUnitOfMeasure1("WAFER");
        operation.setMvinWflId(NpwConstants.MOVEIN_STD);
        operation.setMvinWflRrn(this.getInstanceRrn(NpwConstants.MOVEIN_STD, facilityRrn, ObjectList.WFL_KEY));
        operation.setMvouWflId(NpwConstants.MOVEOUT_STD);
        operation.setMvouWflRrn(this.getInstanceRrn(NpwConstants.MOVEOUT_STD, facilityRrn, ObjectList.WFL_KEY));
        operation.setWsMvinWflId(NpwConstants.MOVEIN_NPW_STD);
        operation.setWsMvinWflRrn(this.getInstanceRrn(NpwConstants.MOVEIN_NPW_STD, facilityRrn, ObjectList.WFL_KEY));
        operation.setWsMvouWflId(NpwConstants.MOVEOUT_NPW_STD);
        operation.setWsMvouWflRrn(this.getInstanceRrn(NpwConstants.MOVEOUT_NPW_STD, facilityRrn, ObjectList.WFL_KEY));
        operation.setTrackUnitFlag("on");
        operation.setKeepUnitHistoryFlag("on");
        operation.setEdcWaferFlag("on");
        //        operation.setMoveInRequired("on");

        long operationRrn = prpService.insertOperation(operation);
        baseService.updateNamedObjectSystemUesd(operationRrn, "1");
        operation.setInstanceRrn(operationRrn);

        // 3-2 insert end operation(eap system need this operation)
        Operation operationEnd = new Operation(operationEndId, namedSpace, ObjectList.OPERATION_KEY);
        operationEnd.setObjectType("DUMMY");
        operationEnd.setTransPerformedby(user);
        operationEnd.setTransId(Constants.CREATE_KEY);
        operationEnd.setUnitOfMeasure1("WAFER");
        operationEnd.setMvinWflId(NpwConstants.MOVEIN_STD);
        operationEnd.setMvinWflRrn(this.getInstanceRrn(NpwConstants.MOVEIN_STD, facilityRrn, ObjectList.WFL_KEY));
        operationEnd.setMvouWflId(NpwConstants.MOVEOUT_STD);
        operationEnd.setMvouWflRrn(this.getInstanceRrn(NpwConstants.MOVEOUT_STD, facilityRrn, ObjectList.WFL_KEY));
        operationEnd.setWsMvinWflId(NpwConstants.MOVEIN_NPW_STD);
        operationEnd.setWsMvinWflRrn(this.getInstanceRrn(NpwConstants.MOVEIN_NPW_STD, facilityRrn, ObjectList.WFL_KEY));
        operationEnd.setWsMvouWflId(NpwConstants.MOVEOUT_NPW_STD);
        operationEnd
                .setWsMvouWflRrn(this.getInstanceRrn(NpwConstants.MOVEOUT_NPW_STD, facilityRrn, ObjectList.WFL_KEY));
        operationEnd.setTrackUnitFlag("on");
        operationEnd.setKeepUnitHistoryFlag("on");
        operationEnd.setEdcWaferFlag("on");
        //        operationEnd.setMoveInRequired("on");

        long operationEndRrn = prpService.insertOperation(operationEnd);
        baseService.updateNamedObjectSystemUesd(operationEndRrn, "1");
        operationEnd.setInstanceRrn(operationEndRrn);


        // step-4 new version
        Ecn ecn = ecnService.generateUnFrozenEcnForProcessPlan(userRrn);
        ProcessVersion processVersion = new ProcessVersion();
        processVersion.copyNamedObject(processPlanning);
        processVersion.setInstanceVersion(processPlanning.getCurrentVersion().intValue() + 1);
        processVersion.setVersionId(processPlanning.getCurrentVersion().intValue() + 1 + "");
        processVersion.setVersionDesc("Automatic schema generation");
        processVersion.setTransId(Constants.CREATE_KEY);
        processVersion.setTransPerformedby(user);
        processVersion.setEcnRrn(ecn.getInstanceRrn());
        processVersion.setEffectiveDateFrom(DateUtils.stringToTimestamp(ecn.getEffectiveDateFrom()));
        processVersion.setEffectiveDateTo(DateUtils.stringToTimestamp(ecn.getEffectiveDateTo()));
        prpService.insertProcessVersion(processVersion);

        RouteVersion routeVersion = new RouteVersion();
        routeVersion.copyNamedObject(route);
        routeVersion.setInstanceVersion(route.getCurrentVersion().intValue() + 1);
        routeVersion.setVersionId(route.getCurrentVersion().intValue() + 1 + "");
        routeVersion.setVersionDesc("Automatic schema generation");
        routeVersion.setTransId(Constants.CREATE_KEY);
        routeVersion.setTransPerformedby(user);
        routeVersion.setEcnRrn(ecn.getInstanceRrn());
        routeVersion.setEffectiveDateFrom(DateUtils.stringToTimestamp(ecn.getEffectiveDateFrom()));
        routeVersion.setEffectiveDateTo(DateUtils.stringToTimestamp(ecn.getEffectiveDateTo()));
        prpService.insertRouteVersion(routeVersion);

        // step-5 build link
        // 5-1 build route workflow link
        List<NamedObject> operationList = new ArrayList<NamedObject>();
        operationList.add(operation);
        operationList.add(operationEnd);
        List<WorkflowStepModel> operationStepModels = dmmService.buildStepModel(routeRrn, 1, operationList, "route");
        List<WorkflowLinkModel> operationLinkModels = buildWorkflowLinkModel(operationStepModels, operationList);
        WorkflowTemplateModel operationTemplateModel = buildTemplateModel(routeRrn, 1, operationStepModels);
        dmmService.importWorkflowModel(operationTemplateModel, operationStepModels, new ArrayList<WorkflowStepModel>(),
                                       operationLinkModels, new ArrayList<WorkflowLinkModel>());

        // 5-2 build process workflow link
        List<NamedObject> routeList = new ArrayList<NamedObject>();
        routeList.add(route);
        List<WorkflowStepModel> routeStepModels = dmmService.buildStepModel(processRrn, 1, routeList, "process");
        List<WorkflowLinkModel> routeLinkModels = buildWorkflowLinkModel(routeStepModels, null);
        WorkflowTemplateModel routeTemplateModel = buildTemplateModel(processRrn, 1, routeStepModels);
        dmmService.importWorkflowModel(routeTemplateModel, routeStepModels, new ArrayList<WorkflowStepModel>(),
                                       routeLinkModels, new ArrayList<WorkflowLinkModel>());

        // 6-2 active version
        activateWithProcessScheduler(routeVersion.getEcnRrn(), true);
        activateWithProcessScheduler(processVersion.getEcnRrn(), false);

        // step-7 return routeRrn
        return routeRrn;
    }

    private List<WorkflowLinkModel> buildWorkflowLinkModel(List<WorkflowStepModel> stepModels,
                                                           List<NamedObject> operations) {

        Long startRrn = null;
        Long endRrn = null;
        WorkflowStepModel routeStep = null;
        for (WorkflowStepModel stepModel : stepModels) {
            if (StringUtils.equalsIgnoreCase("Start", stepModel.getStepId())) {
                startRrn = stepModel.getStepRrn();
            } else if (StringUtils.equalsIgnoreCase("End", stepModel.getStepId())) {
                endRrn = stepModel.getStepRrn();
            } else {
                if (operations == null) {
                    routeStep = stepModel;
                }
            }

        }

        List<WorkflowLinkModel> linkModels = new ArrayList<WorkflowLinkModel>();
        if (operations != null) {
            long stepRrn = startRrn.longValue();
            for (int i = 0; i < operations.size(); i++) {
                WorkflowLinkModel linkModel = new WorkflowLinkModel();
                linkModel.setStepRrn(stepRrn);
                for (WorkflowStepModel stepModel : stepModels) {
                    if (StringUtils.equals(stepModel.getStepId(), operations.get(i).getInstanceId())) {
                        linkModel.setNextStepRrn(stepModel.getStepRrn());
                    }
                }
                linkModel.setConditionType("And");
                linkModels.add(linkModel);
                stepRrn = linkModel.getNextStepRrn();
                if (i == operations.size() - 1) {
                    WorkflowLinkModel linkModelEnd = new WorkflowLinkModel();
                    linkModelEnd.setStepRrn(stepRrn);
                    linkModelEnd.setNextStepRrn(endRrn);
                    linkModelEnd.setConditionType("And");
                    linkModels.add(linkModelEnd);
                }
            }
        } else {
            long stepRrn = startRrn.longValue();
            WorkflowLinkModel linkModelStart = new WorkflowLinkModel();
            linkModelStart.setStepRrn(stepRrn);
            linkModelStart.setNextStepRrn(routeStep.getStepRrn());
            linkModelStart.setConditionType("And");

            linkModels.add(linkModelStart);

            WorkflowLinkModel linkModelEnd = new WorkflowLinkModel();
            linkModelEnd.setStepRrn(routeStep.getStepRrn());
            linkModelEnd.setNextStepRrn(endRrn);
            linkModelEnd.setConditionType("And");

            linkModels.add(linkModelEnd);
        }

        return linkModels;
    }

    private WorkflowTemplateModel buildTemplateModel(Long workflowRrn, Integer version,
                                                     List<WorkflowStepModel> stepModels) {
        WorkflowTemplateModel templateModel = new WorkflowTemplateModel(workflowRrn, version);

        Long startRrn = null;
        Long endRrn = null;
        for (WorkflowStepModel stepModel : stepModels) {
            if (StringUtils.equalsIgnoreCase("Start", stepModel.getStepId())) {
                startRrn = stepModel.getStepRrn();
            }
            if (StringUtils.equalsIgnoreCase("End", stepModel.getStepId())) {
                endRrn = stepModel.getStepRrn();
            }
        }

        templateModel.setRootFlag("Y");
        templateModel.setFirstStepRrn(startRrn);
        templateModel.setLastStepRrn(endRrn);
        return templateModel;
    }

}