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;
|
||||
|
||||
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)
|
||||
public @interface Table {
|
||||
|
||||
/**
|
||||
* 生成类的类名前缀
|
||||
* APT类名
|
||||
* <p>
|
||||
* 支持Ognl 默认使用String.format()
|
||||
*/
|
||||
String prefix() default "";
|
||||
|
||||
/**
|
||||
* 生成类的类名后缀
|
||||
*/
|
||||
String suffix() default "";
|
||||
|
||||
/**
|
||||
* format 优先级低,如果配置了prefix或suffix则不会生效
|
||||
*/
|
||||
String format() default "%sCol";
|
||||
String value() default "%sCol";
|
||||
|
||||
/**
|
||||
* 生成类的包名
|
||||
* <p>
|
||||
* 支持Ognl 默认使用String.format()
|
||||
*/
|
||||
String packageName() default "apt";
|
||||
String packageName() default "%s.apt";
|
||||
|
||||
/**
|
||||
* Tables中的字段名 默认大写的类名
|
||||
* <p>
|
||||
* 支持Ognl 默认使用String.format()
|
||||
*/
|
||||
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 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<? extends TypeElement> 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<? extends Element> 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<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() {
|
||||
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<FieldInfo> getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user