ProcessLoopAction.java

package com.mycim.webapp.actions.process;

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.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.CollectionUtils;
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.consts.VersionStatus;
import com.mycim.valueobject.prp.ProcessLoopInfo;
import com.mycim.webapp.Constants;
import com.mycim.webapp.TemplateLocation;
import com.mycim.webapp.WebUtils;
import com.mycim.webapp.actions.PrpSetupAction;
import com.mycim.webapp.forms.ProcessLoopForm;
import jxl.Workbook;
import jxl.format.Alignment;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.Colour;
import jxl.write.WritableFont;
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.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class ProcessLoopAction extends PrpSetupAction {

    private static final String ACTION_ADD_LOOP = "addLoop";

    private static final String ACTION_DELETE_LOOP = "deleteLoop";

    private static final String ACTION_SHOW_LOTS_IN_RECYCLE = "showInRecycleLots";

    private static final String ACTION_DELETE_LOT_IN_RECYCLE = "deleteLotRecycleInfo";

    private static final String CN = "CN";

    @Override
    public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                              HttpServletResponse response) {
        ProcessLoopForm processLoopForm = (ProcessLoopForm) form;
        String processId = processLoopForm.getInstanceId();
        int processVersion = Integer.parseInt(processLoopForm.getVersionId());

        Assert.isFalse(StringUtils.isEmpty(processId),
                       Errors.create().key(MessageIdList.PROCESS_INVALID).content("Invalid process id!").build());

        processLoopForm.setProcessLoopInfos(prpService.processLoopInfoList(processId, processVersion));
        processLoopForm.setStartRouteId(StringUtils.EMPTY);
        processLoopForm.setStartOperationId(StringUtils.EMPTY);
        processLoopForm.setEndRouteId(StringUtils.EMPTY);
        processLoopForm.setEndOperationId(StringUtils.EMPTY);
        processLoopForm.setLoopCount(null);

        return mapping.getInputForward();
    }

    public ActionForward addLoop(ActionMapping mapping, ProcessLoopForm form, HttpServletRequest request,
                                 HttpServletResponse response) {
        validateParameter(form);

        long processRrn = getInstanceRrn(form.getInstanceId(), LocalContext.getFacilityRrn(), ObjectList.WFL_KEY);

        long startRoute = getInstanceRrn(form.getStartRouteId(), LocalContext.getFacilityRrn(), ObjectList.WFL_KEY);
        long startStep = getInstanceRrn(form.getStartOperationId(), LocalContext.getFacilityRrn(),
                                        ObjectList.OPERATION_KEY);
        Boolean isFirstStepInProcess = prpService
                .isFirstStepInProcess(null, processRrn, Integer.parseInt(form.getVersionId()), startRoute, startStep);

        Assert.isFalse(isFirstStepInProcess, Errors.create().key(MessageIdList.CYCLE_CANNOT_FIRST_STEP).content(
                "The cycle start step cannot be  the first step in " + "process!").build());
        Assert.isFalse(form.getLoopCount() <= 1, Errors.create().key(MessageIdList.LOOP_COUNT_MUST_GREATER_1).
                content("Loop time must be greater than 1, because the normal process also counts as a loop!").build());

        long endRoute = getInstanceRrn(form.getEndRouteId(), LocalContext.getFacilityRrn(), ObjectList.WFL_KEY);

        long endStep = getInstanceRrn(form.getEndOperationId(), LocalContext.getFacilityRrn(),
                                      ObjectList.OPERATION_KEY);
        isFirstStepInProcess = prpService
                .isFirstStepInProcess(null, processRrn, Integer.parseInt(form.getVersionId()), endRoute, endStep);

        Assert.isFalse(isFirstStepInProcess, Errors.create().key(MessageIdList.CYCLE_CANNOT_FIRST_STEP).content(
                "The cycle end step cannot be  the first step in " + "process!").build());

        //check same and fork
        this.checkSameAndFork(form, processRrn, startRoute, startStep, endRoute, endStep);

        ctxExecService
                .saveProcessLoop(processRrn, Integer.parseInt(form.getVersionId()), startRoute, startStep, endRoute,
                                 endStep, form.getLoopCount(), VersionStatus.ACTIVE_KEY);

        return init(mapping, form, request, response);
    }

    private void checkSameAndFork(ProcessLoopForm form, long processRrn, long startRoute, long startStep, long endRoute, long endStep) {
        String processId = form.getInstanceId();
        int processVersion = Integer.parseInt(form.getVersionId());
        List<ProcessLoopInfo> pls = prpService.processLoopInfoList(processId, processVersion);
        String startFlowSeq = prpService.getFlowSeqContainsAllStatus(processRrn, processVersion, startRoute, startStep);
        Assert.isFalse(StringUtils.isBlank(startFlowSeq), Errors.create().key(MessageIdList.PLEASE_SAVE_FLOW_SEQ_FIRST).content("Please save this version of Flow Seq first!").build());
        String endFlowSeq = prpService.getFlowSeqContainsAllStatus(processRrn, processVersion, endRoute, endStep);
        Assert.isFalse(StringUtils.isBlank(endFlowSeq), Errors.create().key("").content("Please save this version of Flow Seq first!").build());
        if (CollectionUtils.isNotEmpty(pls)){
            long start = NumberUtils.toLong(startFlowSeq), end = NumberUtils.toLong(endFlowSeq);
            for (ProcessLoopInfo pli:pls){
                long oldStart = NumberUtils.toLong(pli.getStartFlowSeq()), oldEnd = NumberUtils.toLong(pli.getEndFlowSeq());
                boolean sameOrFork = start == end || start == oldStart || start == oldEnd
                        || end == oldEnd  || end == oldStart
                        || (start > oldStart && start < oldEnd && end - oldEnd > 0)
                        || (end > oldStart && end < oldEnd && start - oldStart < 0);
                Assert.isFalse(sameOrFork, Errors.create().key(MessageIdList.CANNOT_SAME_AND_CROSS).content("Cannot set the same Start Step or End Step, and cross section!").build());
            }
        }
    }

    public ActionForward showInRecycleLots(ActionMapping mapping, ProcessLoopForm form, HttpServletRequest request,
                                           HttpServletResponse response) {
        form.setProcessLoopInfos(prpService.listLotsInRecycledInfo(form.getInstanceId(),
                                                                   Integer.parseInt(form.getVersionId()),
                                                                   form.getStartRouteId(), form.getStartOperationId(),
                                                                   form.getEndRouteId(), form.getEndOperationId()));
        return mapping.findForward(Constants.MEMBERS_KEY);
    }

    public ActionForward deleteLoop(ActionMapping mapping, ProcessLoopForm form, HttpServletRequest request,
                                    HttpServletResponse response) throws Exception {

        long processRrn = getInstanceRrn(form.getInstanceId(), LocalContext.getFacilityRrn(), ObjectList.WFL_KEY);
        long startRoute = getInstanceRrn(form.getStartRouteId(), LocalContext.getFacilityRrn(), ObjectList.WFL_KEY);
        long startStep = getInstanceRrn(form.getStartOperationId(), LocalContext.getFacilityRrn(),
                                        ObjectList.OPERATION_KEY);
        long endRoute = getInstanceRrn(form.getEndRouteId(), LocalContext.getFacilityRrn(), ObjectList.WFL_KEY);

        long endStep = getInstanceRrn(form.getEndOperationId(), LocalContext.getFacilityRrn(),
                                      ObjectList.OPERATION_KEY);

        prpService.deleteProcessLoop(processRrn, Integer.parseInt(form.getVersionId()), startRoute, startStep, endRoute,
                                     endStep);

        return init(mapping, form, request, response);
    }

    public ActionForward deleteLotRecycleInfo(ActionMapping mapping, ProcessLoopForm form, HttpServletRequest request,
                                              HttpServletResponse response) {
        long objectRrn = WebUtils.getParameterLong("objectRrn", request);

        prpService.deleteLotRecycled(objectRrn);

        return init(mapping, form, request, response);
    }

    public ActionForward export(HttpServletRequest request, ProcessLoopForm theform,
                                HttpServletResponse response) throws Exception {
        List<ProcessLoopInfo> processLoopInfos = prpService
                .processLoopInfoList(theform.getInstanceId(), NumberUtils.toInt(theform.getVersionId()));

        Map<String, Object> titles = WebUtils.getExportTitles(request);
        if (StringUtils.equalsIgnoreCase(CN, I18nUtils.getCurrentLanguage().toString())) {
            titles.put("title", "流程循环设置信息");
            titles.put("startFlowSeqForExport", "开始序号");
            titles.put("endFlowSeqForExport", "结束序号");
        } else {
            titles.put("title", "Process Loop Setup");
        }
        titles.put("titleProcessId", "Process ID:" + theform.getInstanceId());
        titles.put("titleProcessVersion", "Process Ver.:" + theform.getVersionId());
        // 导出
        String exportDateTime = DateUtils.getNowTime(DateUtils.DATE_FORMAT4NOSPLICING);
        String fileName = "ProcessLoopSetup_" + exportDateTime + ".xlsx";
        WebUtils.exportExcel(fileName, titles, processLoopInfos, TemplateLocation.PROCESS_LOOP_SETUP, response);
        return WebUtils.NULLActionForward;
    }

    private void validateParameter(ProcessLoopForm form) {
        Assert.isFalse(StringUtils.isBlank(form.getStartRouteId()),
                       Errors.create().key(MessageIdList.CYCLE_EMPTY_START_SUB_PLAN)
                             .content("The cycle start subPlan " + "cannot be empty!").build());

        Assert.isFalse(StringUtils.isBlank(form.getStartOperationId()),
                       Errors.create().key(MessageIdList.CYCLE_EMPTY_START_STEP)
                             .content("The cycle start step cannot be" + " empty!").build());

        Assert.isFalse(StringUtils.isBlank(form.getEndRouteId()),
                       Errors.create().key(MessageIdList.CYCLE_EMPTY_END_SUB_PLAN)
                             .content("The loop end subPlan cannot be empty!").build());

        Assert.isFalse(StringUtils.isBlank(form.getEndOperationId()),
                       Errors.create().key(MessageIdList.CYCLE_EMPTY_END_PLAN)
                             .content("The loop end step cannot be " + "empty!").build());

        Assert.isFalse(form.getLoopCount() <= 0, Errors.create().key(MessageIdList.CYCLE_EMPTY_NUMBER)
                                                       .content("The number of cycles cannot be empty!").build());

        Assert.isFalse(StringUtils.isBlank(form.getStartRouteSeq()) || StringUtils.isBlank(form.getEndRouteSeq()) ||
                               StringUtils.isBlank(form.getStartOperationSeq()) ||
                               StringUtils.isBlank(form.getEndOperationSeq()),
                       Errors.create().key(MessageIdList.CYCLE_START_LESS_END)
                             .content("The cycle start step must be smaller than the end " + "step!").build());

        //校验开始工步是否小于结束工步
        Assert.isFalse(Long.parseLong(form.getStartRouteSeq() + form.getStartOperationSeq(), 36) >
                               Long.parseLong(form.getEndRouteSeq() + form.getEndOperationSeq(), 36),
                       Errors.create().key(MessageIdList.CYCLE_START_LESS_END)
                             .content("The cycle start step " + "must" + " be smaller than " + "the end step!")
                             .build());
    }

    private OutputStream createWorkBookByLoop(ProcessLoopForm theform, Collection processLoopInfos,
                                              HttpServletRequest request, String language) throws Exception {
        OutputStream os = new ByteArrayOutputStream();
        jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(os);
        String excelTitle = "";
        if (StringUtils.equalsIgnoreCase("CN", language)) {
            excelTitle = "流程循环设置信息";
        } else {
            excelTitle = "Process Loop Setup";
        }

        jxl.write.WritableSheet ws = wwb.createSheet(excelTitle, 0);
        jxl.write.WritableFont wf = new jxl.write.WritableFont(WritableFont.TAHOMA, 20, WritableFont.BOLD, true);
        jxl.write.WritableCellFormat wcfF = new jxl.write.WritableCellFormat(wf);
        wcfF.setAlignment(Alignment.CENTRE);

        ws.mergeCells(0, 0, 10, 0);
        jxl.write.Label labelTitle = new jxl.write.Label(0, 0, excelTitle, wcfF);
        ws.addCell(labelTitle);

        jxl.write.Label labelColes = null;
        jxl.write.WritableFont wfs = new jxl.write.WritableFont(WritableFont.ARIAL, 12, WritableFont.BOLD, false);
        jxl.write.WritableCellFormat wfColes = new jxl.write.WritableCellFormat(wfs);
        wfColes.setAlignment(Alignment.CENTRE);

        labelColes = new jxl.write.Label(2, 3, "Process ID:" + theform.getInstanceId(), wfColes);
        ws.addCell(labelColes);
        labelColes = new jxl.write.Label(6, 3, "Process Ver.:" + theform.getVersionId(), wfColes);
        ws.addCell(labelColes);

        jxl.write.Label labelCols = null;
        jxl.write.WritableCellFormat wfCols = new jxl.write.WritableCellFormat();
        wfCols.setBorder(Border.ALL, BorderLineStyle.THIN, Colour.BLACK);

        String[] columnTitleArray = null;
        if (StringUtils.equalsIgnoreCase("EN", language)) {
            columnTitleArray = new String[]{"No.", "Loop Start Sub Plan", "Start Seq", "Loop Start Step",
                    "Loop End " + "Sub Plan", "End Seq", "Loop End Step", "Loop Count"};
        } else {
            columnTitleArray = new String[]{"序号", "循环开始工序", "开始序号", "循环开始工步", "循环结束工序", "结束序号", "循环结束工步", "循环次数"};
        }

        int j = 0;
        for (int i = 0; i < columnTitleArray.length; i++) {
            ws.setColumnView(i, 15);
            labelCols = new jxl.write.Label(j++, 5, columnTitleArray[i], wfCols);
            ws.addCell(labelCols);
        }

        Iterator it = processLoopInfos.iterator();

        jxl.write.Number numberValue = null;
        jxl.write.Label stringValue = null;

        int i = 6;
        int seq = 1;
        j = 0;

        while (it.hasNext()) {
            ProcessLoopInfo processLoopInfo = (ProcessLoopInfo) it.next();
            numberValue = new jxl.write.Number(j++, i, seq++, wfCols);
            ws.addCell(numberValue);
            stringValue = new jxl.write.Label(j++, i, processLoopInfo.getRouteStartId(), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, processLoopInfo.getStartFlowSeq(), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, processLoopInfo.getOperationStartId(), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, processLoopInfo.getRouteEndId(), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, processLoopInfo.getEndFlowSeq(), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, processLoopInfo.getOperationEndId(), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, processLoopInfo.getLoopCount(), wfCols);
            ws.addCell(stringValue);

            j = 0;
            i++;
        }

        if (wwb != null) {
            wwb.write();
            wwb.close();
        }

        return os;
    }

}