mirror of
https://gitee.com/best_handsome/mybatis-plus-join
synced 2025-07-11 00:02:22 +08:00
feat: apt ognl
This commit is contained in:
parent
30377e4f5e
commit
7cd632f1ad
@ -1,37 +1,59 @@
|
|||||||
package com.github.yulichang.annotation;
|
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注解
|
||||||
|
* <p>
|
||||||
|
* 支持Ognl语法字段说明<br/>
|
||||||
|
* Ognl上下文
|
||||||
|
* <ul>
|
||||||
|
* <li>classInfo {@link com.github.yulichang.apt.OgnlRoot.ClassInfo}</li>
|
||||||
|
* <li>stringHelper {@link com.github.yulichang.apt.OgnlRoot.StringHelper}</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* 指定开头 Ognl# 这不是ognl语法,这是MPJ规定的 用于区分 ognl还是String.format
|
||||||
|
* <p>
|
||||||
|
* 举例:
|
||||||
|
* <ul>
|
||||||
|
* <li>去掉3长度的后缀并且大写 Ognl#classInfo.getClassName().substring(0, classInfo.getClassName().length() - 3).toUpperCase() </li>
|
||||||
|
* <li>以“APT”结尾 Ognl#classInfo.getClassName() + 'APT'</li>
|
||||||
|
* <li>全大写并且以“APT”结尾 Ognl#classInfo.getClassName().toUpperCase() + 'APT' </li>
|
||||||
|
* <li>"PO"结尾替换为“APT”且全大写 Ognl#stringHelper.replaceSuffix(classInfo.getClassName(), 'PO', 'APT').toUpperCase() </li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* 支持 三元运算 String所有方法 如lastIndexOf subString toUpperCase等 Ognl语法<p>
|
||||||
|
* 若想扩展stringHelper可在github交流
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.5.0
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
public @interface Table {
|
public @interface Table {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成类的类名前缀
|
* APT类名
|
||||||
|
* <p>
|
||||||
|
* 支持Ognl 默认使用String.format()
|
||||||
*/
|
*/
|
||||||
String prefix() default "";
|
String value() default "%sCol";
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成类的类名后缀
|
|
||||||
*/
|
|
||||||
String suffix() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* format 优先级低,如果配置了prefix或suffix则不会生效
|
|
||||||
*/
|
|
||||||
String format() default "%sCol";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成类的包名
|
* 生成类的包名
|
||||||
|
* <p>
|
||||||
|
* 支持Ognl 默认使用String.format()
|
||||||
*/
|
*/
|
||||||
String packageName() default "apt";
|
String packageName() default "%s.apt";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tables中的字段名 默认大写的类名
|
* Tables中的字段名 默认大写的类名
|
||||||
|
* <p>
|
||||||
|
* 支持Ognl 默认使用String.format()
|
||||||
*/
|
*/
|
||||||
String tablesName() default "%S";
|
String tablesName() default "%S";
|
||||||
|
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,9 +9,11 @@ import com.github.yulichang.processor.matedata.TableInfo;
|
|||||||
import com.github.yulichang.processor.utils.StringUtil;
|
import com.github.yulichang.processor.utils.StringUtil;
|
||||||
|
|
||||||
import javax.annotation.processing.AbstractProcessor;
|
import javax.annotation.processing.AbstractProcessor;
|
||||||
|
import javax.annotation.processing.Messager;
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.annotation.processing.RoundEnvironment;
|
import javax.annotation.processing.RoundEnvironment;
|
||||||
import javax.lang.model.SourceVersion;
|
import javax.lang.model.SourceVersion;
|
||||||
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.ElementKind;
|
import javax.lang.model.element.ElementKind;
|
||||||
import javax.lang.model.element.Modifier;
|
import javax.lang.model.element.Modifier;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
@ -35,21 +37,28 @@ public class EntityProcessor extends AbstractProcessor {
|
|||||||
|
|
||||||
private Elements elementUtils;
|
private Elements elementUtils;
|
||||||
private Types typeUtils;
|
private Types typeUtils;
|
||||||
|
private Messager messager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void init(ProcessingEnvironment processingEnv) {
|
public synchronized void init(ProcessingEnvironment processingEnv) {
|
||||||
super.init(processingEnv);
|
super.init(processingEnv);
|
||||||
this.elementUtils = processingEnv.getElementUtils();
|
this.elementUtils = processingEnv.getElementUtils();
|
||||||
this.typeUtils = processingEnv.getTypeUtils();
|
this.typeUtils = processingEnv.getTypeUtils();
|
||||||
|
this.messager = processingEnv.getMessager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||||
if (!roundEnv.processingOver()) {
|
if (!roundEnv.processingOver()) {
|
||||||
roundEnv.getElementsAnnotatedWith(Table.class).stream().filter(f -> f instanceof TypeElement)
|
TypeElement table = annotations.stream().filter(i -> i.toString().equals(Table.class.getName())).findFirst().orElse(null);
|
||||||
.map(f -> (TypeElement) f).map(this::createColumn)
|
if (table != null) {
|
||||||
.collect(Collectors.groupingBy(TableInfo::getClassPackage))
|
Set<? extends Element> tables = roundEnv.getElementsAnnotatedWith(table);
|
||||||
.forEach(this::createTables);
|
tables.stream().filter(f -> f instanceof TypeElement)
|
||||||
|
.map(f -> (TypeElement) f).map(this::createColumn)
|
||||||
|
.collect(Collectors.groupingBy(TableInfo::getClassPackage))
|
||||||
|
.forEach(this::createTables);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -71,9 +80,7 @@ public class EntityProcessor extends AbstractProcessor {
|
|||||||
* 生成Column类
|
* 生成Column类
|
||||||
*/
|
*/
|
||||||
private TableInfo createColumn(TypeElement element) {
|
private TableInfo createColumn(TypeElement element) {
|
||||||
TableInfo tableInfo = new TableInfo(element.getAnnotation(Table.class));
|
TableInfo tableInfo = new TableInfo(element.getAnnotation(Table.class), element.toString(), element.getSimpleName().toString());
|
||||||
tableInfo.setClassName(element.toString());
|
|
||||||
tableInfo.setSimpleClassName(element.getSimpleName().toString());
|
|
||||||
tableInfo.setClassPackage(elementUtils.getPackageOf(element).getQualifiedName().toString());
|
tableInfo.setClassPackage(elementUtils.getPackageOf(element).getQualifiedName().toString());
|
||||||
tableInfo.setClassComment(elementUtils.getDocComment(element));
|
tableInfo.setClassComment(elementUtils.getDocComment(element));
|
||||||
|
|
||||||
@ -146,7 +153,7 @@ public class EntityProcessor extends AbstractProcessor {
|
|||||||
writer.flush();
|
writer.flush();
|
||||||
writer.close();
|
writer.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
|
this.messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package com.github.yulichang.processor.matedata;
|
package com.github.yulichang.processor.matedata;
|
||||||
|
|
||||||
import com.github.yulichang.annotation.Table;
|
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;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -12,58 +16,76 @@ import java.util.Set;
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class TableInfo {
|
public class TableInfo {
|
||||||
|
|
||||||
public TableInfo(Table tableAnnotation) {
|
public static final String OGNL_PREFIX = "OGNL#";
|
||||||
this.tableAnnotation = tableAnnotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String className;
|
|
||||||
|
|
||||||
private String simpleClassName;
|
private final String className;
|
||||||
|
|
||||||
|
private final String simpleClassName;
|
||||||
|
|
||||||
private String classComment;
|
private String classComment;
|
||||||
|
|
||||||
private String classPackage;
|
private String classPackage;
|
||||||
|
|
||||||
private Table tableAnnotation;
|
private final Table tableAnnotation;
|
||||||
|
|
||||||
private Set<FieldInfo> fields;
|
private Set<FieldInfo> 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() {
|
public String getTagClassName() {
|
||||||
String tag = simpleClassName;
|
if (tagClassName == null) {
|
||||||
if (StringUtil.isNotEmpty(tableAnnotation.prefix()) || StringUtil.isNotEmpty(tableAnnotation.suffix())) {
|
tagClassName = parse(tableAnnotation.value(), this.simpleClassName);
|
||||||
tag = tableAnnotation.prefix() + tag + tableAnnotation.suffix();
|
|
||||||
} else {
|
|
||||||
tag = String.format(tableAnnotation.format(), tag);
|
|
||||||
}
|
}
|
||||||
return tag;
|
return tagClassName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成类的路径
|
* 生成类的路径
|
||||||
*/
|
*/
|
||||||
public String getTagPackage() {
|
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() {
|
public String getClassName() {
|
||||||
return className;
|
return className;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClassName(String className) {
|
|
||||||
this.className = className;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSimpleClassName() {
|
public String getSimpleClassName() {
|
||||||
return simpleClassName;
|
return simpleClassName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSimpleClassName(String simpleClassName) {
|
|
||||||
this.simpleClassName = simpleClassName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getClassComment() {
|
public String getClassComment() {
|
||||||
return classComment;
|
return classComment;
|
||||||
}
|
}
|
||||||
@ -84,10 +106,6 @@ public class TableInfo {
|
|||||||
return tableAnnotation;
|
return tableAnnotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTableAnnotation(Table tableAnnotation) {
|
|
||||||
this.tableAnnotation = tableAnnotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<FieldInfo> getFields() {
|
public Set<FieldInfo> getFields() {
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user