From 7cd632f1adad22174bab1827d4db51f816b4b0d4 Mon Sep 17 00:00:00 2001 From: yulichang <570810310@qq.com> Date: Wed, 17 Jul 2024 02:55:03 +0800 Subject: [PATCH] feat: apt ognl --- .../github/yulichang/annotation/Table.java | 60 +++++++++----- .../com/github/yulichang/apt/OgnlRoot.java | 83 +++++++++++++++++++ .../yulichang/processor/EntityProcessor.java | 23 +++-- .../processor/matedata/TableInfo.java | 70 ++++++++++------ 4 files changed, 183 insertions(+), 53 deletions(-) create mode 100644 mybatis-plus-join-core/src/main/java/com/github/yulichang/apt/OgnlRoot.java diff --git a/mybatis-plus-join-annotation/src/main/java/com/github/yulichang/annotation/Table.java b/mybatis-plus-join-annotation/src/main/java/com/github/yulichang/annotation/Table.java index 117be10..89c6ce4 100644 --- a/mybatis-plus-join-annotation/src/main/java/com/github/yulichang/annotation/Table.java +++ b/mybatis-plus-join-annotation/src/main/java/com/github/yulichang/annotation/Table.java @@ -1,37 +1,59 @@ package com.github.yulichang.annotation; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; -@Documented -@Retention(RetentionPolicy.RUNTIME) +/** + * apt注解 + *

+ * 支持Ognl语法字段说明
+ * Ognl上下文 + *

+ *

+ * 指定开头 Ognl# 这不是ognl语法,这是MPJ规定的 用于区分 ognl还是String.format + *

+ * 举例: + *

+ *

+ * 支持 三元运算 String所有方法 如lastIndexOf subString toUpperCase等 Ognl语法

+ * 若想扩展stringHelper可在github交流 + * + * @author yulichang + * @since 1.5.0 + */ +@Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) public @interface Table { /** - * 生成类的类名前缀 + * APT类名 + *

+ * 支持Ognl 默认使用String.format() */ - String prefix() default ""; - - /** - * 生成类的类名后缀 - */ - String suffix() default ""; - - /** - * format 优先级低,如果配置了prefix或suffix则不会生效 - */ - String format() default "%sCol"; + String value() default "%sCol"; /** * 生成类的包名 + *

+ * 支持Ognl 默认使用String.format() */ - String packageName() default "apt"; + String packageName() default "%s.apt"; /** * Tables中的字段名 默认大写的类名 + *

+ * 支持Ognl 默认使用String.format() */ String tablesName() default "%S"; - -} - +} \ No newline at end of file diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/apt/OgnlRoot.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/apt/OgnlRoot.java new file mode 100644 index 0000000..69bdcda --- /dev/null +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/apt/OgnlRoot.java @@ -0,0 +1,83 @@ +package com.github.yulichang.apt; + +import lombok.Getter; + +import java.util.Objects; + +/** + * apt ognl表达式上下文 + * + * @author yulichang + * @since 1.5.0 + */ +@Getter +public class OgnlRoot { + + private final ClassInfo classInfo; + + private final StringHelper stringHelper; + + public OgnlRoot(String className, String packageName) { + this.classInfo = new ClassInfo(className, packageName); + this.stringHelper = new StringHelper(); + } + + @Getter + public static class ClassInfo { + /** + * 类名 + */ + private final String className; + /** + * 包名 + */ + private final String packageName; + + + public ClassInfo(String className, String packageName) { + this.className = className; + this.packageName = packageName; + } + } + + @SuppressWarnings("unused") + public static final class StringHelper { + /** + * 替换后缀 + * + * @param str 原字符串 + * @param suffix 指定后缀 + * @param replacement 新后缀 + */ + public String replaceSuffix(String str, String suffix, String replacement) { + if (isBlank(str)) { + return str; + } + String rep = Objects.isNull(replacement) ? "" : replacement; + if (isBlank(suffix)) { + return str + rep; + } + if (str.endsWith(suffix)) { + return str.substring(0, str.length() - suffix.length()) + rep; + } + return str; + } + + /** + * 获取上级包名 + * + * @param pk 报名 + * @return 上级报名 + */ + public String getParentPackage(String pk) { + if (pk.lastIndexOf(".") > -1) { + return pk; + } + return pk.substring(0, pk.lastIndexOf('.')); + } + + private boolean isBlank(String str) { + return str == null || str.trim().isEmpty(); + } + } +} diff --git a/plugin/mybatis-plus-join-processor/src/main/java/com/github/yulichang/processor/EntityProcessor.java b/plugin/mybatis-plus-join-processor/src/main/java/com/github/yulichang/processor/EntityProcessor.java index 446fd15..7c99160 100644 --- a/plugin/mybatis-plus-join-processor/src/main/java/com/github/yulichang/processor/EntityProcessor.java +++ b/plugin/mybatis-plus-join-processor/src/main/java/com/github/yulichang/processor/EntityProcessor.java @@ -9,9 +9,11 @@ import com.github.yulichang.processor.matedata.TableInfo; import com.github.yulichang.processor.utils.StringUtil; import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; @@ -35,21 +37,28 @@ public class EntityProcessor extends AbstractProcessor { private Elements elementUtils; private Types typeUtils; + private Messager messager; @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); this.elementUtils = processingEnv.getElementUtils(); this.typeUtils = processingEnv.getTypeUtils(); + this.messager = processingEnv.getMessager(); } + @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if (!roundEnv.processingOver()) { - roundEnv.getElementsAnnotatedWith(Table.class).stream().filter(f -> f instanceof TypeElement) - .map(f -> (TypeElement) f).map(this::createColumn) - .collect(Collectors.groupingBy(TableInfo::getClassPackage)) - .forEach(this::createTables); + TypeElement table = annotations.stream().filter(i -> i.toString().equals(Table.class.getName())).findFirst().orElse(null); + if (table != null) { + Set tables = roundEnv.getElementsAnnotatedWith(table); + tables.stream().filter(f -> f instanceof TypeElement) + .map(f -> (TypeElement) f).map(this::createColumn) + .collect(Collectors.groupingBy(TableInfo::getClassPackage)) + .forEach(this::createTables); + } } return false; } @@ -71,9 +80,7 @@ public class EntityProcessor extends AbstractProcessor { * 生成Column类 */ private TableInfo createColumn(TypeElement element) { - TableInfo tableInfo = new TableInfo(element.getAnnotation(Table.class)); - tableInfo.setClassName(element.toString()); - tableInfo.setSimpleClassName(element.getSimpleName().toString()); + TableInfo tableInfo = new TableInfo(element.getAnnotation(Table.class), element.toString(), element.getSimpleName().toString()); tableInfo.setClassPackage(elementUtils.getPackageOf(element).getQualifiedName().toString()); tableInfo.setClassComment(elementUtils.getDocComment(element)); @@ -146,7 +153,7 @@ public class EntityProcessor extends AbstractProcessor { writer.flush(); writer.close(); } catch (Exception e) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage()); + this.messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage()); } } diff --git a/plugin/mybatis-plus-join-processor/src/main/java/com/github/yulichang/processor/matedata/TableInfo.java b/plugin/mybatis-plus-join-processor/src/main/java/com/github/yulichang/processor/matedata/TableInfo.java index a4dd36c..c6d7a93 100644 --- a/plugin/mybatis-plus-join-processor/src/main/java/com/github/yulichang/processor/matedata/TableInfo.java +++ b/plugin/mybatis-plus-join-processor/src/main/java/com/github/yulichang/processor/matedata/TableInfo.java @@ -1,7 +1,11 @@ package com.github.yulichang.processor.matedata; import com.github.yulichang.annotation.Table; -import com.github.yulichang.processor.utils.StringUtil; +import com.github.yulichang.apt.OgnlRoot; +import org.apache.ibatis.builder.BuilderException; +import org.apache.ibatis.ognl.Ognl; +import org.apache.ibatis.ognl.OgnlContext; +import org.apache.ibatis.ognl.OgnlException; import java.util.Set; @@ -12,58 +16,76 @@ import java.util.Set; @SuppressWarnings("unused") public class TableInfo { - public TableInfo(Table tableAnnotation) { - this.tableAnnotation = tableAnnotation; - } + public static final String OGNL_PREFIX = "OGNL#"; - private String className; - private String simpleClassName; + private final String className; + + private final String simpleClassName; private String classComment; private String classPackage; - private Table tableAnnotation; + private final Table tableAnnotation; private Set fields; + private String tagClassName; + private String tagPackageName; + + public TableInfo(Table tableAnnotation, String className, String simpleClassName) { + this.tableAnnotation = tableAnnotation; + this.className = className; + this.simpleClassName = simpleClassName; + } + /** * 生成的类名 */ public String getTagClassName() { - String tag = simpleClassName; - if (StringUtil.isNotEmpty(tableAnnotation.prefix()) || StringUtil.isNotEmpty(tableAnnotation.suffix())) { - tag = tableAnnotation.prefix() + tag + tableAnnotation.suffix(); - } else { - tag = String.format(tableAnnotation.format(), tag); + if (tagClassName == null) { + tagClassName = parse(tableAnnotation.value(), this.simpleClassName); } - return tag; + return tagClassName; } /** * 生成类的路径 */ public String getTagPackage() { - return classPackage + "." + tableAnnotation.packageName(); + if (tagPackageName == null) { + tagPackageName = parse(tableAnnotation.packageName(), this.classPackage); + } + return tagPackageName; + } + + + private String parse(String expression, String source) { + String tag; + if (expression.toUpperCase().startsWith(OGNL_PREFIX)) { + String ognl = expression.substring(OGNL_PREFIX.length()); + OgnlRoot root = new OgnlRoot(this.simpleClassName, this.classPackage); + OgnlContext context = Ognl.createDefaultContext(root); + try { + return Ognl.getValue(ognl, context, context.getRoot()).toString(); + } catch (OgnlException e) { + throw new BuilderException("Error evaluating expression '" + ognl + "'. Cause: " + e, e); + } + } else { + tag = String.format(expression, source); + } + return tag; } public String getClassName() { return className; } - public void setClassName(String className) { - this.className = className; - } - public String getSimpleClassName() { return simpleClassName; } - public void setSimpleClassName(String simpleClassName) { - this.simpleClassName = simpleClassName; - } - public String getClassComment() { return classComment; } @@ -84,10 +106,6 @@ public class TableInfo { return tableAnnotation; } - public void setTableAnnotation(Table tableAnnotation) { - this.tableAnnotation = tableAnnotation; - } - public Set getFields() { return fields; }