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

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

package gu.sql2java.generator;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
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 net.gdface.utils.Pair;

import static com.google.common.base.Strings.nullToEmpty;
import static net.gdface.utils.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})中的TYPE字段定义,用于插入Java注解代码
	 */
	private static final String TYPE_FIELD_REGEX="TYPE@(.+?)@EPYT";
	
	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(ANNOT_FIELD_REGEX, "")
					.replaceAll(TYPE_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 #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; } /** * 注解中提取正则表达式定义的多符号定义保存到 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