edi.rule.work.cache.JSRuleMappingInfo Maven / Gradle / Ivy
package edi.rule.work.cache;
import java.util.*;
import java.util.Map.Entry;
import edi.rule.config.JSRuleMessage;
import edi.rule.extend.classes.JSRuleDefaultExtend;
import edi.rule.util.*;
import edi.rule.work.constant.ZSSign;
import edi.rule.work.constant.JSRuleDBSign;
import edi.rule.work.enums.JSRuleCrudPermitEnum;
import edi.rule.work.custom.JSRuleException;
/**
* @author 摩拉克斯
* @date 2022年3月30日 下午2:11:15
* 存放实体类信息的缓存类,它与实体类是一对一关系
*/
public final class JSRuleMappingInfo {
/**
*
缓存类的直接类名,唯一标识,用于字段前缀名
* */
public final String className;
/**
*
用于{@link JSRuleMappingInfo#className}直接类名冲突时顶替它的唯一标识,如果是扫描实体类的加载方式,则默认为实体类的全限定类名,如果是继承于{@link JSRuleCacheExtend}则不需要考虑该属性
* */
public final String fullName;
/**
*
缓存类映射表的表名
* */
public final String tableName;
/**
*
允许crud操作的枚举类型,为空时则默认允许所有crud操作
* */
public final JSRuleCrudPermitEnum permit;
/**
*
允许角色访问类型,为null或空时则不做校验
* */
public final Set roles;
/**
* 主键字段
* */
public final String pk;
/**
*
表主体字符串,该主体可能是一个表也可能是一个视图
* */
public final String subject;
/**
*
缓存类映射的是否是一个视图
* */
public final boolean isView;
/**
*
查询时实体类的全部字段
* */
public final String queryFields;
/**
*
实体类对应表中的全部字段
* */
public final String tableFields;
/**
*
不带class前缀的java字段信息,key为java字段名
* */
public final Map classFieldsInfo;
/**
* 带class前缀的java字段信息,key为带前缀的java字段名
* */
public final Map prefixClassFieldsInfo;
/**
* 包含所有的classFieldsInfo和prefixClassFieldsInfo
* */
public final Map allFieldsInfo;
/**
* 包含所有的classFieldsInfo和prefixClassFieldsInfo,但其key为别名alias
* */
public final Map allAliasInfo;
/**
* 映射信息表和表之间的关联关系,key为外键fk对应的java的class类名称,value为其当前类对应的表和外键之间的关联id的sql字符串,如a.id=b.id
*
继承于{@link JSRuleDefaultExtend}的子类无需处理该属性
* */
public final Map relations;
private final Map relationsAdd;
/**
* key为fk关联的class名称,value为字段信息(没有前缀的)
*
继承于{@link JSRuleDefaultExtend}的子类无需处理该属性
* */
public final Map fkFields;
private final Map fkFieldsAdd;
/**
* key为classFieldName(没有前缀的),value为所依赖的外部类的某个字段信息
*
继承于{@link JSRuleDefaultExtend}的子类无需处理该属性
* */
public final Map dependents;
private final Map dependentsAdd;
public JSRuleMappingInfo(String className,String tableName,JSRuleMappingOptional mOptional) {
if (ZSString.isBlank(className)) {
throw new JSRuleException(JSRuleMessage.read("className.is.required"));
}
if (ZSString.isBlank(tableName)) {
throw new JSRuleException(JSRuleMessage.read("tableName.is.required"));
}
this.className = className;
this.tableName = tableName;
this.fullName = mOptional.fullName;
this.permit = mOptional.permit;
if (ZSString.isBlank(mOptional.view)) {
this.subject = ZSSign.BLANK + this.tableName + ZSSign.BLANK ;
this.isView = false;
}else {
this.subject = String.valueOf(ZSSign.BLANK) + ZSSign.LEFT_BRACKET + mOptional.view + ZSSign.RIGHT_BRACKET + ZSSign.BLANK;
this.isView = true;
}
if (ZSVessel.isEmpty(mOptional.roles)){
this.roles = null;
}else{
this.roles = Collections.unmodifiableSet(mOptional.roles);
}
if (ZSVessel.isEmpty(mOptional.classFieldsInfo)) {
this.classFieldsInfo = Collections.unmodifiableMap(new HashMap<>());
}else {
this.classFieldsInfo = Collections.unmodifiableMap(mOptional.classFieldsInfo);
}
if (ZSVessel.isEmpty(mOptional.relations)) {
this.relationsAdd = new HashMap<>();
}else {
this.relationsAdd = mOptional.relations;
}
if (ZSVessel.isEmpty(mOptional.fkFields)) {
this.fkFieldsAdd = new HashMap<>();
}else {
this.fkFieldsAdd = mOptional.fkFields;
}
if (ZSVessel.isEmpty(mOptional.dependents)) {
this.dependentsAdd = new HashMap<>();
}else {
this.dependentsAdd = mOptional.dependents;
}
Map allAliasInfoTemp = new HashMap<>();
Map prefixClassFieldsInfoTemp = new HashMap<>();
/*遍历fields信息,初始化view字段字符串,主键名等等*/
String pkTemp = "";
StringBuilder tableFieldsTemp = new StringBuilder();
for (Entry fieldInfoEntry:this.classFieldsInfo.entrySet()) {
JSRuleFieldInfo classFieldInfo = fieldInfoEntry.getValue();
String classFieldName = classFieldInfo.classFieldName;
String tableFieldName = classFieldInfo.tableFieldName;
String fieldAliasName = classFieldInfo.fieldAliasName;
tableFieldsTemp.append(ZSSign.COMMA).append(tableFieldName);
/*检查变量命名是否符合java命名格式*/
ZSRegex.checkVariable(classFieldName,tableFieldName,fieldAliasName);
/*set pk and fk*/
if (classFieldInfo.isPk) {
pkTemp = classFieldName;
}
allAliasInfoTemp.compute(fieldAliasName,(k,v) -> {
if (allAliasInfoTemp.containsKey(k)) {
throw new JSRuleException(JSRuleMessage.read("duplicate.alias"),k);
}
return classFieldInfo;
});
/*初始化prefixClassFieldsInfo带前缀的字段信息集合*/
buildPrefixFieldInfo(classFieldName,tableFieldName,fieldAliasName,classFieldInfo,prefixClassFieldsInfoTemp);
}
/*初始化table字段字符串等*/
StringBuilder queryFieldsTemp = new StringBuilder();
prefixClassFieldsInfoTemp.forEach((key, value) -> {
allAliasInfoTemp.put(value.fieldAliasName, value);
queryFieldsTemp.append(ZSSign.COMMA).append(value.tableFieldName).append(JSRuleDBSign.getAsText(value.fieldAliasName));
});
this.pk = pkTemp;
this.tableFields = tableFieldsTemp.delete(0,1).toString();
this.queryFields = queryFieldsTemp.delete(0,1).toString();
/*锁定各个map容器*/
this.allAliasInfo = Collections.unmodifiableMap(allAliasInfoTemp);
this.prefixClassFieldsInfo = Collections.unmodifiableMap(prefixClassFieldsInfoTemp);
Map allFieldsInfoTemp = new HashMap<>();
allFieldsInfoTemp.putAll(this.classFieldsInfo);
allFieldsInfoTemp.putAll(this.prefixClassFieldsInfo);
this.allFieldsInfo = Collections.unmodifiableMap(allFieldsInfoTemp);
this.relations = Collections.unmodifiableMap(this.relationsAdd);
this.fkFields = Collections.unmodifiableMap(this.fkFieldsAdd);
this.dependents = Collections.unmodifiableMap(this.dependentsAdd);
}
private void buildPrefixFieldInfo(String classFieldName,String tableFieldName,String fieldAliasName,JSRuleFieldInfo classFieldInfo,Map prefixTemp){
JSRuleFieldOptional fOptional = new JSRuleFieldOptional();
fOptional.tableFieldName = ZSRule.getPrefixTableFieldText(this.tableName,tableFieldName);
fOptional.fieldAliasName = ZSRule.getPrefixFieldAliasText(this.className,fieldAliasName);
fOptional.isPk = classFieldInfo.isPk;
fOptional.fkMappingInfoName = classFieldInfo.fkMappingInfoName;
fOptional.imports = classFieldInfo.imports;
fOptional.export = classFieldInfo.export;
fOptional.desensitizedInfo = classFieldInfo.desensitizedInfo;
String prefixClassFieldName = ZSRule.getPrefixClassFieldText(this.className,classFieldName);
prefixTemp.put(prefixClassFieldName,new JSRuleFieldInfo(this.className,prefixClassFieldName,classFieldInfo.type,fOptional));
}
public String getPk() {
if (ZSString.isBlank(pk)) {
throw new JSRuleException(JSRuleMessage.read("primary.key.not.found"),className);
}
return pk;
}
/**
* 自动判断获取直接类名还是全限定类名
* */
public String getClassName() {
return ZSString.isBlank(fullName)?className:fullName;
}
public JSRuleFieldInfo getFkFieldInfo(String fkClassName) {
JSRuleFieldInfo info = fkFields.get(fkClassName);
if (info == null) {
throw new JSRuleException(className,JSRuleMessage.read("primary.key.field.information.for.the.associated.object.was.not.found"),fkClassName);
}
return info;
}
public String getRelationsText(String fkClassName,String actionName) {
String text = relations.get(fkClassName);
if (ZSString.isBlank(text)) {
throw new JSRuleException(actionName,JSRuleMessage.read("relation.not.found"),fkClassName);
}
return text;
}
void addRelations(Map relations) {
relationsAdd.putAll(relations);
}
void addFkFields(Map fkFields) {
fkFieldsAdd.putAll(fkFields);
}
void addDependents(Map dependents) {
dependentsAdd.putAll(dependents);
}
}