All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gu.sql2java.generator.SqlComment Maven / Gradle / Ivy

The newest version!
package gu.sql2java.generator;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gitee.l0km.com4j.base.Pair;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import com.google.common.collect.ImmutableMap;

import gu.sql2java.excel.annotations.ExcelColumn;
import gu.sql2java.excel.annotations.ExcelSheet;

import static com.google.common.base.Strings.nullToEmpty;
import static com.gitee.l0km.com4j.base.MiscellaneousUtils.elementsOf;
import static com.google.common.base.Preconditions.checkState;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * SQL 语句注释字段(COMMENT)自定义标记解析
 * @author guyadong
 *
 */
class SqlComment {
	/**
	 * 正表达式提取字段注释({@link #remarks})中的JSON字段定义
	 */
	private static final String JSON_FIELD_REGEX="^(\\[JSON_STR(?:,(array|obj(?:ect)?|[a-z][\\w\\.]+\\w+))?\\])(.*)";

	/**
	 * 正表达式提取字段注释({@link #remarks})中的字段名标记
	 */
	private static final String NAME_TAG_REGEX="X@NAME\\s*:(.+?)@X";
	/**
	 * 正表达式提取字段注释({@link #remarks})中的多符号定义标记
	 */
	private static final String NAMES_TAG_REGEX="X@NAMES\\s*:\\s*((?:\\w+[=:-].+?,?)+)@X";
	/**
	 * 正表达式提取字段注释({@link #remarks})中的多值转换定义标记
	 */
	private static final String VALUES_TAG_REGEX="X@VALUES\\s*:((?:.+?[=:-].+?,?)+)@X";

	/**
	 * 正表达式提取字段注释({@link #remarks})中的ExcelColumn注解定义标记
	 */
	private static final String COLUMN_TAG_REGEX="X@COLUMN\\s*:((?:(?:\\s*\\w+\\s*)=(?:.+?),?)+?)@X";
	/**
	 * 正表达式提取字段注释({@link #remarks})中的ExcelSheet注解定义标记
	 */
	private static final String SHEET_TAG_REGEX="X@SHEET\\s*:((?:(?:\\s*\\w+\\s*)=(?:.+?),?)+?)@X";
	/**
	 * 正表达式提取字段注释({@link #remarks})中的NUM字段定义
	 */
	private static final String NUM_FIELD_REGEX="^(\\[NUM,(Boolean|Byte|Short|Integer|Long|Float|Double)\\])(.*)";
	
	/**
	 * 正表达式提取字段注释({@link #remarks})中的ANN字段定义,用于插入Java注解代码
	 */
	private static final String ANNOT_FIELD_REGEX="ANN(@.+?)@NNA";
	
	/**
	 * 正表达式提取字段注释({@link #remarks})中的JSAN字段定义,用于插入JSON序列化反序列化相关Java注解代码
	 */
	private static final String JSON_ANNOT_FIELD_REGEX="JSAN(@.+?)@NASJ";
	
	/**
	 * 正表达式提取字段注释({@link #remarks})中的TYPE字段定义,用于插入Java注解代码
	 */
	private static final String TYPE_FIELD_REGEX="TYPE@(.+?)@EPYT";

	/**
	 * 正表达式提取字段注释({@link #remarks})中的SCOPE字段定义
	 * 
    *
  • SCOPE@LOCAL@EPOSC -- 字段本地可见,在网络传输时不参与序列化反序列化
  • *
*/ private static final String SCOPE_FIELD_REGEX="SCOPE@(LOCAL|THRIFT|JSON)@EPOSC"; private static final Set EXCEL_COLUMN_FIELDS = methodNamesOf(ExcelColumn.class); private static final Set EXCEL_SHEET_FIELDS = methodNamesOf(ExcelSheet.class); private final String remarks; /** * 注解中NAME标记字段定义的字段名,如果没有定义NAME tag则为空字符串,参见{@link #NAME_TAG_REGEX} * @see #setRemarks(String) */ private final String descName; /** * 注解中NAMES标记字段定义的多符号定义,如果没有定义NAMES tag则为空字符串,参见{@link #VALUES_TAG_REGEX} * @see #setRemarks(String) */ private final String namesTag; /** * 注解中NAMES标记字段定义的多符号定义的名字映射,如果没有定义NAMES tag则为空,参见{@link #NAMES_TAG_REGEX} * @see #setRemarks(String) */ private final Map namesTagMap; /** * 注解中VALUES标记字段定义的多符号定义列表,如果没有定义VALUES tag则为空字符串,参见{@link #VALUES_TAG_REGEX} * @see #setRemarks(String) */ private final String valuesTag; /** * 注解中VALUES标记字段定义的多符号定义的名字映射,如果没有定义VALUES tag则为空,参见{@link #VALUES_TAG_REGEX} * @see #setRemarks(String) */ private final Map valuesTagMap; /** * 注解中COLUMN标记字段定义的ExcelColumn字段定义列表,如果没有定义COLUMN tag则为空字符串,参见{@link #COLUMN_TAG_REGEX} * @see #setRemarks(String) */ private final String columnTag; /** * 注解中COLUMN标记字段定义的ExcelColumn字段定义映射,如果没有定义COLUMN tag则为空,参见{@link #COLUMN_TAG_REGEX} * @see #setRemarks(String) */ private final Map columnTagMap; /** * 注解中SHEET标记字段定义的ExcelSheet字段定义列表,如果没有定义SHEET tag则为空字符串,参见{@link #SHEET_TAG_REGEX} * @see #setRemarks(String) */ private final String sheetTag; /** * 注解中SHEET标记字段定义的ExcelSheet字段定义映射,如果没有定义SHEET tag则为空,参见{@link #SHEET_TAG_REGEX} * @see #setRemarks(String) */ private final Map sheetTagMap; /** * 删除{@code X@ @X}标记的注释字段信息 */ private final String normalizedRemarks; SqlComment(String remarks) { this.remarks = nullToEmpty(remarks).replaceAll("/\\*", "SLASH*").replaceAll("\\*/", "*SLASH"); if(!Strings.isNullOrEmpty(this.remarks)){ { /** 从注解中提取NAME标记字段定义的字段名保存到 descName成员 ,如果没有定义NAME tag则descName为空字符串 */ Matcher matcher=Pattern.compile(NAME_TAG_REGEX).matcher(this.remarks); this.descName = matcher.find() ? matcher.group(1) : ""; } { ImmutableBiMap.builder(); /** 注解中提取NAMES标记字段定义的多符号定义保存到 namesTag成员,如果没有定义NAMES tag则namesTag为空字符串 */ Pair> pair = fetchMapDefine(NAMES_TAG_REGEX, ImmutableBiMap.builder()); this.namesTag = pair.getKey(); this.namesTagMap = new TreeMap<>(pair.getValue()); } { /** 注解中提取VALUES标记字段定义的多符号定义保存到 valuesTag成员,如果没有定义VALUES tag则valuesTag为空字符串 */ Pair> pair = fetchMapDefine(VALUES_TAG_REGEX, ImmutableBiMap.builder()); this.valuesTag = pair.getKey(); this.valuesTagMap = new TreeMap<>(pair.getValue()); } { /** 注解中提取COLUMN标记字段定义的多符号定义保存到 columnTag成员,如果没有定义COLUMN tag则columnTag为空字符串 */ Pair> pair = fetchMapDefine(COLUMN_TAG_REGEX, ImmutableMap.builder()); this.columnTag = pair.getKey(); this.columnTagMap = new TreeMap<>(Maps.filterKeys(pair.getValue(), k->EXCEL_COLUMN_FIELDS.contains(k))); } { /** 注解中提取SHEET标记字段定义的多符号定义保存到 sheetTag成员,如果没有定义SHEET tag则sheetTag为空字符串 */ Pair> pair = fetchMapDefine(SHEET_TAG_REGEX, ImmutableMap.builder()); this.sheetTag = pair.getKey(); this.sheetTagMap = new TreeMap<>(Maps.filterKeys(pair.getValue(), k->EXCEL_SHEET_FIELDS.contains(k))); } this.normalizedRemarks = this.remarks .replaceAll(NAME_TAG_REGEX, "$1") .replaceAll(NAMES_TAG_REGEX, "$1") .replaceAll(VALUES_TAG_REGEX, "$1") .replaceAll(COLUMN_TAG_REGEX, "") .replaceAll(SHEET_TAG_REGEX, "") .replaceAll(JSON_FIELD_REGEX, "$3") .replaceAll(NUM_FIELD_REGEX, "$3") .replaceAll(JSON_ANNOT_FIELD_REGEX, "") .replaceAll(ANNOT_FIELD_REGEX, "") .replaceAll(TYPE_FIELD_REGEX, "") .replaceAll(SCOPE_FIELD_REGEX, ""); }else{ this.descName = ""; this.namesTag = ""; this.namesTagMap = ImmutableBiMap.of(); this.valuesTag = ""; this.valuesTagMap = ImmutableBiMap.of(); this.columnTag = ""; this.columnTagMap = ImmutableBiMap.of(); this.sheetTag = ""; this.sheetTagMap = ImmutableBiMap.of(); this.normalizedRemarks = this.remarks; } } /** * @return normalized comment content */ String getRemarks() { return normalizedRemarks; } /** * 返回当前注解中NAME标记字段定义的字段名,如果没有定义NAME tag则返回空字符串,参见{@link #NAME_TAG_REGEX} */ String getDescName() { return descName; } /** * 返回当前注解中NAMES标记字段定义的多符号定义,如果没有定义NAMES tag则返回空字符串,参见{@link #VALUES_TAG_REGEX} */ String getNamesTag() { return namesTag; } /** * 返回注解中NAMES标记字段定义的多符号定义的名字映射,如果没有定义NAMES tag则为空 */ Map getNamesTagMap() { return namesTagMap; } /** * 返回当前注解中VALUES标记字段定义的多符号定义,如果没有定义VALUES tag则返回空字符串,参见{@link #VALUES_TAG_REGEX} */ String getValuesTag() { return valuesTag; } /** * 返回注解中VALUES标记字段定义的多符号定义的名字映射,如果没有定义VALUES tag则为空 */ Map getValuesTagMap() { return valuesTagMap; } /** * @return columnTag */ String getColumnTag() { return columnTag; } /** * @return columnTagMap */ Map getColumnTagMap() { Map m = new TreeMap<>(columnTagMap); /** 优先使用NAME tag定义的名字做name */ if(!descName.isEmpty()){ m.put("name",descName); } /** 优先使用NAME tag定义的名字做name */ if(!valuesTag.isEmpty()){ m.put("readConverterExp",valuesTag); } return m; } /** * @return sheetTag */ String getSheetTag() { return sheetTag; } /** * @return sheetTagMap */ Map getSheetTagMap() { Map m = new TreeMap<>(sheetTagMap); /** 优先使用NAME tag定义的名字做title */ if(!descName.isEmpty()){ m.put("title",descName); } return m; } /** * 返回当前字段的注释是否有JSON tag */ boolean hasJsonTag(){ return !Strings.isNullOrEmpty(remarks) && remarks.matches(JSON_FIELD_REGEX); } /** * 返回当前字段的注释是否有NUM tag */ boolean hasNumTag(){ return !Strings.isNullOrEmpty(remarks) && remarks.matches(NUM_FIELD_REGEX); } /** * 返回当前字段的注释是否有ANNOT tag */ boolean hasAnnotTag(){ return !Strings.isNullOrEmpty(remarks) && remarks.matches(ANNOT_FIELD_REGEX); } /** * 从字段注释中根据正则表达式{@link #JSON_FIELD_REGEX}解析JSON的类型定义(fastjson)
* 根据{@code [JSON_STR,...]}的定义返回不同的JSON类: *
    *
  • [JSON_STR,array] ---- JSONArray
  • *
  • [JSON_STR,object],[JSON_STR,obj] ---- JSONObject
  • *
  • [JSON_STR] ---- JSON
  • *
* 如果不是JSON字段则返回{@code null} */ String getJsonType(){ Matcher matcher=Pattern.compile(JSON_FIELD_REGEX).matcher(remarks); checkState(matcher.find(),"NOT FOUND JSON tag in comment : %s",remarks); String g2 = matcher.group(2); if("array".equals(g2)){ return JSONArray.class.getName(); }else if(null!= g2 && g2.matches("obj(?:ect)?")){ return JSONObject.class.getName(); }else if(null != g2){ return g2; } return JSONObject.class.getName(); } /** * 从字段注释中根据正则表达式{@link #NUM_FIELD_REGEX}解析定义的整数类型
* 根据{@code [NUM,...]}的定义返回不同的整数类型类:(Boolean|Byte|Short|Integer|Long|Float|Double), * 如果不是NUM字段则返回{@code null} */ Class getPrimitiveType(){ Matcher matcher=Pattern.compile(NUM_FIELD_REGEX).matcher(remarks); if(!matcher.find()) { return null; } String g2 = matcher.group(2); switch(g2) { case "Boolean": return Boolean.class; case "Byte": return Byte.class; case "Short": return Short.class; case "Integer": return Integer.class; case "Long": return Long.class; case "Float": return Float.class; case "Double": return Double.class; } throw new IllegalStateException("UNSUPPORTED TYPE FOR " + g2); } /** * 从字段注释中根据正则表达式{@link #ANNOT_FIELD_REGEX}解析ANN的注解定义列表
* 如果没有定义ANN字段则返回空 */ List getAnnotations(){ List annots = Lists.newArrayList(); Matcher matcher=Pattern.compile(ANNOT_FIELD_REGEX).matcher(remarks); while(matcher.find()) { annots.add(matcher.group(1)); } return annots; } /** * 从字段注释中根据正则表达式{@link #JSON_ANNOT_FIELD_REGEX}解析JSAN的注解定义列表
* 如果没有定义JSAN字段则返回空 * @since 3.32.0 */ List getJsonAnnotations(){ List annots = Lists.newArrayList(); Matcher matcher=Pattern.compile(JSON_ANNOT_FIELD_REGEX).matcher(remarks); while(matcher.find()) { annots.add(matcher.group(1)); } return annots; } /** * 从字段注释中根据正则表达式{@link #TYPE_FIELD_REGEX}解析TYPE的类型定义
* 如果不是TYPE字段则返回{@code null} */ String getFieldType(){ Matcher matcher=Pattern.compile(TYPE_FIELD_REGEX).matcher(remarks); if(matcher.find()) { return matcher.group(1); } return null; } /** * 从字段注释中根据正则表达式{@link #SCOPE_FIELD_REGEX}解析TYPE的类型定义
* 如果不是TYPE字段则返回{@code null} * @since 3.32.0 */ String getScopeType(){ Matcher matcher=Pattern.compile(SCOPE_FIELD_REGEX).matcher(remarks); if(matcher.find()) { return matcher.group(1); } return null; } /** * 注解中提取正则表达式定义的多符号定义保存到 Pair的key成员, * 将符号定义的key-value映射保存到Pair的value字段 * 如果没有定义则key为空字符串,value为空 * @param builder Map builder */ @SuppressWarnings("unchecked") private > Pair fetchMapDefine(String regex, M.Builder builder){ Matcher matcher=Pattern.compile(regex).matcher(this.remarks); String namesTag = matcher.find() ? matcher.group(1) : ""; if(!namesTag.isEmpty()){ String[] def = namesTag.split(","); for (String item : def){ String[] itemArray = item.split("[=:-]"); if(itemArray.length == 2){ String left = itemArray[0].trim(); String right = itemArray[1].trim(); if(!left.isEmpty()&& !right.isEmpty()){ builder.put(left, right); } } } } M m = (M) builder.build(); namesTag = m.toString(); namesTag = namesTag.substring(1,namesTag.length()-1); return new Pair(namesTag, m); } private static String formatValue(Class type,String v){ if(String.class.isAssignableFrom(type)){ return "\"" + v + "\""; }else if(Class.class.isAssignableFrom(type)){ return v.replaceAll("\\.class$", "") + ".class"; } return v; } /** * 返回注解类的所有方法名,输入参数为{@code null}返回空集合 * @param annotation */ private static Set methodNamesOf(Class annClass) { if(null != annClass){ return Sets.newLinkedHashSet(Lists.transform(Arrays.asList(annClass.getDeclaredMethods()),Method::getName)); } return Collections.emptySet(); } String getExcelAnnotation(ClassannotationType, Function headerColumns){ final Map tagMap ; if(ExcelColumn.class.equals(annotationType)){ tagMap = getColumnTagMap(); }else if(ExcelSheet.class.equals(annotationType)){ tagMap = getSheetTagMap(); }else { throw new IllegalArgumentException("@ExcelColumn or @ExcelSheet required for annotationType"); } StringBuffer buffer = new StringBuffer("@"+annotationType.getSimpleName()+"("); final AtomicInteger fillCount = new AtomicInteger(0); if(null != headerColumns){ Integer c = headerColumns.apply(buffer); if(null != c){ fillCount.addAndGet(c); } } /** 注释字段(方法)排序输出 */ Ordering.natural() .onResultOf(Method::getName) .sortedCopy(Arrays.asList(annotationType.getDeclaredMethods())) .forEach(m->{ String k = m.getName(); String v = tagMap.get(k); if(null != v){ if(fillCount.get() > 0){ buffer.append(","); } Class type = m.getReturnType(); if(type.isArray()){ Class componentType = type.getComponentType(); String elements = Joiner.on(',').join(Lists.transform(elementsOf(v,"|"),s->formatValue(componentType, s))); buffer.append(k + "={").append(elements).append("}"); }else{ buffer.append(k + "=").append(formatValue(type, v)); } fillCount.incrementAndGet(); } }); buffer.append(")"); return fillCount.get() > 0 ? buffer.toString() : null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy