OperationInfoImportAction.java

package com.mycim.webapp.actions.operation;

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.file.excel.im.ExcelImport;
import com.mycim.framework.file.excel.im.ExcelParser;
import com.mycim.framework.file.excel.im.ExcelRow;
import com.mycim.framework.utils.beans.PropertyUtils;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.CollectionUtils;
import com.mycim.framework.utils.lang.collections.MapUtils;
import com.mycim.framework.utils.lang.math.NumberUtils;
import com.mycim.utils.FieldValidateUtils;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.consts.CompletedssConstants;
import com.mycim.valueobject.prp.Operation;
import com.mycim.valueobject.prp.OperationExcelDataForm;
import com.mycim.valueobject.sys.ReferenceFileDetail;
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.OperationImpForm;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.util.*;

/**
 * @author Fang Tong
 */
public class OperationInfoImportAction extends PrpSetupAction {

    private static final String IMPORT_KEY = "import";

    private static final String RESULT_LIST = "resultList";

    private static final String SUCCESS_ITEMS = "successItems";

    private static final String FAILED_ITEMS = "failedItems";

    private static final String POS = "Y";

    private static final String NEG = "N";

    private static final String MOVEIN_STD = "MOVEIN_STD";

    private static final String MOVEOUT_STD = "MOVEOUT_STD";

    private static final String MOVEIN_STD_WS = "MOVEIN_STD_WS";

    private static final String MOVEOUT_STD_WS = "MOVEOUT_STD_WS";

    private static final String MOVEIN_BONDED_STD = "MOVEIN_BONDED_STD";

    private static final String MOVEOUT_AUTOBONDED_STD = "MOVEOUT_AUTOBONDED_STD";

    private static final int ITEMS_PER_PAGE = 10;

    @Override
    public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        OperationImpForm theform = (OperationImpForm) form;
        request.removeAttribute(RESULT_LIST);
        theform.setTotal(0);
        theform.setCurPage(0);
        return mapping.findForward(Constants.CREATE_KEY);
    }

    public void downloadTemplate(HttpServletResponse response) throws Exception {
        String fileName = "operation_import_template-version.xls";
        WebUtils.exportExcel(fileName, new HashMap<>(), new ArrayList(), TemplateLocation.OPERATION_IMP_TEMPLATE, 1, 1,
                             response);
    }

    public ActionForward pagination(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                    HttpServletResponse response) throws Exception {
        OperationImpForm theform = (OperationImpForm) form;
        List importData = (List) WebUtils.getCacheString2Obj(theform.getCacheImportData());
        if (StringUtils.isNotBlank(WebUtils.getParameter(Constants.NEXT_KEY, request))) {
            theform.setCurPage(theform.getCurPage() + 1);
        } else if (StringUtils.isNotBlank(WebUtils.getParameter(Constants.PREV_KEY, request))) {
            theform.setCurPage(theform.getCurPage() - 1);
        } else if (StringUtils.isNotBlank(WebUtils.getParameter(Constants.FIRST_KEY, request))) {
            theform.setCurPage(1);
        } else if (StringUtils.isNotBlank(WebUtils.getParameter(Constants.LAST_KEY, request))) {
            theform.setCurPage(theform.getTotal());
        } else if (StringUtils.isNotBlank(WebUtils.getParameter("goto", request))) {
            int target = theform.getTarget();
            if (target > theform.getTotal()) {
                target = theform.getTotal();
            } else if (target < 1) {
                target = theform.getCurPage();
            }
            theform.setCurPage(target);
        }
        request.setAttribute(RESULT_LIST, this.generateDisplayByPage(importData, theform.getCurPage()));
        return mapping.findForward(Constants.CREATE_KEY);
    }

    /**
     * the action for import the excel file
     *
     * @param mapping
     * @param theform
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    public ActionForward doImportExcel(ActionMapping mapping, OperationImpForm theform, HttpServletRequest request,
                                       HttpServletResponse response) throws Exception {
        FormFile upFile = theform.getFormFile();
        String fileName = upFile.getFileName();

        Assert.isFalse(StringUtils.isEmpty(fileName), Errors.create().key(MessageIdList.SPEC_PLEASE_SELECT_EXCEL)
                                                            .content("Please select the Excel file to import!")
                                                            .build());
        Assert.isFalse(!StringUtils.endsWith(upFile.getFileName(), ".xls") || upFile.getFileSize() < 1,
                       Errors.create().key(MessageIdList.IMPORT_ERROR_NAME).content("Only import .xls files!").build());


        List<OperationExcelDataForm> list = getImpData(upFile);
        Assert.state(CollectionUtils.isNotEmpty(list),Errors.create().key(MessageIdList.IMPORT_DATA_EMPTY).content("xls is empty!").build());
        List<OperationExcelDataForm> list4view = this.generateDisplayByPage(list, 1);
        theform.setTotal(list.size() / ITEMS_PER_PAGE + (list.size() % ITEMS_PER_PAGE != 0 ? 1 : 0));
        theform.setCurPage(list.size() > 0 ? 1 : 0);
        request.setAttribute(RESULT_LIST, list4view);
        //将List转换成数组
        OperationExcelDataForm[] obj = new OperationExcelDataForm[list.size()];
        list.toArray(obj);
        //执行序列化存储
        theform.setCacheImportData(WebUtils.getCacheObj2String(list));
        return mapping.findForward(Constants.CREATE_KEY);
    }

    /**
     * check the operation id insert the operation data from the list;
     *
     * @param mapping
     * @param theform
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    public ActionForward insertOperation(ActionMapping mapping, OperationImpForm theform, HttpServletRequest request,
                                         HttpServletResponse response) throws Exception {
        String language = I18nUtils.getCurrentLanguage().toString();
        long facilityRrn = LocalContext.getFacilityRrn();
        long userRrn = LocalContext.getUserRrn();
        List<OperationExcelDataForm> importData = (List) WebUtils.getCacheString2Obj(theform.getCacheImportData());
       Assert.isFalse(CollectionUtils.isEmpty(importData),
                       Errors.create().content("import.import_data_first").build());
        List<OperationExcelDataForm> insertList = new LinkedList<OperationExcelDataForm>();
        List<OperationExcelDataForm> failedList = new LinkedList<OperationExcelDataForm>();
        final String importFlag = theform.getImportFlag();
        OperationExcelDataForm item = null;
        // distribute each item into the insert list and the failed list by the attribute of isValidateData
        // from the
        // form;
        for (Iterator<OperationExcelDataForm> ite = importData.iterator(); ite.hasNext(); ) {
            item = ite.next();
            if (item.isValidateData() == true) {
                insertList.add(item);
            } else {
                failedList.add(item);
            }
        }
        Operation operation = null;
        List<ReferenceFileDetail> workAreaRefs = sysService.getReferenceFileDetails(
                this.getInstanceRrn("$$WORK_AREA", facilityRrn, ObjectList.REFERENCE_FILE_KEY));
        ReferenceFileDetail ref = null;
        for (Iterator<OperationExcelDataForm> ite = insertList.iterator(); ite.hasNext(); ) {
            item.clearMessage();
            item = ite.next();
            //            if (item.isUploaded()) {
            //                ite.remove();
            //                item.addMessage("已经添加");
            //                failedList.add(item);
            //            }
            operation = new Operation(item.getInstanceId(), getNamedSpace(ObjectList.OPERATION_KEY, facilityRrn),
                                      ObjectList.OPERATION_KEY);
            // check if the operation id is already existed, remove and put it into the failed list if it
            if (this.getInstance(operation).getInstanceRrn() > 0L) {
                ite.remove();
                item.setValidateData(false);
                if (StringUtils.equalsIgnoreCase("CN", language)) {
                    item.addMessage("步骤号已经存在");
                } else {
                    item.addMessage("The step id already exists.");
                }
                failedList.add(item);
                continue;
            }
            operation.setTransPerformedby(LocalContext.getUserId());
            operation.setTransId(Constants.CREATE_KEY);

            this.copyPropertiesFromFormToBean(operation, item);
            for (Object each : workAreaRefs) {
                ref = (ReferenceFileDetail) each;
                if (StringUtils.equalsIgnoreCase(item.getWorkArea(), ref.getData1Value())) {
                    operation.setWorkArea(ref.getKey1Value());
                    break;
                }
            }
            //set keep_unit_history_flag =0
            operation.setKeepUnitHistoryFlag(FALSE);
            // set the default operation programme id
            String movein = StringUtils.equals(POS, item.getBondingFlag()) ? MOVEIN_BONDED_STD : MOVEIN_STD;
            String moveout = StringUtils.equals(POS, item.getBondingFlag()) ? MOVEOUT_AUTOBONDED_STD : MOVEOUT_STD;
            operation.setMvinWflId(movein);
            operation.setMvinWflRrn(this.getInstanceRrn(movein, facilityRrn, ObjectList.WFL_KEY));
            operation.setMvouWflId(moveout);
            operation.setMvouWflRrn(this.getInstanceRrn(moveout, facilityRrn, ObjectList.WFL_KEY));
            operation.setWsMvinWflId(MOVEIN_STD_WS);
            operation.setWsMvinWflRrn(this.getInstanceRrn(MOVEIN_STD_WS, facilityRrn, ObjectList.WFL_KEY));
            operation.setWsMvouWflId(MOVEOUT_STD_WS);
            operation.setWsMvouWflRrn(this.getInstanceRrn(MOVEOUT_STD_WS, facilityRrn, ObjectList.WFL_KEY));
            operation.setUnitOfMeasure1(CompletedssConstants.COMPLETEDSS_TYPE_WAFER);
            operation.setStoreFlag(EMPTY);
            //            operation.setMoveInRequired(ON);
            if (item.getLowYield() == null) {
                operation.setLowYield(0D);
            }
            operation.setInstanceRrn(prpService.insertOperation(operation, userRrn, importFlag));

            // process Recipe
            if (StringUtils.isNotEmpty(operation.getRecipeId())) {

                Map operationRecipe = new HashMap();
                operationRecipe.put("context_rrn",
                                    new Long(getInstanceRrn("RECIPE_CONTEXT", facilityRrn, ObjectList.CONTEXT_KEY)));
                operationRecipe.put("context_key1", operation.getInstanceRrn() + "");

                Assert.isFalse(getInstanceRrn(operation.getRecipeId(), facilityRrn, ObjectList.RECIPE_KEY) == 0,
                               Errors.create().key(MessageIdList.RECIPE_DEFAULT_RECIPE_MISSING).content("recipe miss")
                                     .build());
                operationRecipe.put("result_value1",
                                    getInstanceRrn(operation.getRecipeId(), facilityRrn, ObjectList.RECIPE_KEY) + "");
                operationRecipe.put("oldResult_value1", item.getRecipeRrn());

                prpService.saveOperationRecipe(operationRecipe);
            }
            this.processAttributes(operation.getInstanceRrn(), item);
            if (StringUtils.equalsIgnoreCase("CN", language)) {
                item.setMessage("上传成功!");
            } else {
                item.setMessage("Uploaded successfully!");
            }
            item.setUploaded(true);
        }
        for (Iterator<OperationExcelDataForm> ite = failedList.iterator(); ite.hasNext(); ) {
            item = ite.next();
            if (item.isUploaded() != true) {
                if (StringUtils.equalsIgnoreCase("CN", language)) {
                    item.addMessage("添加失败");
                } else {
                    item.addMessage("Add failure.");
                }
            }
            item.setUploaded(true);
        }
        request.setAttribute(SUCCESS_ITEMS, insertList);
        request.setAttribute(FAILED_ITEMS, failedList);
        request.setAttribute(RESULT_LIST, this.generateDisplayByPage(importData, 1));
        theform.setCurPage(1);
        theform.setCacheImportData(WebUtils.getCacheObj2String(importData));
        return mapping.findForward(Constants.CREATE_KEY);
    }

    /**
     * paging a list
     *
     * @param list
     * @param page
     * @return
     */
    private List<OperationExcelDataForm> generateDisplayByPage(List<OperationExcelDataForm> list, int page) {
        List<OperationExcelDataForm> result = new LinkedList<OperationExcelDataForm>();
        int index = 0;
        OperationExcelDataForm item = null;
        for (Iterator<OperationExcelDataForm> ite = list.iterator(); ite.hasNext(); index++) {
            item = ite.next();
            if (index > (page - 1) * ITEMS_PER_PAGE - 1 && index < ITEMS_PER_PAGE * page) {
                result.add(item);
            }
        }
        return result;
    }

    private List<OperationExcelDataForm> getImpData(FormFile upFile) throws Exception {
        List<OperationExcelDataForm> operationExcelDataForm = new ArrayList<>();
        long facilityRrn = LocalContext.getFacilityRrn();
        Long refFileRrn = this.getInstanceRrn("$$OPERATION_EXCELFORM", facilityRrn, ObjectList.REFERENCE_FILE_KEY);
        List<ReferenceFileDetail> refFiles = sysService.getReferenceFileDetails(refFileRrn);
        ReferenceFileDetail referenceFileDetail = null;
        Map<String, ReferenceFileDetail> refFileMap = new HashMap<String, ReferenceFileDetail>();
        for (Object each : refFiles) {
            referenceFileDetail = (ReferenceFileDetail) each;
            refFileMap.put(referenceFileDetail.getData1Value(), referenceFileDetail);
        }

        List<Map> results = new ExcelImport().attributeFrom(0).attributeTo(0).tableFrom(1)
                                             .mapper(new ExcelParser<Object, Map>() {

                                                 @Override
                                                 public Object attributeMapper(List<ExcelRow> attributeRows,
                                                                               int attributeFrom, int attributeTo) {
                                                     return null;
                                                 }

                                                 @Override
                                                 public Map tableRowMapper(ExcelRow excelRow, int rowNum,
                                                                           Object attributeDatas) {

                                                     if (rowNum < 4 || StringUtils.isBlank(excelRow.getString(0))) {
                                                         return null;
                                                     }
                                                     int i = 0;
                                                     Map map = new HashMap();
                                                     //序号
                                                     map.put("seq", excelRow.getString(i++));
                                                     //步骤号
                                                     map.put("instanceId", excelRow.getString(i++));
                                                     //步骤类型
                                                     map.put("objectType", excelRow.getString(i++));
                                                     //设备组号
                                                     map.put("entityGroupId", excelRow.getString(i++));
                                                     //计划周期
                                                     map.put("plannedCycleTime4Min", excelRow.getString(i++));
                                                     //工作区域
                                                     map.put("workArea", excelRow.getString(i++));
                                                     //缺省recipe
                                                     map.put("recipeId", excelRow.getString(i++));
                                                     //Bonding标记
                                                     map.put("bondingFlag", excelRow.getString(i++));
                                                     //SwitchMultipath标记
                                                     // map.put("switchMultipathFlag", excelRow.getString(i++));
                                                     //普通工步标记
                                                     map.put("plainStepFlag", excelRow.getString(i++));
                                                     //CT
                                                     // map.put("cycleTime", excelRow.getString(i++));
                                                     //QT
                                                     // map.put("queueTime", excelRow.getString(i++));
                                                     //PT
                                                     // map.put("processTime", excelRow.getString(i++));
                                                     //进站/出站检查用户
                                                     // map.put("userCheckFlag", excelRow.getString(i++));
                                                     return map;
                                                 }
                                             }).file(upFile.getInputStream()).getTableDataList();

        for (int i = 0; i < results.size(); i++) {
            OperationExcelDataForm item = new OperationExcelDataForm();
            item = validateAndImport(results, i, refFileMap, facilityRrn, item, refFiles);
            operationExcelDataForm.add(item);
        }
        return operationExcelDataForm;
    }

    /**
     * prepare to insert the PT/QT/userFlag for the operation;
     *
     * @param instanceRrn
     * @param item
     * @throws RemoteException
     * @throws ServletException
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    private void processAttributes(Long instanceRrn, OperationExcelDataForm item) {
        List<Map> objectAttributeValues = new ArrayList();
        objectAttributeValues
                .add(this.buildAttributeMap(StringUtils.equals(POS, item.getUserCheckFlag()) ? "1" : "0", 4958174L,
                                            instanceRrn));
        objectAttributeValues.add(this.buildAttributeMap(item.getCycleTime(), 5170140L, instanceRrn));
        objectAttributeValues.add(this.buildAttributeMap(item.getProcessTime(), 5170144L, instanceRrn));
        objectAttributeValues.add(this.buildAttributeMap(item.getQueueTime(), 5170142L, instanceRrn));
        sysService.maintainAttribute(objectAttributeValues);
    }

    /**
     * prepare a map for inserting a PT/QT/userFlag attempt that required
     *
     * @param filedValue
     * @param fieldRrn
     * @param instanceRrn
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    private Map buildAttributeMap(String filedValue, Long fieldRrn, Long instanceRrn) {
        Map attributeValue = new HashMap();
        attributeValue.put("instanceRrn", instanceRrn.toString());
        attributeValue.put("instanceVersion", "1");
        attributeValue.put("fieldRrn", fieldRrn.toString());
        attributeValue.put("attributeValue", filedValue);
        return attributeValue;
    }

    /**
     * copy the data from the form to the operation and set values to a right format in order to get the
     * operation ready to be inserted;
     *
     * @param operation
     * @param item
     */
    private void copyPropertiesFromFormToBean(Operation operation, OperationExcelDataForm item) throws Exception {
        PropertyUtils.copyProperties(operation, item);
        operation.setSkippableFlag(this.toCheckBoxValue(item.getSkippableFlag()));
        operation.setReticleRequired(this.toCheckBoxValue(item.getReticleFlag()));
        operation.setPopDummyFlag(this.toCheckBoxValue(item.getDummyFlag()));
        //operation.setEdcWaferFlag(this.toCheckBoxValue(item.getEdcFetchFlag()));
        //operation.setMoveInRequired(this.toCheckBoxValue(item.getEdc2spcFlag()));
        operation.setTrackUnitFlag(this.toCheckBoxValue(POS));
        operation.setKeepUnitHistoryFlag(this.toCheckBoxValue(POS));
        operation.setPlannedCycleTime(this.minsToTime(operation.getPlannedCycleTime4Min()));
        //operation.setMaxQueueTime(this.minsToTime(this.hourToMins(item.getMaxQueueTime())));
        //operation.setMinQueueTime(this.minsToTime(this.hourToMins(item.getMinQueueTime())));
    }

    private String toCheckBoxValue(String value) {
        return StringUtils.equals(value, POS) ? "on" : null;
    }

    /**
     * read a single row of data from the excel file and save into the form accordingly; In case of any
     * invalid data from the excel will result in returning false as the validate result, otherwise return
     * true make the data ready to be saved into database;
     */
    private OperationExcelDataForm validateAndImport(List<Map> list, int rowIndex,
                                                     Map<String, ReferenceFileDetail> refFileMap, Long facility,
                                                     OperationExcelDataForm item,
                                                     List<ReferenceFileDetail> refs) throws Exception {
        String language = I18nUtils.getCurrentLanguage().toString();
        boolean valid = true;
        Class<? extends OperationExcelDataForm> itemClass = item.getClass();
        Field[] fields = itemClass.getDeclaredFields();
        String fieldName = null;
        Field field = null;
        String value = null;
        Method method = null;
        for (int i = 0; i < fields.length; i++) {
            field = fields[i];
            field.setAccessible(true);
            fieldName = field.getName();
            for (Iterator ite = refs.iterator(); ite.hasNext(); ) {
                ReferenceFileDetail ref = (ReferenceFileDetail) ite.next();
                if (StringUtils.equalsIgnoreCase(ref.getData1Value().trim(), fieldName)) {
                    value = StringUtils.isEmpty(MapUtils.getString(list.get(rowIndex), fieldName)) ? "" : MapUtils
                            .getString(list.get(rowIndex), fieldName);
                    value = StringUtils.isNotBlank(ref.getData3Value()) ? value.trim().toUpperCase() : value;
                    field.set(item, value);
                    // validate by required
                    if (StringUtils.isNotBlank(ref.getData2Value()) && StringUtils.isBlank(value)) {
                        if (language.equals("CN")) {
                            item.addMessage(ref.getData4Value() + "不存在 !");
                        } else {
                            item.addMessage(ref.getData4Value() + "Not Found !");
                        }
                        valid = false;
                    }
                    if (StringUtils.equalsIgnoreCase("seq", fieldName) && StringUtils.isNotBlank(value)) {
                        if(value == null){
                            if (StringUtils.equalsIgnoreCase("CN", language)) {
                                item.addMessage("序号不能为空");
                            } else {
                                item.addMessage("NO. is cannot empty!");
                            }
                            valid = false;
                        }
                    }

                    if (StringUtils.equalsIgnoreCase("instanceId", fieldName) && StringUtils.isNotBlank(value)) {
                        if(value.length() > 64){
                            if (StringUtils.equalsIgnoreCase("CN", language)) {
                                item.addMessage("Step ID 长度不大于64个字符.");
                            } else {
                                item.addMessage("Step ID length cannot more than 64.");
                            }
                            valid = false;
                        }else{
                            if (StringUtils.isNotBlank(item.getInstanceId())) {
                                String result =  FieldValidateUtils.validateSpecialChar(item.getInstanceId());
                                if(StringUtils.isNotBlank(result)){
                                    valid = false;
                                    item.addMessage("Step ID "+result);
                                }
                            }
                        }
                        if(StringUtils.contains(value, ".")){
                            if (NumberUtils.isCreatable(value)) {
                                String[] str = value.split("\\.");
                                if (!str[1].equals("0")) {
                                    if (StringUtils.equalsIgnoreCase("CN", language)) {
                                        item.addMessage("步骤号不能包含小数点");
                                    } else {
                                        item.addMessage("Step number cannot contain a decimal point.");
                                    }
                                }
                            } else {
                                if (StringUtils.equalsIgnoreCase("CN", language)) {
                                    item.addMessage("步骤号不能包含小数点");
                                } else {
                                    item.addMessage("Step number cannot contain a decimal point.");
                                }
                            }
                            valid = false;
                        }
                    }
                    if (StringUtils.equalsIgnoreCase("plannedCycleTime4Min", fieldName)) {
                        if (StringUtils.isNotBlank(value) && !NumberUtils.isDouble(value)) {
                            if (StringUtils.equalsIgnoreCase("CN", language)) {
                                item.addMessage("计划周期不是数字");
                            } else {
                                item.addMessage("Planned cycle time is not a number.");
                            }
                            valid = false;
                        }
                    }
                    if (StringUtils.equalsIgnoreCase("cycleTime", fieldName)) {
                        if (StringUtils.isNotBlank(value) && !NumberUtils.isDouble(value)) {
                            if (StringUtils.equalsIgnoreCase("CN", language)) {
                                item.addMessage("Cycle Time不是数字");
                            } else {
                                item.addMessage("Cycle Time is not a number.");
                            }
                            valid = false;
                        }
                    }
                    if (StringUtils.equalsIgnoreCase("queueTime", fieldName)) {
                        if (StringUtils.isNotBlank(value) && !NumberUtils.isDouble(value)) {
                            if (StringUtils.equalsIgnoreCase("CN", language)) {
                                item.addMessage("QTime不是数字");
                            } else {
                                item.addMessage("QTime is not a number.");
                            }
                            valid = false;
                        }
                    }
                    if (StringUtils.equalsIgnoreCase("processTime", fieldName)) {
                        if (StringUtils.isNotBlank(value) && !NumberUtils.isDouble(value)) {
                            if (StringUtils.equalsIgnoreCase("CN", language)) {
                                item.addMessage("Processing Time不是数字");
                            } else {
                                item.addMessage("Processing Time is not a number.");
                            }
                            valid = false;
                        }
                    }
                    // validate and set the result if a reference file id is provided
                    String refId = ref.getData5Value();
                    if (StringUtils.isNotBlank(value) && StringUtils.isNotBlank(refId)) {
                        String refValue = this.validateByReferenceFile(value, refId.trim().toUpperCase(), facility);
                        boolean refFlag = StringUtils.isNotBlank(refValue);
                        PropertyDescriptor pd = new PropertyDescriptor(fieldName + "Text", itemClass);
                        method = pd.getWriteMethod();
                        method.invoke(item, value);

                        if (refFlag == true) {
                            field.set(item, refValue);
                        } else {
                            if (language.equals("CN")) {
                                item.addMessage(ref.getData4Value() + "不存在 !");
                            } else {
                                item.addMessage(ref.getData4Value() + "Not Found !");
                            }
                        }
                        valid = valid && refFlag;
                    }

                    if (StringUtils.equals("instanceId", fieldName) == true) {
                        if (value.contains("--")) {
                            item.addMessage("The step number contains illegal characters: \"--\"");
                            valid = false;
                        }
                    } else if (StringUtils.isNotEmpty(value) &&
                            StringUtils.equals("Id", fieldName.substring(fieldName.length() - 2)) == true) {
                        String bodyName = fieldName.substring(0, fieldName.length() - 2);
                        PropertyDescriptor pd = new PropertyDescriptor(bodyName + "Rrn", itemClass);
                        method = pd.getWriteMethod();
                        method.invoke(item, this.getInstanceRrn(value, facility, bodyName.toUpperCase(), item, ref));
                        valid = valid && ((Long) pd.getReadMethod().invoke(item)) > 0L;
                    }
                }
            }

            if (fieldName.contains("Flag") == true) {
                field.set(item, StringUtils.equals(POS, value) ? POS : NEG);
            }
        }
        item.setValidateData(valid);
        return item;
    }

    /**
     * attempt to find the RRN of the instance, return -1L and add the message into the form in case of failed
     * attempt;
     *
     * @param instanceId
     * @param facility
     * @param objectType
     * @param of
     * @param ref
     * @return
     */
    private long getInstanceRrn(String instanceId, Long facility, String objectType, OperationExcelDataForm of,
                                ReferenceFileDetail ref) {
        String language = I18nUtils.getCurrentLanguage().toString();
        Long instanceRrn = this.getInstanceRrn(instanceId, facility, objectType);
        if (instanceRrn == null || instanceRrn < 1L) {
            if (language.equals("CN")) {
                of.addMessage(ref.getData4Value() + "不存在 !");
            } else {
                of.addMessage(ref.getData4Value() + "Not Found !");
            }
            return -1L;
        } else {
            return instanceRrn;
        }
    }

    /**
     * parse a minutes in string to a time formated as HH:mm:ss
     *
     * @param minStr
     * @return
     */
    private String minsToTime(String minStr) {
        final char COLON = ':';
        String[] parts = minStr.split("\\.");
        StringBuffer result = new StringBuffer(StringUtils.EMPTY);
        if (StringUtils.isNumeric(parts[0])) {
            int mins = Integer.parseInt(StringUtils.isEmpty(parts[0]) ? "0" : parts[0]);
            // ignore the decimal value;
            // int ss = parts.length > 1 ? Math.round(Float.parseFloat("0." + parts[1]) * 60) : 0;
            int ss = 0;
            int hh = mins / 60;
            int mm = mins % 60;
            result.append(this.parseDoubleDigits(hh)).append(COLON).append(this.parseDoubleDigits(mm)).append(COLON)
                  .append(this.parseDoubleDigits(ss));
        }
        return result.toString();
    }

    /**
     * auto add an "0" before the number if the number is a single digit number(the absolute value is less
     * than 10);
     *
     * @param num
     * @return
     */
    private String parseDoubleDigits(int num) {
        return Math.abs(num) < 10 ? "0" + num : String.valueOf(num);
    }

    /**
     * convert the hour in String form to minutes in String form, return "0" if the String is blank(null or
     * space)
     *
     * @param hour
     * @return
     */
    private String hourToMins(String hour) {
        if (StringUtils.isNotBlank(hour)) {
            return String.valueOf((int) (Double.parseDouble(hour) * 60));
        } else {
            return "0";
        }
    }

    /**
     * Get the reference file value according to the description and reference file id that provided; return
     * an empty string if the value is not found
     *
     * @param value       - the description that need to be deciphered
     * @param refFileName - the id of the reference file
     * @param facilityRrn
     * @return
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
    private String validateByReferenceFile(String value, String refFileName, Long facilityRrn) throws Exception {

        List<ReferenceFileDetail> refs = sysService
                .getReferenceFileDetails(this.getInstanceRrn(refFileName, facilityRrn, ObjectList.REFERENCE_FILE_KEY));
        Assert.isFalse(refs == null || refs.size() < 1,
                       Errors.create().content("Reference Detail: {} Not Found !!!").args(refFileName).build());
        String result = StringUtils.EMPTY;
        Class refClass = ReferenceFileDetail.class;
        Field field = null;
        ReferenceFileDetail ref = null;
        String _value = null;

        for (Object each : refs) {
            ref = (ReferenceFileDetail) each;
            for (int i = 1; i < 6; i++) {
                field = refClass.getDeclaredField("data" + i + "Value");
                field.setAccessible(true);
                _value = (String.valueOf(field.get(ref))).trim();
                field.setAccessible(false);
                if (StringUtils.equalsIgnoreCase(_value, value)) {
                    result = ref.getKey1Value();
                    result = StringUtils.isBlank(result) ? ref.getKey2Value() : result;
                    break;
                }
            }
            if (StringUtils.isNotBlank(result)) {
                break;
            }
        }
        return result;
    }

}