RecipeBatchAction.java
package com.mycim.webapp.actions.recipe.recipebatch;
import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.exception.SystemIllegalArgumentException;
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.lang.BooleanUtils;
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.time.DateUtils;
import com.mycim.utils.FieldValidateUtils;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.bas.ObjectVersion;
import com.mycim.valueobject.bas.Relation;
import com.mycim.valueobject.consts.LinkTypeList;
import com.mycim.valueobject.consts.TransactionNames;
import com.mycim.valueobject.ems.Entity;
import com.mycim.valueobject.prp.*;
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.recipe.RecipeSaveAction;
import com.mycim.webapp.forms.RecipeImportForm;
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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.lang.Override;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
public class RecipeBatchAction extends RecipeSaveAction {
private static final int ITEMS_PER_PAGE = 10;
private static final String SUB_RECIPE_SEPARATOR = "-";
private static final String PARALLEL_MODE = "PARALLEL";
private static final String SERIAL_MODE = "SERIAL";
public static String timestampToLongString(Date date) {
String dateString = "";
if (date != null) {
SimpleDateFormat formatter = new SimpleDateFormat(DateUtils.DATE_FORMAT);
dateString = formatter.format(date);
}
return dateString;
}
@Override
public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
RecipeImportForm theform = (RecipeImportForm) form;
theform.setTotal(0);
theform.setCurPage(0);
theform.setIsImportFlag("");
return mapping.findForward(Constants.CREATE_KEY);
}
public ActionForward recipeBatchAction(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
RecipeImportForm theform = (RecipeImportForm) 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);
}
theform.setRecipeData(this.generateDisplayByPage(importData, theform));
return mapping.findForward(Constants.CREATE_KEY);
}
/**
* import action the excel data for display;
*
* @param mapping
* @param theform
* @param request
* @return
*/
public ActionForward doImportExcel(ActionMapping mapping, RecipeImportForm theform,
HttpServletRequest request) 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());
List<RecipeExcelDataForm> list = getImpData(upFile);
List<RecipeExcelDataForm> list4view = this.generateDisplayByPage(list, 1);
theform.setRecipeData(list4view);
theform.setTotal(list.size() / ITEMS_PER_PAGE + (list.size() % ITEMS_PER_PAGE != 0 ? 1 : 0));
theform.setCurPage(list.size() > 0 ? 1 : 0);
theform.setIsImportFlag(list.size() > 0 ? "YES" : "");
//将List转换成数组
RecipeExcelDataForm[] obj = new RecipeExcelDataForm[list.size()];
list.toArray(obj);
//执行序列化存储
theform.setCacheImportData(WebUtils.getCacheObj2String(list));
return mapping.findForward(Constants.CREATE_KEY);
}
/**
* insert the excel data into database, relate the recipe with the equipments if are listed and add new
* version if the ecn flag is 1;
*
* @param mapping
* @param theform
* @param request
* @param response
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
public ActionForward doInsertRecipe(ActionMapping mapping, RecipeImportForm theform, HttpServletRequest request,
HttpServletResponse response) throws Exception {
String language = I18nUtils.getCurrentLanguage().name();
long facility = LocalContext.getFacilityRrn();
String messageSave = StringUtils.equalsIgnoreCase(language, "CN") ? "导入失败" : "Failed imported ";
Ecn ecn = ecnService.generateUnFrozenEcnForProcessPlan(LocalContext.getUserRrn());
List<RecipeExcelDataForm> importData = (List) WebUtils.getCacheString2Obj(theform.getCacheImportData());
for (RecipeExcelDataForm each : importData) {
if (each.isValid() != true) {
//each.addMassage("Not saved");
if (!StringUtils.contains(each.getMessage(), messageSave)) {
each.addMassage(messageSave);
}
continue;
}
Long recipeRrn = this.getInstanceRrn(each.getRecipeId(), facility, ObjectList.RECIPE_KEY);
boolean isInserted = recipeRrn == null || recipeRrn < 1L;
Recipe recipe = null;
if (isInserted == true) {
recipe = new Recipe(each.getRecipeId(), getNamedSpace(ObjectList.RECIPE_KEY, facility),
ObjectList.RECIPE_KEY);
} else {
recipe = recipeService.getRecipe(each.getRecipeId(), LocalContext.getFacilityRrn());
}
each.setInserted(isInserted);
recipe.setTransId(isInserted ? Constants.CREATE_KEY : Constants.MODIFY_KEY);
String user = LocalContext.getUserId();
Long userRrn = LocalContext.getUserRrn();
this.processRecipe(each, recipe, user, userRrn, facility);
if (StringUtils.isNotBlank(each.getECNFlag()) && StringUtils.equals("1", each.getECNFlag().trim())) {
//-----------------生成chamberRecipe--------------start
final char COMMA = ',';
final String PLUS = "\\+";
String chamberJoin = each.getChamberType();
StringBuffer sb = new StringBuffer(recipe.getInstanceId() + SUB_RECIPE_SEPARATOR);
StringBuffer chamberType = new StringBuffer();
String tempChamber = StringUtils.EMPTY;
if (StringUtils.isNotBlank(chamberJoin)) {
String chambers[] = chamberJoin.split(PLUS);
int len = chambers.length;
for (int i = 0; i < len; i++) {
tempChamber = chambers[i].trim().toUpperCase();
ReferenceFileDetail ref = this.getReferenceFileDetail("$CHAMBER_TYPE", tempChamber, facility);
if (ref != null) {
sb.append(chambers[i].trim().toUpperCase());
chamberType.append(tempChamber);
}
}
}
String chamberRecipeId = sb.toString();
String chamberTypeString = chamberType.toString();
Long chamberRecipeRrn = this.getInstanceRrn(chamberRecipeId, facility, ObjectList.RECIPE_KEY);
boolean flag = chamberRecipeRrn == null || chamberRecipeRrn < 1L;
Recipe chamberRecipe = null;
if (flag) {
chamberRecipe = new Recipe(chamberRecipeId, getNamedSpace(ObjectList.RECIPE_KEY, facility),
ObjectList.RECIPE_KEY);
chamberRecipe.setObjectType(ObjectList.RECIPE_KEY);
chamberRecipe.setTransId(Constants.CREATE_KEY);
chamberRecipe.setInstanceRrn(recipeService.insertRecipe(setDefaultParam(chamberRecipe)));
} else {
chamberRecipe = recipeService.getRecipe(chamberRecipeId, LocalContext.getFacilityRrn());
}
chamberRecipe.setTransId(flag ? Constants.CREATE_KEY : Constants.MODIFY_KEY);
//-----------------生成chamberRecipe--------------start
//如果绑定的是chamber类型recipe的话,此时recipe的chamber版本关系和和设备绑定的都是chamberRecipe,而非主recipe
//即processRecipeVersion和processEqtInfo两个方法应该传入chamberRecipe
chamberRecipe.setParentRecipeId(recipe.getInstanceId());
chamberRecipe.setParentRecipeRrn(recipe.getInstanceRrn());
Recipe parentRecipe = recipe;
recipe = chamberRecipe;
this.processRecipeVersion(each, recipe, user, userRrn, facility, ecn);
if (StringUtils.isNotBlank(each.getEntityId())) {
//导入模板中有设备,两种情况:串行;并行
String entityId = each.getEntityId();
Entity entity = new Entity(entityId, getNamedSpace(ObjectList.ENTITY_KEY, facility),
ObjectList.ENTITY_KEY);
entity = emsService.getEntity(entity);
if (StringUtils.equalsIgnoreCase(entity.getChamberMode(), PARALLEL_MODE)) {
//并行
buildAddRecipeRrnsForParallelMode(entity.getInstanceRrn(), parentRecipe, chamberTypeString);
}
}
}
if (StringUtils.isNotBlank(each.getEntityId())) {
this.processEqtInfo(each, recipe, user, userRrn, facility,theform.getReason());
}
}
theform.setRecipeData(this.generateDisplayByPage(importData, 1));
theform.setCacheImportData(WebUtils.getCacheObj2String(importData));
theform.setCurPage(1);
theform.setIsImportFlag("");
return mapping.findForward(Constants.CREATE_KEY);
}
public void downloadTemplate(ActionMapping mapping, ActionForm theform, HttpServletRequest request,
HttpServletResponse response) throws Exception {
String fileName = "recipe_import_template-version.xls";
WebUtils.exportExcel(fileName, new HashMap<>(), new ArrayList(), TemplateLocation.RECIPE_IMP_TEMPLATE, 1, 1,
response);
}
private List<Long> buildAddRecipeRrnsForParallelMode(long equipmentRrn, Recipe parentRecipe, String chamberId) {
List<Long> addRecipeRrns = new ArrayList<>();
Set<String> willCreateChamberIds = new HashSet<>();
willCreateChamberIds.add(chamberId);
//获取当前设备上面绑定的所有单体recipe的类型
buildCreatedSingleChamberId(willCreateChamberIds, equipmentRrn, parentRecipe.getInstanceId());
//生成所有和新添加类型相关的组合,并存人数据库
for (String combinationId : getAvailableSubRecipeChamberIds(willCreateChamberIds)) {
if (!combinationId.contains(chamberId) || StringUtils.equalsIgnoreCase(combinationId, chamberId)) {
continue;
}
long subRecipeRrn = createSubRecipeWithIsExistedByChamberId(parentRecipe, combinationId);
if (combinationId.length() == 1) {
addRecipeRrns.add(subRecipeRrn);
}
}
return addRecipeRrns;
}
private void buildCreatedSingleChamberId(Set<String> willCreateChamberIds, long equipmentRrn,
String parentRecipeId) {
String queryRecipeId = parentRecipeId + "-*";
for (Map<String, Object> map : recipeService
.getRecipesByEquipmentForParallelMode(equipmentRrn, queryRecipeId)) {
willCreateChamberIds
.add(StringUtils.substringAfterLast((MapUtils.getString(map, "recipeId")), SUB_RECIPE_SEPARATOR));
}
}
private List<String> getAvailableSubRecipeChamberIds(Collection<String> chamberTypes) {
if (CollectionUtils.isEmpty(chamberTypes)) {
return Collections.emptyList();
} else {
List<String> list = buildNoRepeatChamberTypes(chamberTypes);
return StringUtils.combinationStrings(list.toArray(new String[0]));
}
}
private long createSubRecipeWithIsExistedByChamberId(Recipe parentRecipe, String combinationId) {
return createSubRecipeWithIsExisted(parentRecipe, StringUtils
.trimToUpperCase(parentRecipe.getInstanceId() + SUB_RECIPE_SEPARATOR + combinationId));
}
private List<String> buildNoRepeatChamberTypes(Collection<String> chamberTypes) {
Set<String> set = new HashSet<>();
for (String string : chamberTypes) {
if (StringUtils.isNotEmpty(string)) {
set.add(string);
}
}
List<String> list = new ArrayList<>(set);
Collections.sort(list);
return list;
}
private Long createSubRecipeWithIsExisted(Recipe parentRecipe, String subRecipeId) {
long subRecipeRrn = getInstanceRrn(subRecipeId, LocalContext.getFacilityRrn(), ObjectList.RECIPE_KEY);
if (subRecipeRrn <= 0) {
subRecipeRrn = createSubRecipeWithActiveVersion(parentRecipe, subRecipeId);
}
checkSubRecipeVersionInfo(subRecipeId, subRecipeRrn);
Relation relation = new Relation(parentRecipe.getInstanceRrn(), subRecipeRrn,
LinkTypeList.RECIPEFAMILY_TO_RECIPE);
if (baseService.getRelation(relation) == null) {
relation.setTransId(TransactionNames.CREATE_KEY);
recipeService.insertRelation4RecipeFamilyToRecipe(relation);
}
return subRecipeRrn;
}
private void checkSubRecipeVersionInfo(String subRecipeId, long subRecipeRrn) {
List<String> recipeChambers = getRecipeChambers(subRecipeRrn);
Assert.isFalse(CollectionUtils.isEmpty(recipeChambers),
Errors.create().key(MessageIdList.RECIPE_NOT_CHAMBER_IS_VERSION)
.content("This recipe {} has not any required " + "chamber in active version!")
.args(subRecipeId).build());
String chamberIds = StringUtils.substringAfterLast(subRecipeId, SUB_RECIPE_SEPARATOR);
boolean isSameNum = chamberIds.length() == recipeChambers.size();
for (String requiredChamberId : recipeChambers) {
Assert.isFalse(!isSameNum || !chamberIds.contains(requiredChamberId),
Errors.create().key(MessageIdList.RECIPE_CHAMBER_IN_VERSION).content(
"This recipe {}" + " " + "required " + "chamber in " + "active " + "version is " +
"not mapped " + "subrecipe id!").args(subRecipeId).build());
}
}
private List<String> getRecipeChambers(long subRecipeRrn) {
RecipeVersion subRecipeVersion = recipeService.getNowActiveRecipeVersion(subRecipeRrn);
boolean isAvailableRecipe = subRecipeVersion != null && subRecipeVersion.getInstanceRrn() > 0 &&
subRecipeVersion.getInstanceVersion() > 0;
String[] chambers = null;
if (isAvailableRecipe) {
chambers = StringUtils.split(StringUtils.substringBefore(subRecipeVersion.getChamberTypes(), ";"),
StringUtils.COMMA_SIGN);
}
List<String> result;
if (chambers != null) {
result = Arrays.asList(chambers);
} else {
result = Collections.emptyList();
}
return result;
}
private long createSubRecipeWithActiveVersion(Recipe parentRecipe, String subRecipeId) {
Recipe recipe = new Recipe(StringUtils.trimToUpperCase(subRecipeId), parentRecipe.getNamedSpace(),
ObjectList.RECIPE_KEY);
recipe.setObjectType(ObjectList.RECIPE_KEY);
recipe.setAttributeData1(parentRecipe.getAttributeData1());
recipe.setAttributeData2(parentRecipe.getAttributeData2());
recipe.setAttributeData3(parentRecipe.getAttributeData3());
recipe.setTransPerformedby(LocalContext.getUserId());
recipe.setTransId(TransactionNames.CREATE_KEY);
long subRecipeRrn = recipeService.insertRecipe(setDefaultParam(recipe));
recipe.setInstanceRrn(subRecipeRrn);
recipe = recipeService.getRecipe(recipe.getInstanceRrn());
baseService.updateNamedObjectSystemUesd(recipe.getInstanceRrn(), "1");
createActiveSubRecipeVersion(recipe, StringUtils.substringAfterLast(subRecipeId, SUB_RECIPE_SEPARATOR));
return subRecipeRrn;
}
private void createActiveSubRecipeVersion(Recipe subRecipe, String chamberIds) {
RecipeVersion recipeVersion = new RecipeVersion();
recipeVersion.copyNamedObject(subRecipe);
int newVersionId = subRecipe.getCurrentVersion() == null ? 1 : subRecipe.getCurrentVersion() + 1;
recipeVersion.setInstanceVersion(newVersionId);
recipeVersion.setVersionId(Integer.toString(newVersionId));
recipeVersion.setVersionDesc("Automatic schema generation");
recipeVersion.setChamberTypes(buildChamberTypesForRecipeVersion(chamberIds.toCharArray()));
recipeVersion.setTransId(TransactionNames.CREATE_KEY);
recipeVersion.setTransPerformedby(LocalContext.getUserId());
recipeService.createRecipeVersion(recipeVersion);
recipeVersion = recipeService.getRecipeVersion(recipeVersion);
ecnService.activateEcn(recipeVersion.getEcnRrn());
}
private String buildChamberTypesForRecipeVersion(char[] chamberIds) {
int lastChar = chamberIds.length - 1;
StringBuilder result = new StringBuilder();
for (int i = 0; i < chamberIds.length; i++) {
result.append(chamberIds[i]);
result.append(i == lastChar ? ";" : StringUtils.COMMA_SIGN);
}
return result.toString();
}
/**
* paging the list in the session based on current page from the form;
*
* @param importData
* @param theform
* @return
*/
@SuppressWarnings("unchecked")
private List<RecipeExcelDataForm> generateDisplayByPage(List importData, RecipeImportForm theform) {
return this.generateDisplayByPage(importData, theform.getCurPage());
}
/**
* page a list with generic to a new list with the same generic;
*
* @param list
* @param page
* @return
*/
private <T> List<T> generateDisplayByPage(List<T> list, int page) {
List<T> result = new LinkedList<T>();
int index = 0;
T item = null;
for (Iterator<T> 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<RecipeExcelDataForm> getImpData(FormFile upFile) throws Exception {
List<RecipeExcelDataForm> recipeExcelDataForms = new ArrayList<>();
long facilityRrn = LocalContext.getFacilityRrn();
Long refFileRrn = this.getInstanceRrn("$$RECIPE_EXCEL_IMPORT_FORM", facilityRrn, ObjectList.REFERENCE_FILE_KEY);
Collection 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;
}
Map map = new HashMap();
//map.put("routeId", excelRow.getString(4));
map.put("seq", excelRow.getString(0));
map.put("entityId", excelRow.getString(1));
map.put("recipeId", excelRow.getString(2));
map.put("recipeDesc", excelRow.getString(3));
map.put("ECNFlag",Double.valueOf(excelRow.getString(4)).intValue());
map.put("chamberType", excelRow.getString(5));
map.put("recipeTime", excelRow.getString(6));
map.put("operateTip", excelRow.getString(7));
map.put("physicalRecipeId", excelRow.getString(8));
map.put("recipeFileUrl", excelRow.getString(9));
map.put("eqtCapability", excelRow.getString(10));
return map;
}
}).file(upFile.getInputStream()).getTableDataList();
for (int i = 0; i < results.size(); i++) {
RecipeExcelDataForm item = new RecipeExcelDataForm();
item = validateAndImport(results, i, refFileMap, facilityRrn, item);
boolean valid = this.validateRecipeDataForm(item) && item.isValid();
item.setValid(valid);
recipeExcelDataForms.add(item);
}
return recipeExcelDataForms;
}
/**
* read a single line of the excel file;
*
* @param list
* @param rowIndex
* @param refFileMap
* @param facility
* @param item
* @return
* @throws Exception
*/
private RecipeExcelDataForm validateAndImport(List<Map> list, int rowIndex,
Map<String, ReferenceFileDetail> refFileMap, Long facility,
RecipeExcelDataForm item) throws Exception {
String language = I18nUtils.getCurrentLanguage().name();
boolean valid = true;
Class<? extends RecipeExcelDataForm> itemClass = item.getClass();
Field[] fields = itemClass.getDeclaredFields();
String fieldName = null;
ReferenceFileDetail ref = null;
PropertyDescriptor pd = null;
String value = null;
for (int i = 0; i < fields.length; i++) {
fieldName = fields[i].getName();
ref = refFileMap.get(fieldName);
if (ref != null) {
value = MapUtils.getString(list.get(rowIndex), fieldName);
if (StringUtils.isNotBlank(value)) {
value = StringUtils.isNotBlank(ref.getData3Value()) ? value.trim().toUpperCase() : value;
}
pd = new PropertyDescriptor(fieldName, itemClass);
pd.getWriteMethod().invoke(item, value);
if (StringUtils.isNotBlank(ref.getData2Value()) && StringUtils.isBlank(value)) {
addMessage(item, language, ref.getData4Value() + "为空", ref.getData4Value() + " input is empty");
valid = false;
}
if (StringUtils.isEqual(fieldName, "recipeId")) {
// #45489 允许$R
if (StringUtils.isNotBlank(value)) {
String msg = FieldValidateUtils.validateRecipeId(value);
if(StringUtils.isNotBlank(msg)){
item.addMassage(msg);
valid = false;
}
}
}
if (StringUtils.contains(fieldName, "Flag")) {
if (StringUtils.equals("1", value) &&
StringUtils.isBlank(MapUtils.getString(list.get(rowIndex), "chamberType"))) {
addMessage(item, language, "Chamber标记为1的recipe的Chamber不能为空",
"The chamber of recipe with chamber flag 1 cannot be empty");
valid = false;
} else if (!StringUtils.equals("1", value)) {
pd.getWriteMethod().invoke(item, "0");
}
}
if (StringUtils.isNotBlank(value) && StringUtils.isNotBlank(ref.getData5Value())) {
String text = value;
value = validateByReferenceFile(value, ref.getData5Value(), facility);
pd.getWriteMethod().invoke(item, value);
pd = new PropertyDescriptor(fieldName + "Text", itemClass);
pd.getWriteMethod().invoke(item, text);
}
if (StringUtils.equalsIgnoreCase("entityId", ref.getData1Value())) {
//如果模板中的设备不为空时,需要校验是否存在于数据库中
if (StringUtils.isNotBlank(value)) {
// 验证数据库中有没有该参数
long entityRrn = getInstanceRrn(value, LocalContext.getFacilityRrn(), ObjectList.ENTITY_KEY);
if (entityRrn <= 0) {
addMessage(item, language, ref.getData4Value() + "不存在!",
ref.getData4Value() + " does not exist!");
valid = false;
} else {
Entity entity = new Entity(value, getNamedSpace(ObjectList.ENTITY_KEY,
LocalContext.getFacilityRrn()),
ObjectList.ENTITY_KEY);
entity = emsService.getEntity(entity);
boolean isChamberEquipment = BooleanUtils.toBoolean(entity.getIsChamberEquip());
boolean isChangeMode =
isChamberEquipment && StringUtils.isNotBlank(entity.getChamberMode());
String chamberFlag = MapUtils.getString(list.get(rowIndex), "ECNFlag");
if (isChangeMode) {
if (StringUtils.isNotBlank(MapUtils.getString(list.get(rowIndex), "chamberType"))) {
String chamberId = MapUtils.getString(list.get(rowIndex), "chamberType");
final String PLUS = "\\+";
StringBuilder tempChamber = new StringBuilder();
String chambers[] = chamberId.split(PLUS);
int len = chambers.length;
for (int j = 0; j < len; j++) {
tempChamber.append(chambers[j].trim().toUpperCase());
}
List<String> canBeCreatedChamberIds = emsService
.getChildChamberEquipmentType(entity.getInstanceRrn());
char[] chars = tempChamber.toString().toCharArray();
for (char c : chars) {
if (!canBeCreatedChamberIds.contains(StringUtils.toString(c))) {
addMessage(item, language, "设备没有该Chamber类型",
"equipment have no these Chamber Type");
valid = false;
break;
}
}
}
if (!StringUtils.equals("1", chamberFlag) ||
StringUtils.isBlank(MapUtils.getString(list.get(rowIndex), "chamberType"))) {
addMessage(item, language, "Chamber设备必须绑定Chamber类型的recipe",
"Chamber equipment must be bound to recipe of chamber type");
valid = false;
} else {
//如果设备是并联模式,此时的recipe chamber只能是一个
if (StringUtils.equalsIgnoreCase(entity.getChamberMode(), PARALLEL_MODE)) {
final String PLUS = "\\+";
String chambers[] = StringUtils
.split(MapUtils.getString(list.get(rowIndex), "chamberType"), PLUS);
int len = chambers.length;
if (len != 1) {
addMessage(item, language, "并行设备只能绑定一个chamber的recipe",
"A parallel equipment can only bind a chamber's " + "recipe");
valid = false;
}
}
}
} else {
if (StringUtils.equals("1", chamberFlag)) {
addMessage(item, language, "非Chamber设备不能绑定Chamber类型的recipe",
"A non chamber equipment cannot bind a chamber type recipe");
valid = false;
}
}
}
}
}
}
}
item.setValid(valid);
return item;
}
/**
* 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 {
Collection refs = sysService
.getReferenceFileDetails(this.getInstanceRrn(refFileName, facilityRrn, ObjectList.REFERENCE_FILE_KEY));
if (refs == null || refs.size() < 1) {
//throw new ValidateFailureException("Reference Detail: " + refFileName + "Not Found !!!");
}
String result = StringUtils.EMPTY;
Class refClass = ReferenceFileDetail.class;
ReferenceFileDetail ref = null;
String _value = null;
PropertyDescriptor pd = null;
for (Object each : refs) {
ref = (ReferenceFileDetail) each;
for (int i = 1; i < 6; i++) {
pd = new PropertyDescriptor("data" + i + "Value", refClass);
_value = (String) pd.getReadMethod().invoke(ref);
if (StringUtils.equalsIgnoreCase(_value, value)) {
result = ref.getKey1Value();
result = StringUtils.isBlank(result) ? ref.getKey2Value() : result;
break;
}
}
if (StringUtils.isNotBlank(result)) {
break;
}
}
return result;
}
private void addMessage(RecipeExcelDataForm item, String language, String chineseString, String englishString) {
if (StringUtils.equalsIgnoreCase(language, "CN")) {
item.addMassage(chineseString);
} else {
item.addMassage(englishString);
}
}
/**
* validate a single line of excel data;
*
* @param item
* @return
*/
private boolean validateRecipeDataForm(RecipeExcelDataForm item) {
String language = I18nUtils.getCurrentLanguage().name();
String standardTimeComment = StringUtils.equalsIgnoreCase(language, "CN") ? "标准时间格式不正确" :
"The standard time " + "format is not " + "correct. ";
String failureTimeComment = StringUtils.equalsIgnoreCase(language, "CN") ? "故障时间格式不正确" :
"The failure time format" + " " + "is incorrect.";
boolean valid = true;
String reicpeTimeRegex = "^(?:[01]\\d|2[0-3])(?::[0-5]\\d){2}$";
String expireTimeRegex = "(((0[1-9]|[12][0-9]|3[01])/((0[13578]|1[02]))|((0[1-9]|[12][0-9]|30)/" + "(0[469" +
"]|11))|(0[1-9]|[1][0-9]|2[0-8])/(02))/" + "([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2" +
"}|[1-9][0-9]{3" + "}))|(29/02/(([0-9]{2})(0[48]|[2468][048]|[13579][26])|(" + "(0[48]|[2468][048" +
"]|[3579][26])00)))";
if (StringUtils.isNotBlank(item.getRecipeTime()) &&
Pattern.matches(reicpeTimeRegex, item.getRecipeTime()) != true) {
item.addMassage(standardTimeComment);
valid = false;
}
if (StringUtils.equals("1", item.getExperimentFlag()) && StringUtils.isNotBlank(item.getExpireTime()) &&
Pattern.matches(expireTimeRegex, item.getExpireTime()) != true) {
item.addMassage(failureTimeComment);
valid = false;
}
return valid;
}
/**
* insert or update the recipe based on the transId of the recipe;
*
* @param item
* @param recipe
* @param user
* @param userRrn
* @param facility
* @throws Exception
*/
private void processRecipe(RecipeExcelDataForm item, Recipe recipe, String user, Long userRrn,
Long facility) throws Exception {
String language = I18nUtils.getCurrentLanguage().name();
String importComment = StringUtils.equalsIgnoreCase(language, "CN") ? "导入成功" : "Successful import";
String updateComment = StringUtils.equalsIgnoreCase(language, "CN") ? "更新成功" : "Successfully update";
Context context = new Context();
context.setInstanceRrn(this.getInstanceRrn("RECIPE_CONTEXT", facility, ObjectList.CONTEXT_KEY));
context = ctxService.getContext(context);
ContextValue contextValue = new ContextValue();
contextValue.setContextRrn(context.getInstanceRrn());
contextValue.setResultValue1(item.getRecipeId());
recipe.setInstanceDesc(item.getRecipeDesc());
recipe.setObjectType(ObjectList.RECIPE_KEY);
recipe.setAttributeData1(this.parseFlagToCheckBox(item.getExperimentFlag()));
recipe.setAttributeData2(item.getExpireTime());
recipe.setTransPerformedby(user);
recipe.setVersions(baseService.getObjectVersions(recipe));
recipe.setRoleId(StringUtils.EMPTY);
recipe.setOperateTip(item.getOperateTip());
this.process(recipe);
recipe.setInstanceRrn(
getInstanceRrn(recipe.getInstanceId(), LocalContext.getFacilityRrn(), ObjectList.RECIPE_KEY));
this.changeRecipeStatusView(recipe, user, userRrn);
if (StringUtils.equalsIgnoreCase("on", recipe.getAttributeData1())) {
updateRelationExpireTime(recipe);
}
recipeService.saveRecipeTime(recipe.getInstanceRrn(), item.getRecipeTime(), item.getIdleTimeLimit());
if (!StringUtils.contains(item.getMessage(), updateComment)) {
if (item.isInserted()) {
item.addMassage(importComment);
} else {
item.setMessage("");
item.addMassage(updateComment);
}
}
}
private String parseFlagToCheckBox(String flag) {
return StringUtils.equals("1", flag) ? "on" : StringUtils.EMPTY;
}
/**
* Relate the recipe with the equipments if is listed;
*
* @param item
* @param recipe
* @param user
* @param userRrn
* @param facility
* @throws Exception
*/
@SuppressWarnings("rawtypes")
private void processEqtInfo(RecipeExcelDataForm item, Recipe recipe, String user, Long userRrn,
Long facility,String comments) throws Exception {
String language = I18nUtils.getCurrentLanguage().name();
String equipmentComment = StringUtils.equalsIgnoreCase(language, "CN") ? "设备不存在" :
"the Equipment does not " + "exist.";
String recipeComment = StringUtils.equalsIgnoreCase(language, "CN") ? "设备已经绑定recipe" :
"Equipment has been " + "associated with the recipe.";
String entityIdsStr = item.getEntityId();
String[] entityIds = entityIdsStr.split(",");
String entityId = null;
Recipe parentRecipe = null;
boolean isSingleChamber = true;
String isSingleChamberStr = "0";
String status = StringUtils.trimToUpperCase(BooleanUtils.toStringOnOff(true));
for (int i = 0; i < entityIds.length; i++) {
long recipeRrn = recipe.getInstanceRrn();
entityId = StringUtils.trimToUpperCase(entityIds[i]);
long entityRrn = this.getInstanceRrn(entityId, facility, ObjectList.ENTITY_KEY);
if (entityRrn < 1L) {
item.addMassage(entityId + " " + equipmentComment);
continue;
}
Entity entity = new Entity(entityId, getNamedSpace(ObjectList.ENTITY_KEY, LocalContext.getFacilityRrn()),
ObjectList.ENTITY_KEY);
entity = emsService.getEntity(entity);
boolean isChamberEquipment = BooleanUtils.toBoolean(entity.getIsChamberEquip());
boolean isChangeMode = isChamberEquipment && StringUtils.isNotBlank(entity.getChamberMode());
if (isChangeMode) {
parentRecipe = recipeService.getRecipe(recipe.getParentRecipeId(), LocalContext.getFacilityRrn());
//绑定主recipe和设备 ----- start -------------
long equipmentRrn = entity.getInstanceRrn();
int maxSize = baseService.getRelationsUseFromRrn(equipmentRrn, LinkTypeList.ENTITY_TO_RECIPE).size();
List<Relation> addRelations = new ArrayList<>();
if (!isExistedInRelation(equipmentRrn, parentRecipe.getInstanceRrn())) {
Relation relation = new Relation(equipmentRrn, parentRecipe.getInstanceRrn(),
LinkTypeList.ENTITY_TO_RECIPE);
relation.setSequenceNumber(++maxSize);
status = StringUtils.trimToUpperCase(BooleanUtils.toStringOnOff(true));
relation.setStatus(status);
relation.setAttributedata1(status);
relation.setAttributedata2(StringUtils.toString(LocalContext.getUserRrn()));
relation.setAttributedata3(timestampToLongString(new Date()));
relation.setAttributedata4("");
relation.setAttributedata5(recipe.getAttributeData2());
relation.setAttributedata6("");
relation.setAttributedata7(entity.getChamberMode());
relation.setTransPerformedby(LocalContext.getUserId());
relation.setTransId(TransactionNames.CREATE_KEY);
addRelations.add(relation);
}
if (CollectionUtils.isNotEmpty(addRelations)) {
// baseService.insertRelation(addRelations);
emsService.insertRelation4RecipeToEntity(addRelations,comments);
}
//绑定主recipe和设备 ----- end -------------
String chamberId = StringUtils.substringAfterLast(recipe.getInstanceId(), SUB_RECIPE_SEPARATOR);
isSingleChamber = chamberId.length() == 1;
boolean isParentRecipe = recipeRrn == parentRecipe.getInstanceRrn();
isSingleChamberStr = isParentRecipe ? null : StringUtils
.upperCase(BooleanUtils.toStringYesNo(isSingleChamber));
checkInputRecipeIdCanBeCreated(entity.getInstanceRrn(), chamberId);
}
List<Relation> recipes = baseService.getFullRelations(LinkTypeList.ENTITY_TO_RECIPE,entityRrn,recipeRrn);
boolean isRelated = false;
if(CollectionUtils.isNotEmpty(recipes)){
if (!StringUtils.contains(item.getMessage(), recipeComment)) {
item.addMassage(entityId + " " + recipeComment);
}
isRelated = true;
}
if (!isRelated) {
Relation relation = new Relation();
relation.setFromRrn(entityRrn);
relation.setLinkType(LinkTypeList.ENTITY_TO_RECIPE);
relation.setStatus(status);
relation.setAttributedata1(StringUtils.isNotBlank(
recipe.getAttributeData1()) ? RecipeStatus.EXIST_KEY : RecipeStatus.ON_KEY);
relation.setAttributedata2(String.valueOf(userRrn));
relation.setAttributedata3(timestampToLongString(new Date()));
if (isChangeMode) {
relation.setAttributedata4(StringUtils.toString(parentRecipe.getInstanceRrn()));
if (isSingleChamber) {
relation.setAttributedata6(isSingleChamberStr);
}
relation.setAttributedata7(entity.getChamberMode());
}
relation.setToRrn(recipeRrn);
relation.setTransPerformedby(user);
relation.setTransId(Constants.ADD_KEY);
relation.setAttributedata5(recipe.getAttributeData2());
// baseService.insertRelation(relation);
emsService.insertRelation4RecipeToEntity(relation,comments);
}
}
}
private boolean isExistedInRelation(long equipmentRrn, Long recipeRrn) {
return baseService.getRelation(new Relation(equipmentRrn, recipeRrn, LinkTypeList.ENTITY_TO_RECIPE)) != null;
}
private void checkInputRecipeIdCanBeCreated(long equipmentRrn, String chamberId) {
Assert.isFalse(StringUtils.isEmpty(chamberId), Errors.create().key(MessageIdList.RECIPE_ID_IS_ERROR).content(
"Recipe ID must use a Recipe ID with a " + "\"-\" and cannot end with a \"-\"!").build());
List<String> canBeCreatedChamberIds = emsService.getChildChamberEquipmentType(equipmentRrn);
Assert.isFalse(CollectionUtils.isEmpty(canBeCreatedChamberIds),
Errors.create().key(MessageIdList.EQUIPMENT_NOT_HAVE_CHAMBER)
.content("This Equipment does not " + "have any chamber!").build());
char[] chars = chamberId.toCharArray();
for (char c : chars) {
Assert.isTrue(canBeCreatedChamberIds.contains(StringUtils.toString(c)),
Errors.create().key(MessageIdList.EQUIPMENT_NOT_HAVE_CHAMBER_2)
.content("This Equipment " + "does not " + "have this " + "chamber: {}").args(c)
.build());
}
}
/**
* process the recipeVersion data, and active the new version if the data is valid;
*
* @param item
* @param recipe
* @param user
* @param userRrn
* @param facility
* @throws Exception
*/
@SuppressWarnings("rawtypes")
private void processRecipeVersion(RecipeExcelDataForm item, Recipe recipe, String user, Long userRrn,
Long facility, Ecn ecn) throws Exception {
String language = I18nUtils.getCurrentLanguage().name();
String chamberComment = StringUtils.equalsIgnoreCase(language, "CN") ? "腔体没有设置." : "Chamber not configured.";
RecipeVersion recipeVersion = new RecipeVersion();
recipeVersion.copyNamedObject(recipe);
int newVersionId = recipe.getCurrentVersion() == null ? 1 : recipe.getCurrentVersion().intValue() + 1;
recipeVersion.setInstanceVersion(newVersionId);
recipeVersion.setVersionId(Integer.toString(newVersionId));
recipeVersion.setVersionDesc("Automatic schema generation");
recipeVersion.setTransId(Constants.CREATE_KEY);
recipeVersion.setTransPerformedby(user);
try {
recipeVersion = recipeService.createRecipeVersionWithEcn(recipeVersion,ecn);
} catch (Exception e) {
throw new SystemIllegalArgumentException(Errors.create().key(MessageIdList.SYSTEM_UPDATE_VERSION_ERROR)
.content("导入至 {},系统今日导入的版本已达最大值,请明日再试! ")
.args(recipe.getInstanceId()).build());
}
Collection versions = baseService.getObjectVersions(recipe);
ObjectVersion objectVersion = (ObjectVersion) versions.iterator().next();
recipeVersion.setVersionStatus(objectVersion.getVersionStatus());
recipe.setVersions(versions);
final char COMMA = ',';
final String PLUS = "\\+";
String chamberJoin = item.getChamberType();
StringBuffer sb = new StringBuffer();
String tempChamber = StringUtils.EMPTY;
if (StringUtils.isNotBlank(chamberJoin)) {
String chambers[] = chamberJoin.split(PLUS);
int len = chambers.length;
for (int i = 0; i < len; i++) {
tempChamber = chambers[i].trim().toUpperCase();
ReferenceFileDetail ref = this.getReferenceFileDetail("$CHAMBER_TYPE", tempChamber, facility);
if (ref != null) {
sb.append(chambers[i].trim().toUpperCase()).append(len - 1 > i ? COMMA : StringUtils.EMPTY);
} else {
item.addMassage(chambers[i] + " " + chamberComment);
}
}
// if the last char of the stringbuffer is a comma, delete it;
int lastIndex = sb.length() - 1;
if (lastIndex > 0 && sb.charAt(lastIndex) == COMMA) {
sb.deleteCharAt(lastIndex);
}
sb.append(RecipeVersion.CHAMBERSEPARATOR);
}
recipeVersion.setChamberTypes(sb.toString());
recipeVersion.setPpid(item.getPhysicalRecipeId());
recipeVersion.setRecipeComments(item.getRecipeFileUrl());
recipeVersion.setSetupId(StringUtils.EMPTY);
recipeVersion.setProcessTimePerHour(0L);
recipeVersion.setProcessTimePerUnit(0L);
recipeVersion.setTransId(Constants.MODIFY_KEY);
recipeVersion.setTransPerformedby(user);
this.process(recipeVersion);
/*recipeService.updateRecipeVersionExt(recipeVersion.getInstanceRrn(),
new Long(recipeVersion.getInstanceVersion()),
item.getEqtCapability());*/
recipeService.updateRecipeVersion(recipeVersion, String.valueOf(recipeVersion.getInstanceVersion()));
ecnService.activateEcn(recipeVersion.getEcnRrn(), user);
//绑定主recipe和子recipe
Recipe parentRecipe = null;
parentRecipe = recipeService.getRecipe(recipe.getParentRecipeId(), LocalContext.getFacilityRrn());
Relation relation = new Relation();
relation.setFromRrn(parentRecipe.getInstanceRrn());
relation.setLinkType(LinkTypeList.RECIPEFAMILY_TO_RECIPE);
relation.setToRrn(recipe.getInstanceRrn());
relation.setTransPerformedby(LocalContext.getUserId());
relation.setTransId(TransactionNames.CREATE_KEY);
recipeService.insertRelation4RecipeFamilyToRecipe(relation);
}
protected void changeRecipeStatusView(Recipe recipe, String user, Long userRrn) throws Exception {
if (StringUtils.isNotBlank(recipe.getAttributeData1())) {
Relation relation = new Relation();
relation.setTransId(Constants.UPDATE_KEY);
relation.setTransPerformedby(user);
relation.setLinkType(LinkTypeList.ENTITY_TO_RECIPE);
relation.setAttributedata2(String.valueOf(userRrn));
relation.setAttributedata3(timestampToLongString(new Date()));
recipeService.updateRecipesStatus(RecipeStatus.ON_KEY, RecipeStatus.EXIST_KEY, recipe.getInstanceRrn() + "",
relation);
recipeService.updateRecipesStatus(RecipeStatus.OFF_KEY, RecipeStatus.NOTEXIST_KEY, recipe.getInstanceRrn() + "",
relation);
} else {
Relation relation = new Relation();
relation.setTransId(Constants.UPDATE_KEY);
relation.setTransPerformedby(user);
relation.setLinkType(LinkTypeList.ENTITY_TO_RECIPE);
relation.setAttributedata2(String.valueOf(userRrn));
relation.setAttributedata3(timestampToLongString(new Date()));
recipeService.updateRecipesStatus(RecipeStatus.EXIST_KEY, RecipeStatus.ON_KEY,
recipe.getInstanceRrn() + "", relation);
recipeService.updateRecipesStatus(RecipeStatus.NOTEXIST_KEY, RecipeStatus.OFF_KEY,
recipe.getInstanceRrn() + "", relation);
}
}
}