package com.vci.starter.revision.service; import com.vci.starter.revision.bo.TreeWrapperOptions; import com.vci.starter.revision.model.*; import com.vci.starter.revision.provider.*; import com.vci.starter.web.annotation.Column; import com.vci.starter.web.annotation.VciBtmType; import com.vci.starter.web.annotation.VciColumnDefinition; import com.vci.starter.web.constant.RevisionConstant; import com.vci.starter.web.constant.RegExpConstant; import com.vci.starter.web.enumpck.DataSecretEnum; import com.vci.starter.web.enumpck.UserSecretEnum; import com.vci.starter.web.exception.VciBaseException; import com.vci.starter.web.model.BaseLinkModel; import com.vci.starter.web.model.BaseModel; import com.vci.starter.web.pagemodel.BaseResult; import com.vci.starter.web.pagemodel.PageHelper; import com.vci.starter.web.pagemodel.Tree; import com.vci.starter.web.pagemodel.TreeQueryObject; import com.vci.starter.web.service.VciSecretServiceI; import com.vci.starter.web.util.BeanUtil; import com.vci.starter.web.util.BeanUtilForVCI; import com.vci.starter.web.util.VciBaseUtil; import com.vci.starter.web.util.VciDateUtil; import com.vci.starter.web.wrapper.VciQueryWrapperForDO; import com.vci.starter.web.wrapper.VciQueryWrapperOption; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * 版本和对象模型的工具类 * @author weidy * @date 2020/4/15 */ @Component public class RevisionModelUtil implements VciSecretServiceI { /** * 日志对象 */ private Logger logger = LoggerFactory.getLogger(getClass()); /** * 存储对象类的属性的注释 */ public volatile static Map> modelColumnAnnotationMap = new ConcurrentHashMap<>(); /** * 实体类和注解的映射,在springboot热加载的时候一定要清除 */ public volatile static Map modelAnnotationMap = new ConcurrentHashMap<>(); /** * 判断幂等性,使用redis */ public static boolean CHECK_IDEMPOTENCE = false; /** * 版本的数据操作层 */ @Autowired(required = false) private VciRevisionServiceI revisionMapper; /** * 版本的调用器 */ @Autowired(required = false) private CommonRevisionRuleProvider revisionRuleProvider; /** * 生命周期的调用器 */ @Autowired(required = false) private CommonLifeCycleProvider lifeCycleProvider; /** * 注释的调用接口 */ @Autowired(required = false) private CommonAnnotationProvider annotationProvider; /** * 是最新版本的值 */ public static final String LAST_REV_VALUE = "1"; /** * 不是最新版本的值 */ public static final String UN_LAST_REV_VALUE = "0"; /** * 在数据新增的时候封装属性(包括创建者和生命周期等),并且校验必输项,唯一项(其中唯一项对于时间无法判断),密级 * @param baseModel 基础数据对象 */ public void wrapperForAdd(BaseModel baseModel){ wrapperForAddOrUpVersion(baseModel,false,false); } /** * 批量添加数据 * @param baseModelCollection 数据对象集合 */ public void wrapperForBatchAdd(Collection baseModelCollection ){ VciBaseUtil.alertCollectionNotNull("要新增的数据对象",baseModelCollection); BaseModel fristModel = baseModelCollection.iterator().next(); VciBtmType vciBtmType = getBtmTypeAnnotation(fristModel); if(vciBtmType == null){ throw new VciBaseException("实体对象上没有添加VciBtmType注解"); } //有column注解的属性,有这个注解才需要校验必输项和唯一项 List hasColumnAnnoFields = filterHasColumnAnnoFields(VciBaseUtil.getAllFieldForObj(fristModel.getClass())); //必输项 List checkNullFields = filterCheckNullFields(hasColumnAnnoFields); //唯一项的,包含不区分大小写和区分大小写的 Map checkUniqueFieldsMap = filterCheckUniqueFieldsHasUnCase(fristModel.getClass()); //唯一的属性的值 Map> unqiueFieldValueMap = new HashMap<>(); String creator = VciBaseUtil.getCurrentUserId(); Date currentDate= new Date(); String btmName = vciBtmType.name(); //获取默认的版本号,生命周期,密级 wrapperFristRevision(fristModel); wrapperLifeCycle(fristModel); boolean manageRevision = isManageRevision(vciBtmType); boolean manageLifeCycle = isManageLifeCycle(vciBtmType); boolean checkSecret = isCheckSecret(vciBtmType); //遍历,实际也是每一个处理一次,只是版本和生命周期等不重复获取 baseModelCollection.stream().forEach(s -> { VciBaseUtil.alertNotNull(s,"要添加的数据对象"); setBaseFieldValue(s,creator,currentDate,btmName); //校验必输项 checkFieldsRequired(checkNullFields,s); //先判断当前集合中唯一项是否有重复 if(!CollectionUtils.isEmpty(checkUniqueFieldsMap)){ checkUniqueFieldsMap.forEach( (field,unCase) ->{ checkUniqueValues(field,unCase,s,unqiueFieldValueMap,false); }); } //因为新增都一定是第一个版本和版次,所以如果没有设置的时候,全部用初始版本号 if(manageRevision){ if(StringUtils.isBlank(s.getNameOid())){ s.setNameOid(VciBaseUtil.getPk()); } if(StringUtils.isBlank(s.getRevisionOid())){ s.setRevisionOid(VciBaseUtil.getPk()); } s.setRevisionRule(fristModel.getRevisionRule()); s.setRevisionValue(fristModel.getRevisionValue()); s.setRevisionSeq(1); s.setFirstR("1"); s.setLastR("1"); s.setVersionRule(fristModel.getVersionRule()); s.setVersionValue(fristModel.getVersionValue()); s.setVersionSeq(1); s.setLastV("1"); s.setFirstV("1"); } if(manageLifeCycle && StringUtils.isBlank(s.getLcStatus())){ s.setLcStatus(fristModel.getLcStatus()); } if(checkSecret){ checkDataSecret(s); } }); } /** * 在数据修改的时候封装属性 * @param baseModel 基础数据对象 */ public void wrapperForEdit(BaseModel baseModel){ VciBaseUtil.alertNotNull(baseModel,"要修改的数据对象",baseModel.getOid(),"数据的主键"); Date currentDate = new Date(); baseModel.setTs(currentDate); baseModel.setLastModifier(VciBaseUtil.getCurrentUserId()); baseModel.setLastModifyTime(currentDate); // VciBtmType vciBtmType = getBtmTypeAnnotation(baseModel); if(StringUtils.isBlank(baseModel.getBtmname()) && vciBtmType!=null){ baseModel.setBtmname(vciBtmType.name()); } //获取包含了column注解的属性,因为不包含这个注解的时候是默认nullable为true,unique为false List hasColumnAnnoFields = filterHasColumnAnnoFields(baseModel); //判断是否有空的属性 checkFieldsRequired(filterCheckNullFields(hasColumnAnnoFields),baseModel); Map checkUniqueFields = filterCheckUniqueFieldsHasUnCase(hasColumnAnnoFields); if(!CollectionUtils.isEmpty(checkUniqueFields)){ checkUniqueFields.forEach((field,unCase) ->{ checkUniqueValues(field,unCase,baseModel,new HashMap<>(),true); }); } //校验密级 checkDataSecret(baseModel); //修改的时候版本号和生命周期不应该变化 } /** * 批量修改数据对象时封装属性,包括唯一项,必输项和基本属性设置 * @param baseModelCollection 数据对象集合 */ public void wrapperForBatchEdit(List baseModelCollection){ VciBaseUtil.alertCollectionNotNull("要修改的数据对象",baseModelCollection); BaseModel fristModel = baseModelCollection.iterator().next(); VciBtmType vciBtmType = getBtmTypeAnnotation(fristModel); if(vciBtmType == null){ throw new VciBaseException("实体对象上没有添加VciBtmType注解"); } //有column注解的属性,有这个注解才需要校验必输项和唯一项 List hasColumnAnnoFields = filterHasColumnAnnoFields(VciBaseUtil.getAllFieldForObj(fristModel.getClass())); //必输项 List checkNullFields = filterCheckNullFields(hasColumnAnnoFields); //唯一项的,包含不区分大小写和区分大小写的 Map checkUniqueFieldsMap = filterCheckUniqueFieldsHasUnCase(fristModel.getClass()); //唯一的属性的值 Map> unqiueFieldValueMap = new HashMap<>(); String creator = VciBaseUtil.getCurrentUserId(); Date currentDate= new Date(); String btmName = vciBtmType.name(); boolean checkSecret = isCheckSecret(vciBtmType); //遍历,实际也是每一个处理一次,只是版本和生命周期等不重复获取 baseModelCollection.stream().forEach(s -> { VciBaseUtil.alertNotNull(s,"要添加的数据对象"); setBaseFieldValueEdit(s,creator,currentDate); //校验必输项 checkFieldsRequired(checkNullFields,s); //先判断当前集合中唯一项是否有重复 if(!CollectionUtils.isEmpty(checkUniqueFieldsMap)){ checkUniqueFieldsMap.forEach( (field,unCase) ->{ checkUniqueValues(field,unCase,s,unqiueFieldValueMap,true); }); } //修改的时候,版本和生命周期都不能修改,密级需要修改,所以需要再次校验 if(checkSecret){ checkDataSecret(s); } }); } /** * 升版本号 * @param baseModel 数据对象 */ public void wrapperForUpRevision(BaseModel baseModel){ wrapperForAddOrUpVersion(baseModel,true,false); } /** * 升版次 * @param baseModel 数据对象 */ public void wrapperForUpVersion(BaseModel baseModel){ wrapperForAddOrUpVersion(baseModel,true,true); } /** * 在修改的时候拷贝,防止前端没有传递默认的属性 * @param dto 数据传输对象 * @param baseModel 数据库中的数据对象 */ public void copyFromDTO(Object dto,BaseModel baseModel){ VciBaseUtil.alertNotNull(dto,"数据传输对象",baseModel,"数据库中的数据对象"); //前端可能不会把默认的所有属性传递过来,所以先从数据库中的数据对象拷贝到临时的对象上 BaseModel tempModel = new BaseModel(); BeanUtil.convert(baseModel,tempModel); BeanUtil.convert(dto,baseModel); //BeanUtil.convert(tempModel,baseModel); //不知道为啥,突然BeanUtil.convert(tempModel,baseModel);不好使了 BeanUtilForVCI.copyPropertiesIgnoreCase(tempModel,baseModel); //为了防止前端没有传递默认的属性,所以得先拷贝到baseModel中,然后dto拷贝一次后,再把数据库中拷贝回来。 //但是因为id,name,description极大概率前端会传递,所以这里也设置一下 baseModel.setId(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("id",dto))); baseModel.setName(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("name",dto))); baseModel.setDescription(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("description",dto))); tempModel = null; } /** * 从DTO上拷贝,忽略属性大小写 * @param dto DTO对象 * @param baseModel 目标对象 */ public void copyFromDTOIgnore(Object dto,BaseModel baseModel){ VciBaseUtil.alertNotNull(dto,"数据传输对象",baseModel,"数据库中的数据对象"); //前端可能不会把默认的所有属性传递过来,所以先从数据库中的数据对象拷贝到临时的对象上 BaseModel tempModel = new BaseModel(); BeanUtilForVCI.copyPropertiesIgnoreCase(baseModel,tempModel); BeanUtilForVCI.copyPropertiesIgnoreCase(dto,baseModel); BeanUtilForVCI.copyPropertiesIgnoreCase(tempModel,baseModel); //为了防止前端没有传递默认的属性,所以得先拷贝到baseModel中,然后dto拷贝一次后,再把数据库中拷贝回来。 //但是因为id,name,description极大概率前端会传递,所以这里也设置一下 baseModel.setId(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("id",dto))); baseModel.setName(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("name",dto))); baseModel.setDescription(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("description",dto))); tempModel = null; } /** * 在数据新增的时候为链接类型封装属性 * @param linkModel 链接类型数据对象 */ public void wrapperForAddLink(BaseLinkModel linkModel){ VciBaseUtil.alertNotNull(linkModel,"要新增的链接类型数据对象"); if(StringUtils.isBlank(linkModel.getOid())){ linkModel.setOid(VciBaseUtil.getPk()); } linkModel.setCreator(VciBaseUtil.getCurrentUserId()); Date currentDate = new Date(); linkModel.setCreateTime(currentDate); linkModel.setTs(currentDate); linkModel.setLastModifier(linkModel.getCreator()); linkModel.setLastModifytime(currentDate); } /** * 在新增数据的时候为链接类型封装属性 * @param linkModel 链接类型对象 * @param fromModel from端业务数据 * @param toModel to端业务数据 */ public void wrapperForAddLink(BaseLinkModel linkModel,BaseModel fromModel,BaseModel toModel){ wrapperForAddLink(linkModel); VciBaseUtil.alertNotNull(fromModel,"链接类型from端",toModel,"链接类型to端"); linkModel.setFoid(fromModel.getOid()); linkModel.setFbtmname(fromModel.getBtmname()); linkModel.setFnameoid(fromModel.getNameOid()); linkModel.setToid(toModel.getOid()); linkModel.setTbtmname(toModel.getBtmname()); linkModel.setTnameoid(toModel.getNameOid()); linkModel.setTrevisionoid(toModel.getRevisionOid()); } /** * 在数据修改的时候为链接类型封装属性 * @param linkModel 基础数据对象 */ public void wrapperForEditLink(BaseLinkModel linkModel){ VciBaseUtil.alertNotNull(linkModel,"要修改的链接类型数据对象"); Date currentDate = new Date(); linkModel.setTs(currentDate); linkModel.setLastModifier(VciBaseUtil.getCurrentUserId()); linkModel.setLastModifytime(currentDate); } /** * 判断时间戳是否相同 * @param dtoTs 数据传输对象上的ts * @param doTs 数据对象上的ts * @return true表示相同 */ public boolean checkTs(Date dtoTs,Date doTs){ if(dtoTs!=null && doTs!=null){ if(dtoTs.getTime() == doTs.getTime()){ return true; } String dtoTsString = VciDateUtil.date2Str(dtoTs,VciDateUtil.DateTimeMillFormat); String doTsString = VciDateUtil.date2Str(doTs,VciDateUtil.DateTimeMillFormat); if(dtoTsString.equalsIgnoreCase(doTsString)){ return true; }else{ throw new VciBaseException("tsNotEqual"); } } return false; } /** * 判断密级是否符合要求 * @param baseModel 数据对象 * @return true 表示符合要求 * @throws VciBaseException 不符合要求时会抛出异常 */ public boolean checkDataSecret(BaseModel baseModel) throws VciBaseException{ VciBaseUtil.alertNotNull(baseModel,"要校验密级的数据对象"); //todo 登录还未启用,所以密级无法获取需要修改 // if(isCheckSecret(baseModel) && VciBaseUtil.getCurrentUserSecret()>0) { // if (baseModel.getSecretGrade() == null ) { // baseModel.setSecretGrade(DataSecretEnum.NONE.getValue()); // } // Integer userSecret = VciBaseUtil.getCurrentUserSecret(); // if (!checkUserSecret(baseModel.getSecretGrade())) { // throw new VciBaseException("当前用户的密级低于数据的密级,用户密级为" + UserSecretEnum.getSecretText(userSecret) + ",数据密级为" + DataSecretEnum.getSecretText(baseModel.getSecretGrade())); // } // } return true; } /** * 发布当前版本 * @param baseModel 要发布的数据对象 */ public void saveRelease(BaseModel baseModel){ VciBaseUtil.alertNotNull(baseModel,"数据对象"); VciBtmType btmType = getBtmTypeAnnotation(baseModel); if(isManageRevision(btmType)) { //必须管理版本才会执行发布 VciBaseUtil.alertNotNull( baseModel.getOid(), "数据对象的主键", baseModel.getNameOid(), "对象的主键",baseModel.getRevisionOid(),"版本的主键"); ReleasedObjDO releasedObjDO = new ReleasedObjDO(); BeanUtil.convert(baseModel,releasedObjDO); if(StringUtils.isBlank(releasedObjDO.getBtmName())){ releasedObjDO.setBtmName(btmType.name()); } revisionMapper.saveReleased(releasedObjDO); } } /** * 数据新增的时候封装属性,可以升版本,可以升版次 * @param baseModel 数据对象 * @param upRevsion 升版号 * @param upVersion 升版次 */ private void wrapperForAddOrUpVersion(BaseModel baseModel,boolean upRevsion,boolean upVersion){ VciBaseUtil.alertNotNull(baseModel,"数据对象"); //封装基本属性 setBaseFieldValue(baseModel); //校验必输项和唯一项 List fields = VciBaseUtil.getAllFieldForObj(baseModel.getClass()); if(!CollectionUtils.isEmpty(fields)){ //获取包含了column注解的属性,因为不包含的默认nullable为true,unique为false List hasColumnAnnoFields = fields.stream().filter(s->s.isAnnotationPresent(Column.class)).distinct().collect(Collectors.toList()); if(!CollectionUtils.isEmpty(hasColumnAnnoFields)){ //分离出需要判断是否为空的字段 List notNullFields = filterCheckNullFields(hasColumnAnnoFields); //判断是否有空的属性 checkFieldsRequired(notNullFields,baseModel); Map checkUniqueFields = filterCheckUniqueFieldsHasUnCase(hasColumnAnnoFields); if(!CollectionUtils.isEmpty(checkUniqueFields)){ checkUniqueFields.forEach((field,unCase) ->{ checkUniqueValues(field,unCase,baseModel,new HashMap<>(),false); }); } } } //校验密级 checkDataSecret(baseModel); //处理生命周期 wrapperLifeCycle(baseModel); //如果控制版本,会创建第一个版本 if(isManageRevision(baseModel)) { if(!upVersion) { if (StringUtils.isBlank(baseModel.getCopyFromVersion()) && !upRevsion) { //说明是新增 wrapperFristRevision(baseModel); } else { //说明是升版号 wrapperRevisionModel(baseModel); } }else { wrapperVersionModel(baseModel); } } } /** *处理基本属性 * @param baseModel 数据对象 */ public void setBaseFieldValue(BaseModel baseModel){ VciBaseUtil.alertNotNull(baseModel,"数据对象"); setBaseFieldValue(baseModel,null,null,null); } /** * 处理基本属性 * @param currentUserId 当前用户 * @param currentDate 当前时间 * @param btmName 业务类型名称 * @param baseModel 数据对象 */ public void setBaseFieldValue(BaseModel baseModel,String currentUserId,Date currentDate,String btmName){ if(StringUtils.isBlank(currentUserId)){ currentUserId = VciBaseUtil.getCurrentUserId(); } if(currentDate == null){ currentDate = new Date(); } if(StringUtils.isBlank(btmName)){ btmName = VciBaseUtil.getBtmTypeNameFromDO(baseModel.getClass()); } //处理基本属性 if(StringUtils.isBlank(baseModel.getOid())){ baseModel.setOid(VciBaseUtil.getPk()); } if(StringUtils.isBlank(baseModel.getCreator())) { baseModel.setCreator(currentUserId); } baseModel.setCreateTime(currentDate); baseModel.setTs(currentDate); if(StringUtils.isBlank(baseModel.getLastModifier())) { baseModel.setLastModifier(currentUserId); } baseModel.setLastModifyTime(currentDate); if(StringUtils.isBlank(baseModel.getOwner())) { baseModel.setOwner(baseModel.getCreator()); } baseModel.setBtmname(btmName); } /** * 编辑的时候处理基本属性 * @param baseModel 数据对象 * @param currentUserId 当前用户 * @param currentDate 当前时间 */ public void setBaseFieldValueEdit(BaseModel baseModel,String currentUserId,Date currentDate){ if(StringUtils.isBlank(currentUserId)){ currentUserId = VciBaseUtil.getCurrentUserId(); } if(currentDate == null){ currentDate = new Date(); } baseModel.setTs(currentDate); baseModel.setLastModifier(currentUserId); baseModel.setLastModifyTime(currentDate); } /** * 批量执行的时候,校验唯一项 * @param field 属性 * @param unCase 是否不区分大小写 * @param baseModel 数据对象 * @param unqiueFieldValueMap 存在的数据集合 * @param edit 是否为修改 */ private void checkUniqueValues(Field field,Boolean unCase,BaseModel baseModel, Map> unqiueFieldValueMap ,boolean edit){ field.setAccessible(true); String fieldName = field.getName(); Set fieldValueList ; if(unqiueFieldValueMap.containsKey(fieldName)){ fieldValueList = unqiueFieldValueMap.get(fieldName); }else{ fieldValueList = new HashSet<>(); } Object fieldValue = null; try { fieldValue = field.get(baseModel); } catch (IllegalAccessException e) { if(logger.isDebugEnabled()){ logger.debug("获取属性的值出现了错误,{}",fieldName); } } if(fieldValue!=null){ if(unCase !=null && unCase){ fieldValue = fieldValue.toString().toLowerCase(); } if(fieldValueList.contains(fieldValue) || (unCase?checkFieldNotUniqueUnCase(field,baseModel,edit):checkFieldNotUnique(field,baseModel,edit))){ throw new VciBaseException("dataRepeat",new String[]{getColumnChineseText(field),fieldValue.toString()}); }else{ fieldValueList.add(fieldValue); } } unqiueFieldValueMap.put(fieldName,fieldValueList); } /** * 封装新的版本信息,会自动处理老的版本和最新版本的问题 * @param newModel 新版本的数据对象 * @throws VciBaseException 参数错误,无注解,服务配置不正确的时候会抛出异常 */ public void wrapperRevisionModel(BaseModel newModel) throws VciBaseException{ setBtmName(newModel); VciBaseUtil.alertNotNull(newModel.getCopyFromVersion(),"引用老版本的主键"); if (revisionMapper != null) { RevisionInfo oldRevision = revisionMapper.selectByOid(newModel.getCopyFromVersion(),VciBaseUtil.getTableName(newModel.getBtmname())); if(oldRevision == null || StringUtils.isBlank(oldRevision.getOid()) ){ throw new VciBaseException("老版本在数据库中不存在"); } BaseModel oldModel = new BaseModel(); BeanUtil.convert(oldRevision,oldModel); wrapperRevisionModel(oldModel,newModel); }else{ throw new VciBaseException("没有初始化版本规则的数据操作层,请开发人员检查Maven是否引用"); } } /** * 封装新的版次信息,会自动处理老的版次和最新版次问题 * @param newModel 新版次的数据对象 * @throws VciBaseException 参数错误,缺少注解,配置错误都会抛出这个异常 */ public void wrapperVersionModel(BaseModel newModel) throws VciBaseException{ VciBaseUtil.alertNotNull(newModel,"新版次的数据对象",newModel.getCopyFromVersion(),"引用老版次的主键"); if (revisionMapper != null) { RevisionInfo oldRevision = revisionMapper.selectByOid(newModel.getCopyFromVersion(),VciBaseUtil.getTableName(newModel.getBtmname())); if(oldRevision == null || StringUtils.isBlank(oldRevision.getOid()) ){ throw new VciBaseException("老版次数据在数据库中不存在"); } BaseModel oldModel = new BaseModel(); BeanUtil.convert(oldRevision,oldModel); wrapperVersionModel(oldModel,newModel); }else{ throw new VciBaseException("没有初始化版本规则的数据操作层,请开发人员检查Maven是否引用"); } } /** * 获取数据对象中所有包含了column列的属性 * @param baseModel 数据对象 * @return 没有时会返回Null */ public List filterHasColumnAnnoFields(BaseModel baseModel){ List fields = VciBaseUtil.getAllFieldForObj(baseModel.getClass()); return filterHasColumnAnnoFields(fields); } /** * 过滤包含了column的属性 * @param fields 所有的属性 * @return 符合条件的属性,不存在的时候会返回null */ public List filterHasColumnAnnoFields( List fields){ if(!CollectionUtils.isEmpty(fields)) { return fields.stream().filter(s -> s.isAnnotationPresent(Column.class)).distinct().collect(Collectors.toList()); }else{ return null; } } /** * 过滤需要校验是否输入的属性 * @param fields 包含有column注解的属性 * @return 符合条件的属性,不存在的时候会返回null */ public List filterCheckNullFields(List fields){ if(!CollectionUtils.isEmpty(fields)){ return fields.stream().filter(s -> { Column column = getColumnAnnotation(s); //指定了不能为空,或者需要校验唯一的一定不能为空 return ((column != null && column.nullable()) == false) || ((column != null && column.unique()) == true); }).collect(Collectors.toList()); } return null; } /** * 获取校验唯一项,包含 区分大小写唯一项的属性 * @param doClass 数据对象所属的类 * @return 属性映射,key是属性对象,value的值为true表示不区分大小写的方式校验唯一项 */ public Map filterCheckUniqueFieldsHasUnCase(Class doClass){ List hasColumnAnnoFields = filterHasColumnAnnoFields(VciBaseUtil.getAllFieldForObj(doClass)); return filterCheckUniqueFieldsHasUnCase(hasColumnAnnoFields); } /** * 获取校验唯一项,包含 区分大小写唯一项的属性 * @param hasColumnAnnoFields 数据对象所属的类 * @return 属性映射,key是属性对象,value的值为true表示不区分大小写的方式校验唯一项 */ public Map filterCheckUniqueFieldsHasUnCase(List hasColumnAnnoFields){ //唯一项的,包含不区分大小写和区分大小写的 Map checkUniqueFieldsMap = new HashMap<>(); List checkUniqueFields = filterCheckUniqueFields(hasColumnAnnoFields); if(!CollectionUtils.isEmpty(checkUniqueFields)){ checkUniqueFields.stream().forEach(s -> { checkUniqueFieldsMap.put(s,false); }); } List checkUniqueUnCaseFields = filterCheckUniqueUnCaseFields(hasColumnAnnoFields); if(!CollectionUtils.isEmpty(checkUniqueUnCaseFields)){ checkUniqueUnCaseFields.stream().forEach(s -> { //这个是不区分大小写 checkUniqueFieldsMap.put(s,true); }); } return checkUniqueFieldsMap; } /** * 获取需要校验唯一的属性 * @param fields 包含有column注解的属性 * @return 符合条件的属性,不存在的时候会返回null */ public List filterCheckUniqueFields(List fields){ if(!CollectionUtils.isEmpty(fields)){ return fields.stream().filter(s -> { Column column = getColumnAnnotation(s); return (column != null && column.unique()) == true; }).collect(Collectors.toList()); } return null; } /** * 获取需要校验唯一的属性 * @param fields 包含有column注解的属性 * @return 符合条件的属性,不存在的时候会返回null */ public List filterCheckUniqueUnCaseFields(List fields){ if(!CollectionUtils.isEmpty(fields)){ return fields.stream().filter(s -> { Column column = getColumnAnnotation(s); return (column != null && column.unique() && column.unUniqueCase()) == true; }).collect(Collectors.toList()); } return null; } /** * 校验属性的值是否唯一 * @param uniqueFields 需要校验唯一的属性值 * @param baseModel 数据对象 * @param editFlag 是否为修改数据,修改的时候需要排除当前数据 */ public void checkFieldsUnique(List uniqueFields, BaseModel baseModel, boolean editFlag) { if(!CollectionUtils.isEmpty(uniqueFields)){ List notUniqueFields = uniqueFields.stream().filter( s -> checkFieldNotUnique(s,baseModel,editFlag)).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(notUniqueFields)){ //找对应的中文名称 List notUniqueFieldChineseNames = new ArrayList<>(); notUniqueFields.stream().forEach( s -> { //先从注释中上获取,但是怕的是之前没有注释,所以可能得从注解上获取 notUniqueFieldChineseNames.add(getColumnChineseText(s)); }); //按理说这个错误信息不应该出现的,所以不做多语 throw new VciBaseException("属性[" + notUniqueFieldChineseNames.stream().collect(Collectors.joining(",")) + "]对应的数据在系统中已经存在",notUniqueFieldChineseNames.toArray()); } } } /** * 校验属性的值是否唯一,不区分属性值的大小写 * @param uniqueFields 需要校验唯一的属性值 * @param baseModel 数据对象 * @param editFlag 是否为修改数据,修改的时候需要排除当前数据 */ public void checkFieldsUnUniqueCase(List uniqueFields, BaseModel baseModel, boolean editFlag){ if(!CollectionUtils.isEmpty(uniqueFields)){ List notUniqueFields = uniqueFields.stream().filter( s -> checkFieldNotUniqueUnCase(s,baseModel,editFlag)).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(notUniqueFields)){ //找对应的中文名称 List notUniqueFieldChineseNames = new ArrayList<>(); notUniqueFields.stream().forEach( s -> { //先从注释中上获取,但是怕的是之前没有注释,所以可能得从注解上获取 notUniqueFieldChineseNames.add(getColumnChineseText(s)); }); //按理说这个错误信息不应该出现的,所以不做多语 throw new VciBaseException("属性[" + notUniqueFieldChineseNames.stream().collect(Collectors.joining(",")) + "]对应的数据在系统中已经存在",notUniqueFieldChineseNames.toArray()); } } } /** * 检查属性是否唯一 * @param field 需要校验的属性对象 * @param baseModel 数据对象 * @param editFlag 是否为修改数据,修改的时候需要排除当前数据 * @return true表示不唯一,false唯一 */ public boolean checkFieldNotUnique(Field field,BaseModel baseModel,boolean editFlag){ return checkFieldNotUnique(field,baseModel,editFlag,false); } /** * 检查属性是否唯一,并且不区分大小写 * @param field 需要校验的属性对象 * @param baseModel 数据对象 * @param editFlag 是否为修改数据,修改的时候需要排除当前数据 * @return true表示不唯一,false唯一 */ public boolean checkFieldNotUniqueUnCase(Field field,BaseModel baseModel,boolean editFlag){ return checkFieldNotUnique(field,baseModel,editFlag,true); } /** * 检查属性是否唯一,可以设置不区分大小写 * @param field 需要校验的属性对象 * @param baseModel 数据对象 * @param editFlag 是否为修改数据,修改的时候需要排除当前数据 * @param unCase 不区分大小写 * @return true表示不唯一,false唯一 */ private boolean checkFieldNotUnique(Field field,BaseModel baseModel,boolean editFlag,boolean unCase){ String btmType = VciBaseUtil.getBtmTypeNameFromDO(baseModel.getClass()); String className = baseModel.getClass().getName(); String columnName =VciBaseUtil.getCboAttrNameFromField(field,baseModel.getClass()); String tableName = VciBaseUtil.getTableName(btmType); Object columnValue = null; String oid = ""; if(editFlag){ oid = baseModel.getOid(); } field.setAccessible(true); try { columnValue = field.get(baseModel); } catch (IllegalAccessException e) { String msg = "判断某个对象的属性是否重复时出现了错误"; if(logger.isErrorEnabled()) { logger.error(msg + ",{}.{}", className, field.getName(), e); } throw new VciBaseException(msg + "{0},{1}",new String[]{className,field.getName()},e); } if(unCase && columnValue instanceof String){ //只有字符串才有大小写,日期和数字这些不支持 columnName = "lower(" + columnName + ")"; columnValue = columnValue.toString().toLowerCase(); } int count; if(editFlag){ count= revisionMapper.countByPropertiesNotIncludeSelf(columnName, columnValue, tableName, oid); }else{ count = revisionMapper.countByProperties(columnName,columnValue,tableName); } if(count>0){ return true; } return false; } /** * 判断数据是否为空 * @param notNullFields 需要判断的属性 * @param baseModel 数据对象 */ public void checkFieldsRequired(List notNullFields, BaseModel baseModel) { if(!CollectionUtils.isEmpty(notNullFields)){ String className = baseModel.getClass().getName(); List nullValueFields = notNullFields.stream().filter( s -> checkFieldValueNull(s,baseModel)).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(nullValueFields)){ //找对应的中文名称 List nullFieldChineseNames = new ArrayList<>(); nullValueFields.stream().forEach( s -> { //先从注释中上获取,但是怕的是之前没有注释,所以可能得从注解上获取 nullFieldChineseNames.add(getColumnChineseText(s)); }); //按理说这个错误信息不应该出现的,所以不做多语 throw new VciBaseException("属性[" + nullFieldChineseNames.stream().collect(Collectors.joining(",")) + "]不能为空",nullFieldChineseNames.toArray()); } } } /** * 校验属性为空 * @param field 属性对象 * @param baseModel 数据对象 * @return true表示为空,false表示不为空 */ public boolean checkFieldValueNull(Field field,BaseModel baseModel){ String className = baseModel.getClass().getName(); field.setAccessible(true); try { Object value = field.get(baseModel); if(value == null || (value instanceof String) && StringUtils.isBlank((String)value)){ return true; } } catch (IllegalAccessException e) { String msg = "判断某个对象的属性是否为空时出现了错误"; if(logger.isErrorEnabled()) { logger.error(msg + ",{}.{}", className, field.getName(), e); } throw new VciBaseException(msg + "{0},{1}",new String[]{className,field.getName()},e); } return false; } /** * 获取 * @param field 属性对象 * @return 中文名称,优先取注释,否则取注解,最后返回属性的英文名称 */ public String getColumnChineseText(Field field){ String className = field.getDeclaringClass().getName(); if(modelColumnAnnotationMap.containsKey(className) && modelColumnAnnotationMap.get(className.toLowerCase()).containsKey(field.getName().toLowerCase())){ return modelColumnAnnotationMap.get(className.toLowerCase()).get(field.getName().toLowerCase()); }else{ Column column = getColumnAnnotation(field); if(column!=null && StringUtils.isNotBlank(column.columnDefinition())){ return column.columnDefinition(); }else{ //看看columnDefinition注解 if(field.isAnnotationPresent(VciColumnDefinition.class)){ VciColumnDefinition columnDefinition = field.getDeclaredAnnotation(VciColumnDefinition.class); if(columnDefinition == null){ columnDefinition = field.getAnnotation(VciColumnDefinition.class); } if(columnDefinition!=null) { return columnDefinition.value(); } } } return field.getName(); } } /** * 获取数据对象上的列注解 * @param field 字段的属性对象 * @return 没有注解的时候返回空,否则返回对应的注解 */ public Column getColumnAnnotation(Field field){ if(field.isAnnotationPresent(Column.class)) { Column column = field.getDeclaredAnnotation(Column.class); if (column == null) { column = field.getAnnotation(Column.class); } return column; } return null; } /** * 校验是否控制密级 * @param doObject 数据对象 * @return true需要校验密级 */ public boolean isCheckSecret(BaseModel doObject){ VciBtmType btmType = getBtmTypeAnnotation(doObject); return isCheckSecret(btmType); } /** * 校验是否控制密级 * @param btmType 业务类型的注解 * @return true需要校验密级 */ public boolean isCheckSecret(VciBtmType btmType){ if(btmType !=null && btmType.secretAble()){ return true; } return false; } /** * 封装新的版本信息,会自动处理老的版本和最新版本的问题 * @param oldModel 老版本的数据对象 * @param newModel 新版本的数据对象 * @throws VciBaseException 参数错误,缺少注解,配置错误都会抛出这个异常 */ public void wrapperRevisionModel(BaseModel oldModel, BaseModel newModel) throws VciBaseException { VciBaseUtil.alertNotNull(oldModel,"老版本的数据对象",newModel,"新版本的数据对象"); VciBtmType btmType = getBtmTypeAnnotation(newModel); if(btmType == null){ throw new VciBaseException("没有VciBtmType注解,无法判断是否控制版本"); }else { if ( isManageRevision(btmType)) { //升版的前提是有版本规则,并且如果是手动输入的时候,必须从前端输入值。 //1. 主键不能相同 if (StringUtils.isBlank(newModel.getOid()) || newModel.getOid().equalsIgnoreCase(oldModel.getOid())) { newModel.setOid(VciBaseUtil.getPk()); } //2.nameOid要相同 newModel.setNameOid(oldModel.getNameOid()); //2.1 revisionOid不相同 newModel.setRevisionOid(VciBaseUtil.getPk()); //查找最后一个版本的版本值 RevisionInfo lastRevision = null; if (revisionMapper != null) { lastRevision = revisionMapper.selectLastRevision(newModel.getNameOid(),VciBaseUtil.getTableName(btmType.name())); } else { //没有这个,那就直接用oldModel去获取版本号 lastRevision = new RevisionInfo(); BeanUtil.convert(oldModel, lastRevision); } newModel.setRevisionRule(lastRevision.getRevisionRule()); newModel.setVersionRule(lastRevision.getVersionRule()); //3.版本号 if(StringUtils.isBlank(newModel.getRevisionValue()) && !isInputRevision(newModel) && StringUtils.isBlank(lastRevision.getRevisionRule())){ //不处理 }else { if (StringUtils.isBlank(newModel.getRevisionValue())) { wrapperRevisionValue(newModel, btmType, lastRevision); } } //如果有版次,那这个就是新版本的第一个版次 if (isManageVersion(btmType)) { wrapperFristVersion(newModel); }else{ //可能没有处理版次,但是必须要添加上 newModel.setFirstV("1"); newModel.setLastV("1"); } //4.新的版本顺序 newModel.setRevisionSeq(lastRevision.getRevisionSeq() + 1); newModel.setLastR("1"); newModel.setFirstR("0"); //5.修改老的版本的isLastR saveOldModel(oldModel); //而且可能oldModel不是最后的那个版本 } //支持可以使用版本规则生成,也同时可以手动输入,所以当手动输入而值又没有的时候需要新生成 } } /** * 封装新的版次信息,会自动处理老的版次和最新版次问题 * @param oldModel 老版次的数据对象 * @param newModel 新版次的数据对象 * @throws VciBaseException 参数错误,缺少注解,配置错误都会抛出这个异常 */ public void wrapperVersionModel(BaseModel oldModel, BaseModel newModel) throws VciBaseException { VciBaseUtil.alertNotNull(oldModel,"老版次的数据对象",newModel,"新版次的数据对象"); VciBtmType btmType = getBtmTypeAnnotation(newModel); if(btmType == null){ throw new VciBaseException("没有VciBtmType注解,无法判断是否控制版次"); }else { if (isManageVersion(btmType)) { //才处理新的版次 //主键不能相同,nameoid和revisionoid必须相同 if (StringUtils.isBlank(newModel.getOid()) || newModel.getOid().equalsIgnoreCase(oldModel.getOid())) { newModel.setOid(VciBaseUtil.getPk()); } if(StringUtils.isBlank(newModel.getNameOid()) || !newModel.getNameOid().equalsIgnoreCase(oldModel.getNameOid())){ newModel.setNameOid(oldModel.getNameOid()); } if(StringUtils.isBlank(newModel.getRevisionOid()) || !newModel.getRevisionOid().equalsIgnoreCase(oldModel.getRevisionOid())){ newModel.setRevisionOid(oldModel.getRevisionOid()); } //查询这个相同的版本下的最新版次 RevisionInfo lastRevision = null; if (revisionMapper != null) { lastRevision = revisionMapper.selectLastVersion(newModel.getNameOid(),newModel.getRevisionOid(),VciBaseUtil.getTableName(btmType.name())); } else { //没有这个,那就直接用oldModel去获取版本号 lastRevision = new RevisionInfo(); BeanUtil.convert(oldModel, lastRevision); } //版次号,就数字和字母两种 if(oldModel.getVersionValue().matches(RegExpConstant.LETTER)){ //说明是字母的 newModel.setVersionValue(String.valueOf((char)(oldModel.getVersionValue().toCharArray()[0] + 1))); }else{ newModel.setVersionValue(String.valueOf(Integer.valueOf(oldModel.getVersionValue()) + 1)); } newModel.setVersionSeq(lastRevision.getVersionSeq() + 1); newModel.setVersionRule(oldModel.getVersionRule()); newModel.setLastV("1"); newModel.setFirstV("0"); //处理老版次 saveOldModelVersion(oldModel); } } } /** * 处理业务类型的名称 * @param baseModel 数据对象 */ private void setBtmName(BaseModel baseModel){ VciBaseUtil.alertNotNull(baseModel,"数据对象"); if(StringUtils.isBlank(baseModel.getBtmname())){ VciBtmType btmType = getBtmTypeAnnotation(baseModel); if(btmType == null){ throw new VciBaseException("没有VciBtmType注解,无法判断业务类型"); } baseModel.setBtmname(btmType.name()); } } /** * 保存旧的版本,会自动把以前最新版本的哪条数据修改,同时会把老的这条版本修改 * @param oldModel 老版本的数据对象 */ public void saveOldModel(BaseModel oldModel){ setBtmName(oldModel); if (revisionMapper != null) { revisionMapper.resetLastRevision(oldModel.getNameOid(),VciBaseUtil.getTableName(oldModel.getBtmname())); revisionMapper.resetOldRevision(oldModel.getOid(),VciBaseUtil.getTableName(oldModel.getBtmname())); }else{ throw new VciBaseException("没有初始化版本规则的数据操作层,请开发人员检查maven是否引用"); } } /** * 保存旧的版次,会自动把以前最新版次的哪条数据修改,同时会把老的这条版次修改 * @param oldModel 老版次的数据对象 */ public void saveOldModelVersion(BaseModel oldModel){ setBtmName(oldModel); if (revisionMapper != null) { revisionMapper.resetLastVersion(oldModel.getNameOid(),oldModel.getRevisionOid(),VciBaseUtil.getTableName(oldModel.getBtmname())); revisionMapper.resetOldVersion(oldModel.getOid(),VciBaseUtil.getTableName(oldModel.getBtmname())); }else{ throw new VciBaseException("没有初始化版本规则的数据操作层,请开发人员检查maven是否引用"); } } /** * 封装版本的信息,支持第一个版本的第一个版次,和升版的情况 * @param newModel 新版本的数据,请先行设置版本规则的值在这个对象中 * @param btmType 对象的注解 * @param lastRevision 当前最新版本最新版次的对象,是第一个版本的第一个版本时传递null */ public void wrapperRevisionValue(BaseModel newModel,VciBtmType btmType,RevisionInfo lastRevision){ //没有版本号的时候必须使用编码规则来生成新的版本号 if (RevisionConstant.CHARACTER.equalsIgnoreCase(newModel.getRevisionRule())) { //使用字母这个默认的字符,这个没有前缀,没有后缀,步长为1,没有跳跃字符 newRevisionForLetter(newModel, lastRevision, btmType != null ? btmType.revisionRulePrefix() : "", btmType != null ? btmType.revisionRuleSubfix() : ""); } else if (RevisionConstant.NUMBER.equalsIgnoreCase(newModel.getRevisionRule())) { newRevisionForNumber(newModel,lastRevision,btmType != null ? btmType.revisionRulePrefix() : "", btmType != null ? btmType.revisionRuleSubfix() : ""); } else { if (revisionRuleProvider != null) { try { BaseResult nextRevisionResult = revisionRuleProvider.getNextRevisionValue(newModel.getRevisionRule(), lastRevision==null?"":lastRevision.getRevisionValue()); if (nextRevisionResult.isSuccess()) { newModel.setRevisionValue((String) nextRevisionResult.getObj()); } else { throw new VciBaseException(nextRevisionResult.getMsg(), nextRevisionResult.getMsgObjs()); } } catch (Throwable e) { throw new VciBaseException("获取下一个版本号出现了错误,{0}", new String[]{newModel.getRevisionRule()}, e); } } else { throw new VciBaseException("没有初始化版本规则的调用器,请开发人员检查feign"); } } } /** * 根据数字的规则封装新的版本 * @param baseModel 基础数据对象 * @param lastRevision 最后的版本对象 * @param prefix 前缀 * @param subfix 后缀 */ private void newRevisionForNumber(BaseModel baseModel, RevisionInfo lastRevision,String prefix,String subfix) { if(prefix==null){ prefix = ""; } if(subfix == null){ subfix = ""; } if(lastRevision == null) { //说明是第一个版本 baseModel.setRevisionValue(prefix + "1" + subfix); }else { String ruleValue = replacePrefixAndSubfix(lastRevision, prefix, subfix); if (ruleValue.matches(RegExpConstant.NUMBER)) { //数字可以不停地加 ruleValue = String.valueOf(Integer.valueOf(ruleValue) + 1); baseModel.setRevisionValue(prefix + ruleValue + subfix); } else { //最后一个版本可能是手动输入的,那就直接找一下最后一排数字, if (ruleValue.matches(RegExpConstant.HAS_NUMBER)) { String onlyNumber = getNumbers(ruleValue); String nextNumber = String.valueOf(Integer.valueOf(onlyNumber) + 1); if (ruleValue.startsWith(onlyNumber)) { ruleValue = ruleValue.substring(onlyNumber.length()); baseModel.setRevisionValue(prefix + onlyNumber + ruleValue + subfix); } else if (ruleValue.endsWith(onlyNumber)) { ruleValue = ruleValue.substring(0, ruleValue.length() - onlyNumber.length() - 1); baseModel.setRevisionValue(prefix + ruleValue + nextNumber + subfix); } else { baseModel.setRevisionValue(prefix + ruleValue.substring(0, ruleValue.lastIndexOf(onlyNumber)) + nextNumber + ruleValue.substring(ruleValue.lastIndexOf(onlyNumber) + 1) + subfix); } } else { //一个数字都没有 baseModel.setRevisionValue(prefix + ruleValue + "1" + subfix); } } } } /** * 获取字符串中的数字部分 * @param content 字符串内容 * @return 数字的部分,最后的那部分 */ private String getNumbers(String content) { Pattern pattern = Pattern.compile("\\d+"); Matcher matcher = pattern.matcher(content); while (matcher.find()) { return matcher.group(matcher.groupCount()-1); } return ""; } /** * 替换前缀和后缀 * @param lastRevision 最后版本的对象 * @param prefix 前缀 * @param subfix 后缀 * @return 去除前缀和后缀的版本规则 */ private String replacePrefixAndSubfix(RevisionInfo lastRevision,String prefix,String subfix){ String ruleValue = lastRevision.getRevisionValue(); if(prefix==null){ prefix = ""; } if(subfix == null){ subfix = ""; } if(StringUtils.isNotBlank(prefix) && ruleValue.startsWith(prefix)){ ruleValue = ruleValue.substring(prefix.length()); } if(StringUtils.isNotBlank(subfix) && ruleValue.endsWith(subfix)){ ruleValue = ruleValue.substring(0,ruleValue.length()-subfix.length()-1); } return ruleValue; } /** * 根据字母的规则封装新的版本 * @param baseModel 基础数据对象 * @param lastRevision 最后的版本对象 * @param prefix 前缀 * @param subfix 后缀 */ private void newRevisionForLetter(BaseModel baseModel,RevisionInfo lastRevision,String prefix,String subfix){ if(prefix==null){ prefix = ""; } if(subfix == null){ subfix = ""; } if(lastRevision == null){ //说明是第一个版本 baseModel.setRevisionValue(prefix + "A" + subfix); }else { String ruleValue = replacePrefixAndSubfix(lastRevision, prefix, subfix); if (ruleValue.matches(RegExpConstant.LETTER)) { //从A到ZZ的形式 String lastLetter = ruleValue.substring(ruleValue.length() - 1); if (lastLetter.equalsIgnoreCase("Z")) { if (lastRevision.getRevisionValue().length() == 1) { baseModel.setRevisionValue(prefix + "AA" + subfix); } else { lastLetter = ruleValue.substring(ruleValue.length() - 2, ruleValue.length() - 1); lastLetter = String.valueOf((char) (lastLetter.toCharArray()[0] + 1)); baseModel.setRevisionValue(prefix + ruleValue.substring(0, ruleValue.length() - 2) + lastLetter + subfix); } } else { lastLetter = String.valueOf((char) (lastLetter.toCharArray()[0] + 1)); baseModel.setRevisionValue(prefix + ruleValue.substring(0, ruleValue.length() - 1) + lastLetter + subfix); } } else { //最后一个版本可能是手动输入的,如果我们之间存储A的话,可能会造成重复,最后一位是字母就在该字母上加1,最后一位不是字母,就原值上加A String lastLetter = ruleValue.substring(ruleValue.length() - 1); if (lastLetter.matches(RegExpConstant.LETTER)) { lastLetter = String.valueOf((char) (lastLetter.toCharArray()[0] + 1)); baseModel.setRevisionValue(prefix + ruleValue.substring(0, ruleValue.length() - 1) + lastLetter + subfix); } else { baseModel.setRevisionValue(prefix + ruleValue + "A" + subfix); } } } } /** * 封装某个版本的第一个版次 * @param baseModel 数据对象 */ public void wrapperFristVersion(BaseModel baseModel){ VciBaseUtil.alertNotNull(baseModel,"数据对象"); VciBtmType btmType = getBtmTypeAnnotation(baseModel); if(isManageVersion(btmType)) { //只支持从0,1,或者字母A开始 if (StringUtils.isBlank(baseModel.getVersionRule())) { baseModel.setVersionRule(btmType.versionRule().getValue()); } if (btmType.versionRule().equals(VciBtmType.VciBtmTypeVersionRule.INTSTART0)) { baseModel.setVersionValue("0"); } else if (btmType.versionRule().equals(VciBtmType.VciBtmTypeVersionRule.INTSTART1)) { baseModel.setVersionValue("1"); } else { baseModel.setVersionValue("A"); } } baseModel.setVersionSeq(1); baseModel.setFirstV("1"); baseModel.setLastV("1"); } /** * 封装第一个版本的第一个版次 * @param baseModel 新增的数据对象(第一个版本的第一个版次 */ public void wrapperFristRevision(BaseModel baseModel){ VciBaseUtil.alertNotNull(baseModel,"数据对象"); //需要先判断是否控制版本 VciBtmType btmType = getBtmTypeAnnotation(baseModel); if(isManageRevision(btmType)) { if (StringUtils.isBlank(baseModel.getOid())) { baseModel.setOid(VciBaseUtil.getPk()); } //第一个版本的第一个版次 if (StringUtils.isBlank(baseModel.getNameOid())) { baseModel.setNameOid(VciBaseUtil.getPk()); } if (StringUtils.isBlank(baseModel.getRevisionOid())) { baseModel.setRevisionOid(VciBaseUtil.getPk()); } //第一个版本 if (btmType != null) { baseModel.setRevisionRule(btmType.revisionRule()); baseModel.setVersionValue(btmType.versionRule().getValue()); } else { throw new VciBaseException("没有VciBtmType注解,{0}"); } //根据版本规则生成版本号 //3.版本号 //版本号为空,只能是手动后输入的时候,应该是错误 //其他情况下版本号为空都设置版本号 if (StringUtils.isBlank(baseModel.getRevisionValue() )&& isInputRevision(baseModel) && StringUtils.isBlank(baseModel.getRevisionRule())){ //不处理 }else { if (StringUtils.isBlank(baseModel.getRevisionValue())) { wrapperRevisionValue(baseModel, btmType, null); } } //如果有版次,那这个就是新版本的第一个版次 if (StringUtils.isNotBlank(baseModel.getVersionRule()) && StringUtils.isBlank(baseModel.getVersionValue())) { wrapperFristVersion(baseModel); } else { baseModel.setFirstV("1"); baseModel.setLastV("1"); } //4.版本顺序 baseModel.setRevisionSeq(1); baseModel.setFirstR("1"); baseModel.setLastR("1"); } } /** * 封装生命周期 * @param baseModel 数据对象 */ public void wrapperLifeCycle(BaseModel baseModel){ VciBaseUtil.alertNotNull(baseModel,"数据对象"); VciBtmType btmType = getBtmTypeAnnotation(baseModel); if(StringUtils.isBlank(baseModel.getLcStatus()) &&isManageLifeCycle(btmType) ){ //开始的时候获取生命周期的初始状态 if(StringUtils.isNotBlank(btmType.startStatus())){ baseModel.setLcStatus(btmType.startStatus()); }else { if (lifeCycleProvider != null) { try { BaseResult lifeCycleResult = lifeCycleProvider.getStartStatus(btmType.lifeCycle()); if (lifeCycleResult.isSuccess()) { baseModel.setLcStatus((String) lifeCycleResult.getObj()); } else { throw new VciBaseException(lifeCycleResult.getMsg(), lifeCycleResult.getMsgObjs()); } } catch (Throwable e) { throw new VciBaseException("调用【生命周期】服务获取初始状态时出错,{0}", new String[]{btmType.lifeCycle()}, e); } } else { throw new VciBaseException("没有初始化生命周期的调用器,请开发人员检查feign"); } } } } /** * 是否管理生命周期 * @param baseModel 数据对象 * @return true表示管理 */ public boolean isManageLifeCycle(BaseModel baseModel){ VciBtmType btmType = getBtmTypeAnnotation(baseModel); return isManageLifeCycle(btmType); } /** * 是否管理生命周期 * @param btmType 业务类型注解 * @return true表示管理 */ public boolean isManageLifeCycle(VciBtmType btmType){ if(btmType !=null && (StringUtils.isNotBlank(btmType.lifeCycle()) && !"defaultLC".equalsIgnoreCase(btmType.lifeCycle()))){ return true; }else{ return false; } } /** * 是否管理版本 * @param baseModel 数据对象 * @return true 表示管理版本 */ public boolean isManageRevision(BaseModel baseModel){ VciBtmType btmType = getBtmTypeAnnotation(baseModel); return isManageRevision(btmType); } /** * 是否管理版本 * @param btmType 业务类型的注解 * @return true 表示管理版本 */ public boolean isManageRevision(VciBtmType btmType){ if(btmType !=null && (btmType.revisionRuleInput() || StringUtils.isNotBlank(btmType.revisionRule()))){ return true; } return false; } /** * 是否管理版次,必须管理版本才可以管理版次 * @param baseModel 数据对象 * @return true 表示管理版本 */ public boolean isManageVersion(BaseModel baseModel){ VciBtmType btmType = getBtmTypeAnnotation(baseModel); return isManageVersion(btmType); } /** * 是否管理版次,必须管理版本才可以管理版次 * @param btmType 业务类型的注解 * @return true 表示管理版本 */ public boolean isManageVersion(VciBtmType btmType){ if(isManageRevision(btmType) && !btmType.versionRule().equals(VciBtmType.VciBtmTypeVersionRule.NONE)){ return true; } return false; } /** * 是否可以手动输入版本号 * @param baseModel 基本数据对象 * @return true允许手动输入版本号 */ public boolean isInputRevision(BaseModel baseModel) { VciBtmType btmType = getBtmTypeAnnotation(baseModel); return isInputRevision(btmType); } /** * 是否可以手动输入版本号 * @param btmType 业务类型的注解 * @return true允许手动输入版本号 */ public boolean isInputRevision(VciBtmType btmType) { if(btmType !=null && btmType.revisionRuleInput()){ return true; } return false; } /** * 获取数据对象上的注解 * @param baseModel 数据对象 * @return 不存在注解的时候会返回null */ public VciBtmType getBtmTypeAnnotation(BaseModel baseModel){ VciBaseUtil.alertNotNull(baseModel,"数据对象"); return getBtmTypeAnnotation(baseModel.getClass()); } /** * 获取DO对象上的注解 * @param doClass do对象的类 * @return 不存在注解的时候会返回null */ public VciBtmType getBtmTypeAnnotation(Class doClass){ VciBaseUtil.alertNotNull(doClass,"要校验业务类型的类"); if(modelAnnotationMap.containsKey(doClass.getName())){ return modelAnnotationMap.get(doClass.getName()); } if(doClass.isAnnotationPresent(VciBtmType.class)){ VciBtmType btmType = (VciBtmType)doClass.getAnnotation(VciBtmType.class); if(btmType == null){ btmType = doClass.getDeclaredAnnotation(VciBtmType.class); } modelAnnotationMap.put(doClass.getName(),btmType); return btmType; } return null; } /** * 封装树形数据查询器.这个方法被废弃,改为 VciQueryWrapperForDO里的 parentQueryChild * @param treeQueryObject 树形查询对象 * @param doClass 实体的类 * @param parentFieldName 上级属性的字段 * @return 查询封装器 */ @Deprecated public VciQueryWrapperForDO wrapperForTree(TreeQueryObject treeQueryObject,Class doClass,String parentFieldName){ if(doClass == null){ throw new VciBaseException("数据对象所属的类不能为空,不能封装树形查询器"); } if (treeQueryObject == null){ treeQueryObject = new TreeQueryObject(); } VciQueryWrapperOption queryWrapperOption = new VciQueryWrapperOption(); if(treeQueryObject.isQueryAllRev()){ queryWrapperOption.setThisObjectQueryLastRevision(false); queryWrapperOption.setThisObjectQueryRelease(false); } VciQueryWrapperForDO queryWrapper = new VciQueryWrapperForDO(treeQueryObject.getConditionMap(),doClass,new PageHelper(-1),true,queryWrapperOption); if(StringUtils.isBlank(parentFieldName)){ return queryWrapper; } if(StringUtils.isNotBlank(treeQueryObject.getParentOid()) ){ //说明传递了上级的 if(treeQueryObject.isQueryAllLevel()){ //全部的层级都要查询,我们使用start with先查询出结果后,再匹配查询条件 queryWrapper.in(queryWrapper.getOidFieldName(), "select " + queryWrapper.getOidFieldName() + " from " + queryWrapper.getTableName() + " start with " + parentFieldName + " = '" + treeQueryObject.getParentOid().trim() + "' connect by prior " + queryWrapper.getOidFieldName() + " = " + parentFieldName ); }else { queryWrapper.eq(parentFieldName, treeQueryObject.getParentOid()); } }else{ if(treeQueryObject.isQueryAllLevel()){ //全部的层级都要查询,我们使用start with先查询出结果后,再匹配查询条件 queryWrapper.in(queryWrapper.getOidFieldName(), "select " + queryWrapper.getOidFieldName() + " from " + queryWrapper.getTableName() + " start with " + parentFieldName + " is null connect by prior " + queryWrapper.getOidFieldName() + " = " + parentFieldName ); }else{ queryWrapper.isNull(parentFieldName); } } return queryWrapper; } /** * 将数据对象转换为树形 * @param doList 数据对象 * @param wrapperOptions 封装的信息 * @return 树列表 */ public List doList2Trees(List doList, TreeWrapperOptions wrapperOptions, Function f){ if(CollectionUtils.isEmpty(doList)){ return new ArrayList<>(); } List allTree = new ArrayList(); List children = new ArrayList(); for (T doObject: doList) { Tree tree =new Tree(); List oidFieldNames = VciBaseUtil.str2List(wrapperOptions.getOidFieldName()); List oidValues = new LinkedList<>(); oidFieldNames.stream().forEach( s->{ oidValues.add(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField(s,doObject))); }); tree.setOid(oidValues.stream().collect(Collectors.joining(wrapperOptions.getOidValueSep()))); if(f !=null){ tree.setText((String)f.apply(doObject)); }else{ List textFieldNames = VciBaseUtil.str2List(wrapperOptions.getTextFieldName()); List textValues = new LinkedList<>(); textFieldNames.stream().forEach( s->{ textValues.add(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField(s,doObject))); }); tree.setText(textValues.stream().collect(Collectors.joining(wrapperOptions.getTextValueSep()))); } if(StringUtils.isNotBlank(wrapperOptions.getParentFieldName())){ tree.setParentId(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField(wrapperOptions.getParentFieldName(),doObject))); } if(wrapperOptions.isAllAttributes()) { try { tree.setAttributes(VciBaseUtil.objectToMapString(doObject)); } catch (Exception e) { //这里不做处理 if (logger.isErrorEnabled()) { logger.error("把对象转换为map时出现了错误,但是不影响树的展示,对业务可能有影响"); } } } if(wrapperOptions.isMultipleSelect() || wrapperOptions.isShowCheckBox()){ tree.setShowCheckbox(true); } if(wrapperOptions.getParentOid() == null){ wrapperOptions.setParentOid(""); } if(StringUtils.isBlank(tree.getParentId()) || (StringUtils.isNotBlank(wrapperOptions.getParentOid()) && wrapperOptions.getParentOid().equalsIgnoreCase(tree.getParentId()))){ allTree.add(tree); }else { children.add(tree); } } new Tree().findChild(allTree,children); if(allTree.size()<=0){ allTree.addAll(children); } return allTree; } }