|
@@ -0,0 +1,191 @@
|
|
|
|
+package com.persagy.fm.mybatis.service.impl;
|
|
|
|
+
|
|
|
|
+import com.persagy.common.exception.BusinessException;
|
|
|
|
+import com.persagy.fm.common.context.AppContext;
|
|
|
|
+import com.persagy.fm.common.helper.LockHelper;
|
|
|
|
+import com.persagy.fm.common.model.entity.ITreeEntity;
|
|
|
|
+import com.persagy.fm.mybatis.dao.SimpleTreeCodeDao;
|
|
|
|
+import com.persagy.fm.mybatis.service.ITreeCodeService;
|
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+
|
|
|
|
+import javax.annotation.Resource;
|
|
|
|
+import java.util.List;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 树形编码服务简单实现,目前支持单节点,集群时增加一位节点代码
|
|
|
|
+ * @author Charlie Yu
|
|
|
|
+ * @date 2021-03-29
|
|
|
|
+ */
|
|
|
|
+@Service
|
|
|
|
+public class SimpleTreeCodeServiceImpl implements ITreeCodeService {
|
|
|
|
+
|
|
|
|
+ /** 数据访问对象 */
|
|
|
|
+ @Resource
|
|
|
|
+ private SimpleTreeCodeDao dao = null;
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public <T extends ITreeEntity> T generateTreeCode(T entity, String parentCode) {
|
|
|
|
+ String tableName = entity.getTreeTableName();
|
|
|
|
+ String innerCodeField = entity.getInnerCodeField();
|
|
|
|
+ String code = generateTreeCode(tableName, parentCode, innerCodeField);
|
|
|
|
+ entity.setInnerCode(code);
|
|
|
|
+ return entity;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public <T extends ITreeEntity> String generateTreeCodeByParent(T parent) {
|
|
|
|
+ return generateTreeCode(parent.getTreeTableName(), parent.getInnerCode(), parent.getInnerCodeField());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public String generateTreeCode(String tableName, String parentCode, String innerCodeField) {
|
|
|
|
+ if (parentCode == null) {
|
|
|
|
+ parentCode = StringUtils.EMPTY;
|
|
|
|
+ }
|
|
|
|
+ String key = AppContext.getContext().getGroupCode() + "-" + tableName + parentCode;
|
|
|
|
+ if (LockHelper.lock(key)) {
|
|
|
|
+ try {
|
|
|
|
+ String maxCode = dao.getMaxCode(tableName, parentCode, innerCodeField);
|
|
|
|
+ if (maxCode != null) {
|
|
|
|
+ maxCode = maxCode.substring(parentCode.length());
|
|
|
|
+ }
|
|
|
|
+// if(StringUtils.isBlank(maxCode)){
|
|
|
|
+// maxCode="00000";
|
|
|
|
+// }
|
|
|
|
+ maxCode = increase(maxCode);
|
|
|
|
+ return parentCode + maxCode;
|
|
|
|
+ } finally {
|
|
|
|
+ LockHelper.unlock(key);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ throw new BusinessException("编码生成失败,请重新操作");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public <T extends ITreeEntity> List<T> generateTreeCodes(List<T> entitys, String parentCode) {
|
|
|
|
+ if (entitys == null || entitys.size() == 0) {
|
|
|
|
+ return entitys;
|
|
|
|
+ }
|
|
|
|
+ if (parentCode == null) {
|
|
|
|
+ parentCode = StringUtils.EMPTY;
|
|
|
|
+ }
|
|
|
|
+ int length = entitys.size();
|
|
|
|
+ ITreeEntity entity = entitys.get(0);
|
|
|
|
+
|
|
|
|
+ String tableName = entity.getTreeTableName();
|
|
|
|
+ String innerCodeField = entity.getInnerCodeField();
|
|
|
|
+ String key = AppContext.getContext().getGroupCode() + "-" + tableName + "-" + parentCode;
|
|
|
|
+ if (LockHelper.lock(key)) {
|
|
|
|
+ try {
|
|
|
|
+ String maxCode = dao.getMaxCode(tableName, parentCode, innerCodeField);
|
|
|
|
+ if (maxCode != null) {
|
|
|
|
+ maxCode = maxCode.substring(parentCode.length());
|
|
|
|
+ }
|
|
|
|
+ for (int i = 0; i < length; i++) {
|
|
|
|
+ maxCode = increase(maxCode);
|
|
|
|
+ entitys.get(i).setInnerCode(parentCode + maxCode);
|
|
|
|
+ }
|
|
|
|
+ return entitys;
|
|
|
|
+ } finally {
|
|
|
|
+ LockHelper.unlock(key);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ throw new BusinessException("编码生成失败,请重新操作");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public <T extends ITreeEntity> String[] generateTreeCodesByParent(T parent, int length) {
|
|
|
|
+ String parentCode = parent.getInnerCode();
|
|
|
|
+ if (parentCode == null) {
|
|
|
|
+ parentCode = StringUtils.EMPTY;
|
|
|
|
+ }
|
|
|
|
+ String tableName = parent.getTreeTableName();
|
|
|
|
+ String[] codes = new String[length];
|
|
|
|
+ String key = getLockKey(tableName);
|
|
|
|
+ if (LockHelper.lock(key)) {
|
|
|
|
+ try {
|
|
|
|
+ String maxCode = dao.getMaxCode(tableName, parentCode, parent.getInnerCodeField());
|
|
|
|
+ if (maxCode != null) {
|
|
|
|
+ maxCode = maxCode.substring(parentCode.length());
|
|
|
|
+ }
|
|
|
|
+ for (int i = 0; i < length; i++) {
|
|
|
|
+ maxCode = increase(maxCode);
|
|
|
|
+ codes[i] = parentCode + maxCode;
|
|
|
|
+ }
|
|
|
|
+ return codes;
|
|
|
|
+ } finally {
|
|
|
|
+ LockHelper.unlock(key);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ throw new BusinessException("编码生成失败,请重新操作");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public <T extends ITreeEntity> void synchronizeSubTree(T entity, String oldTreeCode) {
|
|
|
|
+ if (entity == null || StringUtils.isEmpty(entity.getInnerCode())) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ String tableName = entity.getTreeTableName();
|
|
|
|
+ String parentCode = entity.getInnerCode();
|
|
|
|
+ dao.updateSubTreeCode(tableName, parentCode, oldTreeCode, entity.getInnerCodeField());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public <T extends ITreeEntity> T afterMoveNodeToParent(T entity, String parentCode) {
|
|
|
|
+ if (entity == null || StringUtils.isEmpty(entity.getInnerCode())) {
|
|
|
|
+ return entity;
|
|
|
|
+ }
|
|
|
|
+ String oldTreeCode = entity.getInnerCode();
|
|
|
|
+ String key = getLockKey(entity.getTreeTableName());
|
|
|
|
+ if (LockHelper.lock(key)) {
|
|
|
|
+ try {
|
|
|
|
+ generateTreeCode(entity, parentCode);
|
|
|
|
+ synchronizeSubTree(entity, oldTreeCode);
|
|
|
|
+ return entity;
|
|
|
|
+ } finally {
|
|
|
|
+ LockHelper.unlock(key);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ throw new BusinessException("节点移动失败,请重试操作");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 递增最大编码
|
|
|
|
+ * @param maxCode 原有最大编码
|
|
|
|
+ * @return 递增后编码
|
|
|
|
+ */
|
|
|
|
+ public String increase(String maxCode) {
|
|
|
|
+ long v = 0;
|
|
|
|
+ if (maxCode != null) {
|
|
|
|
+ v = Long.parseLong(maxCode, Character.MAX_RADIX);
|
|
|
|
+ v++;
|
|
|
|
+ }
|
|
|
|
+ maxCode = Long.toString(v, Character.MAX_RADIX);
|
|
|
|
+ int digit = TREE_CODE_LENGTH - maxCode.length();
|
|
|
|
+ if (digit < 0) {
|
|
|
|
+ throw new RuntimeException("Tree Code digit overflow!");
|
|
|
|
+ }
|
|
|
|
+ char[] chars = new char[TREE_CODE_LENGTH];
|
|
|
|
+ for (int i = 0; i < digit; i++) {
|
|
|
|
+ chars[i] = '0';
|
|
|
|
+ }
|
|
|
|
+ System.arraycopy(maxCode.toCharArray(), 0, chars, digit, maxCode.length());
|
|
|
|
+ return new String(chars);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 取得锁的键值
|
|
|
|
+ * @param tableName 表名
|
|
|
|
+ * @return 键值
|
|
|
|
+ */
|
|
|
|
+ private String getLockKey(String tableName) {
|
|
|
|
+ String tenant = AppContext.getContext().getGroupCode();
|
|
|
|
+ if (StringUtils.isEmpty(tenant)) {
|
|
|
|
+ throw new BusinessException("未指定租户id");
|
|
|
|
+ }
|
|
|
|
+ return tenant + "-" + tableName;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|