86 lines
3.8 KiB
Java
86 lines
3.8 KiB
Java
package com.yunhai.userbase.utils;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* 课程节点 64 bit 复合 ID 工具类(无实体、纯静态)
|
|
* rootType 根节点类别【资源,辅导,题库,试卷,专项】
|
|
* nodeType 虚拟节点类型【根节点,教材(辅)目录节点,年级节点,教材知识树节点,真实节点】
|
|
* stage 学段【2小学 3初中 4高中】
|
|
* grade 年级 1-12
|
|
*/
|
|
|
|
public final class NodeIdUtil {
|
|
|
|
/* ===================== 位宽 ===================== */
|
|
private static final int ROOT_BITS = 4;
|
|
private static final int TYPE_BITS = 4; // 原 biz
|
|
private static final int SUBJ_BITS = 20;
|
|
private static final int STAGE_BITS = 4;
|
|
private static final int GRADE_BITS = 4;
|
|
private static final int NODE_BITS = 28;
|
|
|
|
private static final long ROOT_MASK = mask(ROOT_BITS);
|
|
private static final long TYPE_MASK = mask(TYPE_BITS);
|
|
private static final long SUBJ_MASK = mask(SUBJ_BITS);
|
|
private static final long STAGE_MASK = mask(STAGE_BITS);
|
|
private static final long GRADE_MASK = mask(GRADE_BITS);
|
|
private static final long NODE_MASK = mask(NODE_BITS);
|
|
|
|
/* ===================== 编码 ===================== */
|
|
public static long encode(Integer rootType,
|
|
String subject,
|
|
Integer stage,
|
|
Integer nodeType,
|
|
Integer grade,
|
|
Integer nodeId) {
|
|
int subNum = subjectToInt(subject);
|
|
long root = (rootType == null ? 0 : rootType) & ROOT_MASK;
|
|
long type = (nodeType == null ? 0 : nodeType) & TYPE_MASK;
|
|
long stageVal = (stage == null ? 0 : stage) & STAGE_MASK;
|
|
long gradeVal = (grade == null ? 0 : grade) & GRADE_MASK;
|
|
long nodeVal = (nodeId == null ? 0 : nodeId) & NODE_MASK;
|
|
|
|
return root << (TYPE_BITS + SUBJ_BITS + STAGE_BITS + GRADE_BITS + NODE_BITS)
|
|
| type << (SUBJ_BITS + STAGE_BITS + GRADE_BITS + NODE_BITS)
|
|
| (long) subNum << (STAGE_BITS + GRADE_BITS + NODE_BITS)
|
|
| stageVal << (GRADE_BITS + NODE_BITS)
|
|
| gradeVal << NODE_BITS
|
|
| nodeVal;
|
|
}
|
|
|
|
/* ===================== 解码 ===================== */
|
|
public static Map<String, Object> decode(long compositeId) {
|
|
Map<String, Object> map = new HashMap<>(6);
|
|
int root = (int) ((compositeId >>> (TYPE_BITS + SUBJ_BITS + STAGE_BITS + GRADE_BITS + NODE_BITS)) & ROOT_MASK);
|
|
int type = (int) ((compositeId >>> (SUBJ_BITS + STAGE_BITS + GRADE_BITS + NODE_BITS)) & TYPE_MASK);
|
|
int subNum = (int) ((compositeId >>> (STAGE_BITS + GRADE_BITS + NODE_BITS)) & SUBJ_MASK);
|
|
int stage = (int) ((compositeId >>> (GRADE_BITS + NODE_BITS)) & STAGE_MASK);
|
|
int grade = (int) ((compositeId >>> (NODE_BITS)) & GRADE_MASK);
|
|
int nodeId = (int) (compositeId & NODE_MASK);
|
|
|
|
map.put("rootType", root == 0 ? null : root);
|
|
map.put("nodeType", type == 0 ? null : type);
|
|
map.put("subject", intToSubject(subNum));
|
|
map.put("stage", stage == 0 ? null : stage);
|
|
map.put("grade", grade == 0 ? null : grade);
|
|
map.put("nodeId", nodeId == 0 ? null : nodeId);
|
|
return map;
|
|
}
|
|
|
|
/* ===================== subject 工具 ===================== */
|
|
private static int subjectToInt(String subject) {
|
|
if (subject == null || !subject.startsWith("SUB")) return 0;
|
|
return Integer.parseUnsignedInt(subject.substring(3));
|
|
}
|
|
|
|
private static String intToSubject(int n) {
|
|
if (n == 0) return null;
|
|
return (n <= 6) ? "SUB0" + n : "SUB" + n;
|
|
}
|
|
|
|
private static long mask(int bits) { return (1L << bits) - 1; }
|
|
|
|
private NodeIdUtil() {}
|
|
} |