From 4f2070b1b884cf55516c77301df8c144e953c0b2 Mon Sep 17 00:00:00 2001 From: Firok Date: Wed, 30 Mar 2022 17:06:13 +0800 Subject: [PATCH] 17.2.0 --- pom.xml | 12 +- readme.md | 40 +++- .../spring/mvci/MVCIntrospectProcessor.java | 36 +-- .../spring/mvci/internal/BeanContext.java | 206 +++++++++--------- .../spring/mvci/internal/ResourceCache.java | 39 ++++ .../spring/mvci/internal/RuntimeGenerate.java | 130 +++++++++++ .../mvci/runtime/CurrentBeanClasses.java | 38 ++++ .../spring/mvci/runtime/CurrentBeanNames.java | 20 ++ .../runtime/CurrentControllerClasses.java | 38 ++++ .../mvci/runtime/CurrentControllerNames.java | 38 ++++ .../mvci/runtime/CurrentMapperClasses.java | 38 ++++ .../mvci/runtime/CurrentMapperNames.java | 38 ++++ .../mvci/runtime/CurrentServiceClasses.java | 38 ++++ .../runtime/CurrentServiceImplClasses.java | 38 ++++ .../mvci/runtime/CurrentServiceImplNames.java | 38 ++++ .../mvci/runtime/CurrentServiceNames.java | 38 ++++ .../spring/mvci/runtime/package-info.java | 6 + src/main/resources/current_classes.txt | 17 ++ .../resources/current_names_with_mapping.txt | 17 ++ .../current_names_without_mapping.txt | 9 + 20 files changed, 752 insertions(+), 122 deletions(-) create mode 100644 src/main/java/firok/spring/mvci/internal/ResourceCache.java create mode 100644 src/main/java/firok/spring/mvci/internal/RuntimeGenerate.java create mode 100644 src/main/java/firok/spring/mvci/runtime/CurrentBeanClasses.java create mode 100644 src/main/java/firok/spring/mvci/runtime/CurrentBeanNames.java create mode 100644 src/main/java/firok/spring/mvci/runtime/CurrentControllerClasses.java create mode 100644 src/main/java/firok/spring/mvci/runtime/CurrentControllerNames.java create mode 100644 src/main/java/firok/spring/mvci/runtime/CurrentMapperClasses.java create mode 100644 src/main/java/firok/spring/mvci/runtime/CurrentMapperNames.java create mode 100644 src/main/java/firok/spring/mvci/runtime/CurrentServiceClasses.java create mode 100644 src/main/java/firok/spring/mvci/runtime/CurrentServiceImplClasses.java create mode 100644 src/main/java/firok/spring/mvci/runtime/CurrentServiceImplNames.java create mode 100644 src/main/java/firok/spring/mvci/runtime/CurrentServiceNames.java create mode 100644 src/main/java/firok/spring/mvci/runtime/package-info.java create mode 100644 src/main/resources/current_classes.txt create mode 100644 src/main/resources/current_names_with_mapping.txt create mode 100644 src/main/resources/current_names_without_mapping.txt diff --git a/pom.xml b/pom.xml index 795d955..55d33c6 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ firok.spring mvci - 17.1.1 + 17.2.0 An annotation processing tool to generate MVC code from JavaBean(s). @@ -24,23 +24,15 @@ - - maven-compiler-plugin - 3.7.0 - - 1.8 - 1.8 - - org.apache.maven.plugins maven-compiler-plugin + 3.7.0 17 17 - diff --git a/readme.md b/readme.md index 3ad6a6b..d9bdcd3 100644 --- a/readme.md +++ b/readme.md @@ -72,19 +72,57 @@ > 生成 `a.b.c.Test2Bean` 实体时将使用 `##TEST## = "test2"`, > 生成 `a.b.DemoBean` 实体时将使用 `##TEST## = "test"` +### 运行时数据类 + +`17.2.0` 版本之后的 MVCI 在参与编译时会在 `firok.spring.mvci.runtime` 包下生成数个类, +操作这些类可以获取本项目中所有标注了 `@MVCIntrospective` 注解并生成了相应结构的实体信息. + +所有信息都按照两种方式存放在 `XXX Names` 和 `XXX Classes` 类内. + +> **为什么要以两种方式储存信息** +> +> 根据 [虚拟机规范(Java SE 17)对类初始化的描述](https://docs.oracle.com/javase/specs/jls/se17/html/jls-12.html#:~:text=12.4.1.%C2%A0-,When%20Initialization%20Occurs,-A%20class%20or), +> 某个类初次实例化之前或其静态字段初次被主动引用之前, +> 此类一定会先进行类初始化. +> GraalVM 下经测试, +> 仅是访问某个类的 Class 对象不会触发其类加载. +> +> 为了避免不同编译器或解释器实现可能出现的不同实现, +> MVCI 仍储存了一份字符串类型的信息, +> 以完全避免期望之外的类加载. + ## 注意 +### 关于代码生成模板 + **MVCI 本身** 不基于 SpringBoot 和 MybatisPlus, 但是 **MVCI 默认的结构代码模板** 基于 SpringBoot 和 MybatisPlus. 所以默认情况下需为编译环境引入相关依赖, 否则项目无法通过编译. 此外, 还需要正确提供数据库驱动等依赖, 否则项目可能无法正常运行. -MVCI 仅于 **Java17 环境** 下通过测试. +### 关于运行时数据类 + +`firok.spring.mvci.runtime` 包下的各信息类的字段和方法内容会在编译期动态扩展. + +* `firok.spring.mvci.runtime.CurrentBeanNames` 和 `firok.spring.mvci.runtime.CurrentBeanClasses` 中 + 包含有项目中 **所有** 标注了 `@MVCIntrospective` 注解的实体类信息 +* 其它 `firok.spring.mvci.runtime.CurrentXXXNames` 和 `firok.spring.mvci.runtime.CurrentXXXClasses` 中 + 包含有项目中 **由 MVCI 生成了相应结构** 的实体信息 + +比如, 如果实体 `TestBean` 没有配置生成 `Controller` 结构, 在 `CurrentControllerNames.NAMES` 数组内就不会包含相应信息, 且使用 `TestBean` 的完整限定名作为参数调用 `#getByFullQualifiedBeanName` 将会返回 `null`. + +### 关于 Java 版本 + +MVCI 17.x 仅于 **Java17 环境** 下通过测试. 更低 Java 版本中仍可能使用, 但是您需要手动调整 `firok.spring.mvci.MVCIntrospectProcessor` 上的 `@SupportedSourceVersion` 注解值和部分 MVCI 代码. ## 变动记录 +### 17.2.0 + +* 现在 MVCI 将会额外生成数个包含生成数据的信息的类 + ### 17.1.1 * 细微代码改动 diff --git a/src/main/java/firok/spring/mvci/MVCIntrospectProcessor.java b/src/main/java/firok/spring/mvci/MVCIntrospectProcessor.java index 321bc5d..369ccbe 100644 --- a/src/main/java/firok/spring/mvci/MVCIntrospectProcessor.java +++ b/src/main/java/firok/spring/mvci/MVCIntrospectProcessor.java @@ -1,6 +1,9 @@ package firok.spring.mvci; import firok.spring.mvci.internal.BeanContext; +import firok.spring.mvci.internal.RegexPipeline; +import firok.spring.mvci.internal.ResourceCache; +import firok.spring.mvci.internal.RuntimeGenerate; import lombok.SneakyThrows; import javax.annotation.processing.*; @@ -11,13 +14,13 @@ import javax.lang.model.util.Types; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; +import javax.tools.StandardLocation; +import java.io.IOException; import java.io.Writer; import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Set; +import java.util.*; +@SuppressWarnings({"unused", "FieldCanBeLocal"}) @SupportedAnnotationTypes({ "firok.spring.mvci.MVCIntrospective", "firok.spring.mvci.MVCConfig", @@ -29,15 +32,15 @@ public class MVCIntrospectProcessor extends AbstractProcessor private Elements elementUtils; private Filer filer; private Messager messager; - private void printNote(Object obj) + public void printNote(Object obj) { messager.printMessage(Diagnostic.Kind.NOTE,"[MVCI] " + obj); } - private void printWarning(Object obj) + public void printWarning(Object obj) { messager.printMessage(Diagnostic.Kind.WARNING,"[MVCI] " + obj); } - private void printError(Object obj) + public void printError(Object obj) { messager.printMessage(Diagnostic.Kind.ERROR,"[MVCI] " + obj); } @@ -60,13 +63,14 @@ public synchronized void init(ProcessingEnvironment processingEnv) { * 省得出问题 还是加上个锁吧 */ private static final Object LOCK_JFO_API = new Object(); - public Writer createSourceFileWrite(String location) throws Exception + public Writer createSourceFileWrite(String location) throws IOException { JavaFileObject jfo; synchronized (LOCK_JFO_API) { jfo = filer.createSourceFile(location); return jfo.openWriter(); } } + @SuppressWarnings("ReflectionForUnavailableAnnotation") @SneakyThrows private void checkAnnotation(Annotation anno) { @@ -118,6 +122,9 @@ public boolean process(Set annotations, RoundEnvironment var setAnno = roundEnv.getElementsAnnotatedWith(MVCIntrospective.class); if(setAnno.isEmpty()) return true; + // 所有生成的实体数据 + var listContext = new Vector(); + setAnno.stream().parallel().forEach(ele -> { if(ele instanceof TypeElement eleBean) { @@ -167,19 +174,22 @@ public boolean process(Set annotations, RoundEnvironment // 开始生成 context.generate(); + listContext.add(context); } }); + + // 根据实体数据生成runtime类 + printNote("开始生成运行时内容..."); + RuntimeGenerate.startGenAll(listContext, this); + + printNote("完成生成"); } catch (Exception e) { -// if(e.getStackTrace() != null) -// for(var st : e.getStackTrace()) -// { -// printWarning(st.toString()); -// } printError(e); } return true; } + } diff --git a/src/main/java/firok/spring/mvci/internal/BeanContext.java b/src/main/java/firok/spring/mvci/internal/BeanContext.java index fd0704e..294db36 100644 --- a/src/main/java/firok/spring/mvci/internal/BeanContext.java +++ b/src/main/java/firok/spring/mvci/internal/BeanContext.java @@ -1,5 +1,6 @@ package firok.spring.mvci.internal; +import firok.spring.mvci.Constants; import firok.spring.mvci.MVCIntrospectProcessor; import firok.spring.mvci.MVCIntrospective; import firok.spring.mvci.Param; @@ -7,7 +8,6 @@ import javax.lang.model.element.TypeElement; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import java.util.function.Supplier; @@ -19,28 +19,28 @@ public class BeanContext final List configs; final MVCIntrospectProcessor mvci; - Map mapExtraParams = new HashMap<>(); + public Map mapExtraParams = new HashMap<>(); // String basePackage; // String beanNameShort; // String beanNameFull; - boolean shouldMapper; - boolean shouldService; - boolean shouldServiceImpl; - boolean shouldController; - String templateMapperName; - String templateServiceName; - String templateServiceImplName; - String templateControllerName; - String templateMapperPackage; - String templateServicePackage; - String templateServiceImplPackage; - String templateControllerPackage; - String templateMapper; - String templateService; - String templateServiceImpl; - String templateController; + public boolean shouldMapper; + public boolean shouldService; + public boolean shouldServiceImpl; + public boolean shouldController; + public String templateMapperName; + public String templateServiceName; + public String templateServiceImplName; + public String templateControllerName; + public String templateMapperPackage; + public String templateServicePackage; + public String templateServiceImplPackage; + public String templateControllerPackage; + public String templateMapper; + public String templateService; + public String templateServiceImpl; + public String templateController; public BeanContext(List configs, TypeElement eleBean, MVCIntrospectProcessor mvci) @@ -52,6 +52,58 @@ public BeanContext(List configs, TypeElement eleBean, MVCIntro // 为当前实体创建参数上下文 for(var config : configs) readExtraParams(config.extraParams()); + + final String beanQualifiedName = eleBean.getQualifiedName().toString(); + final int beanQualifiedNameLastDot = beanQualifiedName.lastIndexOf("."); + + String beanNameFull = nonDefault(configs, MVCIntrospective::beanNameFull, ()-> beanQualifiedName.substring(beanQualifiedNameLastDot + 1)); + String beanNameShort; + if(beanNameFull.startsWith("Bean")) + beanNameShort = beanNameFull.substring(4); + else if(beanNameFull.startsWith("Entity")) + beanNameShort = beanNameFull.substring(6); + else if(beanNameFull.endsWith("Bean")) + beanNameShort = beanNameFull.substring(0,beanNameFull.length()-4); + else if(beanNameFull.endsWith("Entity")) + beanNameShort = beanNameFull.substring(0,beanNameFull.length()-6); + else beanNameShort = beanNameFull; + String beanPackage = beanQualifiedName.substring(0, beanQualifiedNameLastDot); + + mapExtraParams.put(BEAN_NAME_FULL, beanNameFull); + mapExtraParams.put(BEAN_NAME_SHORT, beanNameShort); + mapExtraParams.put(BEAN_PACKAGE, beanPackage); + + // 根据配置 处理各种参数 + shouldMapper = should(configs, MVCIntrospective::generateMapper); + shouldService = should(configs, MVCIntrospective::generateService); + shouldServiceImpl = should(configs, MVCIntrospective::generateServiceImpl); + shouldController = should(configs, MVCIntrospective::generateController); + + // 根据配置 加载模板 + templateMapperName = templateOrResource(configs, MVCIntrospective::templateMapperName, "mapper.name"); + templateServiceName = templateOrResource(configs, MVCIntrospective::templateServiceName, "service.name"); + templateServiceImplName = templateOrResource(configs, MVCIntrospective::templateServiceImplName, "service_impl.name"); + templateControllerName = templateOrResource(configs, MVCIntrospective::templateControllerName, "controller.name"); + + templateMapperPackage = templateOrResource(configs, MVCIntrospective::templateMapperPackage, "mapper.package"); + templateServicePackage = templateOrResource(configs, MVCIntrospective::templateServicePackage, "service.package"); + templateServiceImplPackage = templateOrResource(configs, MVCIntrospective::templateServiceImplPackage, "service_impl.package"); + templateControllerPackage = templateOrResource(configs, MVCIntrospective::templateControllerPackage, "controller.package"); + + templateMapper = shouldMapper ? templateOrResource(configs, MVCIntrospective::templateMapperContent, "mapper.java") : null; + templateService = shouldService ? templateOrResource(configs, MVCIntrospective::templateServiceContent, "service.java") : null; + templateServiceImpl = shouldServiceImpl ? templateOrResource(configs, MVCIntrospective::templateServiceImplContent, "service_impl.java") : null; + templateController = shouldController ? templateOrResource(configs, MVCIntrospective::templateControllerContent, "controller.java") : null; + + single(MAPPER_NAME, templateMapperName); + single(SERVICE_NAME, templateServiceName); + single(SERVICE_IMPL_NAME, templateServiceImplName); + single(CONTROLLER_NAME, templateControllerName); + + single(MAPPER_PACKAGE, templateMapperPackage, paramMapper); + single(SERVICE_PACKAGE, templateServicePackage, paramService); + single(SERVICE_IMPL_PACKAGE, templateServiceImplPackage, paramServiceImpl); + single(CONTROLLER_PACKAGE, templateControllerPackage, paramController); } @@ -64,6 +116,9 @@ private void readExtraParams(Param[] customValues) } } + /** + * 根据配置注解判断所需字段是否为真 + */ private static boolean should(List configs, Function mapper) { boolean ret = false; @@ -84,6 +139,9 @@ private static boolean should(List configs, Function configs, Function mapper, @@ -102,35 +160,9 @@ private static String templateOrResource( return value; } } - return resource(defaultLocation); - } - private static final Map mapCachedResources = new ConcurrentHashMap<>(); - private static String resource(String location) - { - return mapCachedResources.computeIfAbsent(location, loc -> { - var ret = new StringBuilder(); - try(var is = Objects.requireNonNull( - BeanContext.class.getClassLoader().getResourceAsStream(location + ".txt"), - "resource not found: "+location - ); - var in = new Scanner(is) - ) { - boolean hasNextLine; - do - { - ret.append(in.nextLine()); - hasNextLine = in.hasNextLine(); - if(hasNextLine) ret.append('\n'); - } - while (hasNextLine); - } - catch (Exception e) - { - throw new RuntimeException(e); - } - return ret.toString(); - }); + return ResourceCache.getResourceString(defaultLocation); } + private static String nonDefault(List configs, Function mapper, Supplier defaultValue) { FOR: for(var config : configs) @@ -185,62 +217,40 @@ private void write(String valueKeyLocation, String valueKeyName, String template @SneakyThrows public void generate() { - final String beanQualifiedName = eleBean.getQualifiedName().toString(); - final int beanQualifiedNameLastDot = beanQualifiedName.lastIndexOf("."); - - String beanNameFull = nonDefault(configs, MVCIntrospective::beanNameFull, ()-> beanQualifiedName.substring(beanQualifiedNameLastDot + 1)); - String beanNameShort; - if(beanNameFull.startsWith("Bean")) - beanNameShort = beanNameFull.substring(4); - else if(beanNameFull.startsWith("Entity")) - beanNameShort = beanNameFull.substring(6); - else if(beanNameFull.endsWith("Bean")) - beanNameShort = beanNameFull.substring(0,beanNameFull.length()-4); - else if(beanNameFull.endsWith("Entity")) - beanNameShort = beanNameFull.substring(0,beanNameFull.length()-6); - else beanNameShort = beanNameFull; - String beanPackage = beanQualifiedName.substring(0, beanQualifiedNameLastDot); - - mapExtraParams.put(BEAN_NAME_FULL, beanNameFull); - mapExtraParams.put(BEAN_NAME_SHORT, beanNameShort); - mapExtraParams.put(BEAN_PACKAGE, beanPackage); - - // 根据配置 处理各种参数 - shouldMapper = should(configs, MVCIntrospective::generateMapper); - shouldService = should(configs, MVCIntrospective::generateService); - shouldServiceImpl = should(configs, MVCIntrospective::generateServiceImpl); - shouldController = should(configs, MVCIntrospective::generateController); - - // 根据配置 加载模板 - templateMapperName = templateOrResource(configs, MVCIntrospective::templateMapperName, "mapper.name"); - templateServiceName = templateOrResource(configs, MVCIntrospective::templateServiceName, "service.name"); - templateServiceImplName = templateOrResource(configs, MVCIntrospective::templateServiceImplName, "service_impl.name"); - templateControllerName = templateOrResource(configs, MVCIntrospective::templateControllerName, "controller.name"); - - templateMapperPackage = templateOrResource(configs, MVCIntrospective::templateMapperPackage, "mapper.package"); - templateServicePackage = templateOrResource(configs, MVCIntrospective::templateServicePackage, "service.package"); - templateServiceImplPackage = templateOrResource(configs, MVCIntrospective::templateServiceImplPackage, "service_impl.package"); - templateControllerPackage = templateOrResource(configs, MVCIntrospective::templateControllerPackage, "controller.package"); - - templateMapper = shouldMapper ? templateOrResource(configs, MVCIntrospective::templateMapperContent, "mapper.java") : null; - templateService = shouldService ? templateOrResource(configs, MVCIntrospective::templateServiceContent, "service.java") : null; - templateServiceImpl = shouldServiceImpl ? templateOrResource(configs, MVCIntrospective::templateServiceImplContent, "service_impl.java") : null; - templateController = shouldController ? templateOrResource(configs, MVCIntrospective::templateControllerContent, "controller.java") : null; - - single(MAPPER_NAME, templateMapperName); - single(SERVICE_NAME, templateServiceName); - single(SERVICE_IMPL_NAME, templateServiceImplName); - single(CONTROLLER_NAME, templateControllerName); - - single(MAPPER_PACKAGE, templateMapperPackage, paramMapper); - single(SERVICE_PACKAGE, templateServicePackage, paramService); - single(SERVICE_IMPL_PACKAGE, templateServiceImplPackage, paramServiceImpl); - single(CONTROLLER_PACKAGE, templateControllerPackage, paramController); - // 生成代码文件 if(shouldMapper) write(MAPPER_PACKAGE, MAPPER_NAME, templateMapper); if(shouldService) write(SERVICE_PACKAGE, SERVICE_NAME, templateService); if(shouldServiceImpl) write(SERVICE_IMPL_PACKAGE, SERVICE_IMPL_NAME, templateServiceImpl); if(shouldController) write(CONTROLLER_PACKAGE, CONTROLLER_NAME, templateController); } + + private String cacheBean, cacheMapper, cacheService, cacheServiceImpl, cacheController; + public String getBeanFullQualifiedName() + { + return cacheBean != null ? + cacheBean : + (cacheBean = mapExtraParams.get(BEAN_PACKAGE) + "." + mapExtraParams.get(BEAN_NAME_FULL)); + } + public String getMapperFullQualifiedName() + { + return cacheMapper != null ? + cacheMapper : + (cacheMapper = mapExtraParams.get(MAPPER_PACKAGE) + "." + mapExtraParams.get(MAPPER_NAME)); + } + public String getServiceFullQualifiedName() + { + return cacheService != null ? + cacheService : + (cacheService = mapExtraParams.get(SERVICE_PACKAGE) + "." + mapExtraParams.get(SERVICE_NAME)); + } + public String getServiceImplFullQualifiedName() + { + return cacheServiceImpl != null ? cacheServiceImpl : + (cacheServiceImpl = mapExtraParams.get(SERVICE_IMPL_PACKAGE) + "." + mapExtraParams.get(SERVICE_IMPL_NAME)); + } + public String getControllerFullQualifiedName() + { + return cacheController != null ? cacheController : + (cacheController = mapExtraParams.get(CONTROLLER_PACKAGE) + "." + mapExtraParams.get(CONTROLLER_NAME)); + } } diff --git a/src/main/java/firok/spring/mvci/internal/ResourceCache.java b/src/main/java/firok/spring/mvci/internal/ResourceCache.java new file mode 100644 index 0000000..5e7093b --- /dev/null +++ b/src/main/java/firok/spring/mvci/internal/ResourceCache.java @@ -0,0 +1,39 @@ +package firok.spring.mvci.internal; + +import java.util.Map; +import java.util.Objects; +import java.util.Scanner; +import java.util.concurrent.ConcurrentHashMap; + +public class ResourceCache +{ + + private static final Map mapCachedResources = new ConcurrentHashMap<>(); + public static String getResourceString(String location) + { + return mapCachedResources.computeIfAbsent(location, loc -> { + var ret = new StringBuilder(); + try(var is = Objects.requireNonNull( + BeanContext.class.getClassLoader().getResourceAsStream(location + ".txt"), + "resource not found: "+location + ); + var in = new Scanner(is) + ) { + boolean hasNextLine; + do + { + ret.append(in.nextLine()); + hasNextLine = in.hasNextLine(); + if(hasNextLine) ret.append('\n'); + } + while (hasNextLine); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + return ret.toString(); + }); + } + +} diff --git a/src/main/java/firok/spring/mvci/internal/RuntimeGenerate.java b/src/main/java/firok/spring/mvci/internal/RuntimeGenerate.java new file mode 100644 index 0000000..5bdf456 --- /dev/null +++ b/src/main/java/firok/spring/mvci/internal/RuntimeGenerate.java @@ -0,0 +1,130 @@ +package firok.spring.mvci.internal; + +import firok.spring.mvci.MVCIntrospectProcessor; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.function.Function; + +public class RuntimeGenerate +{ + /** + * 生成所有运行时内容 + */ + public static void startGenAll( + List listContext, + MVCIntrospectProcessor processor + ) throws IOException + { + genOnePart("Bean", BeanContext::getBeanFullQualifiedName, listContext, processor); + genOnePart("Mapper", BeanContext::getMapperFullQualifiedName, listContext, processor); + genOnePart("Service", BeanContext::getServiceFullQualifiedName, listContext, processor); + genOnePart("ServiceImpl", BeanContext::getServiceImplFullQualifiedName, listContext, processor); + genOnePart("Controller", BeanContext::getControllerFullQualifiedName, listContext, processor); + } + + private static void genOnePart( + String type, Function funGetFullQualifiedName, + List listContext, + MVCIntrospectProcessor processor + ) throws IOException + { + if("Bean".equals(type)) startGenSomeNamesWithoutMappings(type, funGetFullQualifiedName, listContext, processor); + else startGenSomeNamesWithMappings(type, funGetFullQualifiedName, listContext, processor); + startGenSomeClasses(type, funGetFullQualifiedName, listContext, processor); + } + + private static boolean should(BeanContext context, String type) + { + return switch (type) + { + case "Mapper" -> context.shouldMapper; + case "Service" -> context.shouldService; + case "ServiceImpl" -> context.shouldServiceImpl; + case "Controller" -> context.shouldController; + default -> true; + }; + } + + private static void startGenSomeNamesWithoutMappings( + String type, Function funGetFullQualifiedName, + List listContext, + MVCIntrospectProcessor processor + ) throws IOException + { + final var template = ResourceCache.getResourceString("current_names_without_mapping"); + final var bufferName = new StringBuilder(); + for(var objContext : listContext) + { + if(!should(objContext, type)) continue; + + final var targetRef = funGetFullQualifiedName.apply(objContext); + bufferName.append("\n\"").append(targetRef).append("\","); + } + final var paramBeanName = new HashMap(); + paramBeanName.put("##TYPE_NAME##", type); + paramBeanName.put("##NAMES_NAME##", bufferName.toString()); + + try(var writer = processor.createSourceFileWrite("firok.spring.mvci.runtime.Current" + type + "Names")) + { + writer.write(RegexPipeline.pipelineAll(template, paramBeanName)); + } + } + private static void startGenSomeNamesWithMappings( + String type, Function funGetFullQualifiedName, + List listContext, + MVCIntrospectProcessor processor + ) throws IOException + { + final var template = ResourceCache.getResourceString("current_names_without_mapping"); + final var bufferName = new StringBuilder(); + final var bufferMapping = new StringBuilder(); + for(var objContext : listContext) + { + if(!should(objContext, type)) continue; + + final var beanRef = objContext.getBeanFullQualifiedName(); + final var targetRef = funGetFullQualifiedName.apply(objContext); + bufferName.append("\n\"").append(targetRef).append("\","); + bufferMapping.append("\ncase \"").append(beanRef).append("\" -> \"").append(targetRef).append("\";"); + } + final var paramBeanName = new HashMap(); + paramBeanName.put("##TYPE_NAME##", type); + paramBeanName.put("##NAMES_NAME##", bufferName.toString()); + paramBeanName.put("##MAPPINGS_NAME##", bufferMapping.toString()); + + try(var writer = processor.createSourceFileWrite("firok.spring.mvci.runtime.Current" + type + "Names")) + { + writer.write(RegexPipeline.pipelineAll(template, paramBeanName)); + } + } + private static void startGenSomeClasses( + String type, Function funGetFullQualifiedName, + List listContext, + MVCIntrospectProcessor processor + ) throws IOException + { + final var template = ResourceCache.getResourceString("current_classes"); + final var bufferClass = new StringBuilder(); + final var bufferSwitch = new StringBuilder(); + for(final var objContext : listContext) + { + if(!should(objContext, type)) continue; + + final var beanRef = objContext.getBeanFullQualifiedName(); + final var targetRef = funGetFullQualifiedName.apply(objContext); + bufferClass.append("\n").append(targetRef).append(".class,"); + bufferSwitch.append("\ncase \"").append(beanRef).append("\" -> ").append(targetRef).append(".class;"); + } + final var paramBeanClass = new HashMap(); + paramBeanClass.put("##TYPE_CLASS##", type); + paramBeanClass.put("##CLASSES_CLASS##", bufferClass.toString()); + paramBeanClass.put("##SWITCHES_CLASS##", bufferSwitch.toString()); + + try(var writer = processor.createSourceFileWrite("firok.spring.mvci.runtime.Current" + type + "Classes")) + { + writer.write(RegexPipeline.pipelineAll(template, paramBeanClass)); + } + } +} diff --git a/src/main/java/firok/spring/mvci/runtime/CurrentBeanClasses.java b/src/main/java/firok/spring/mvci/runtime/CurrentBeanClasses.java new file mode 100644 index 0000000..73011b7 --- /dev/null +++ b/src/main/java/firok/spring/mvci/runtime/CurrentBeanClasses.java @@ -0,0 +1,38 @@ +package firok.spring.mvci.runtime; + +/** + * @since 17.2.0 + */ +@SuppressWarnings("all") +public final class CurrentBeanClasses +{ + private CurrentBeanClasses() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + + + /** + *

当前项目中所有标注了 {@code @MVCIntrospective} 的实体类 Class 对象

+ *

An array contains Class instances of all bean-class marked with {@code @MVCIntrospective}

+ * + * @implNote 此字段会在编译期填充内容 this field will be filled during compiling phase + */ + public static final Class[] CLASSES = new Class[] {}; + + + + /** + *

如果不希望使用 {@code Class.forName(xxx)} 获取实体类 Class 对象, 可以使用此方法.

+ *

This method is available for the case to get Class instances without {@code Class.forName(xxx)}

+ * + * @param fullQualifiedBeanName 类完整限定名 + * @return 类 Class 对象 + * @implNote 此方法会在编译期填充内容 this method will be filled during compiling phase + */ + public static Class getByFullQualifiedBeanName(String fullQualifiedBeanName) + { + return switch (fullQualifiedBeanName) + { + default -> null; + }; + } +} diff --git a/src/main/java/firok/spring/mvci/runtime/CurrentBeanNames.java b/src/main/java/firok/spring/mvci/runtime/CurrentBeanNames.java new file mode 100644 index 0000000..b931a28 --- /dev/null +++ b/src/main/java/firok/spring/mvci/runtime/CurrentBeanNames.java @@ -0,0 +1,20 @@ +package firok.spring.mvci.runtime; + +/** + * @since 17.2.0 + */ +@SuppressWarnings("all") +public final class CurrentBeanNames +{ + private CurrentBeanNames() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + + + /** + *

当前项目中由 MVCI 读取到的所有实体类完整限定名

+ *

An array contains full qualified names of all bean-class marked with {@code @MVCIntrospective}

+ * + * @implNote 此字段会在编译期填充内容 this field will be filled during compiling phase + */ + public static final String[] NAMES = new String[] {}; +} diff --git a/src/main/java/firok/spring/mvci/runtime/CurrentControllerClasses.java b/src/main/java/firok/spring/mvci/runtime/CurrentControllerClasses.java new file mode 100644 index 0000000..d758030 --- /dev/null +++ b/src/main/java/firok/spring/mvci/runtime/CurrentControllerClasses.java @@ -0,0 +1,38 @@ +package firok.spring.mvci.runtime; + +/** + * @since 17.2.0 + */ +@SuppressWarnings("all") +public final class CurrentControllerClasses +{ + private CurrentControllerClasses() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + + + /** + *

当前项目中所有由 MVCI 生成的 Controller 类对象

+ *

An array contains Class instances of all controller-class generated by MVCI

+ * + * @implNote 此字段会在编译期填充内容 this field will be filled during compiling phase + */ + public static final Class[] CLASSES = new Class[] {}; + + + + /** + *

如果不希望使用 {@code Class.forName(xxx)} 获取实体类 Class 对象, 可以使用此方法.

+ *

This method is available for the case to get Class instances without {@code Class.forName(xxx)}

+ * + * @param fullQualifiedBeanName 类完整限定名 + * @return 类 Class 对象 + * @implNote 此方法会在编译期填充内容 this method will be filled during compiling phase + */ + public static Class getByFullQualifiedBeanName(String fullQualifiedBeanName) + { + return switch (fullQualifiedBeanName) + { + default -> null; + }; + } +} diff --git a/src/main/java/firok/spring/mvci/runtime/CurrentControllerNames.java b/src/main/java/firok/spring/mvci/runtime/CurrentControllerNames.java new file mode 100644 index 0000000..92d9a31 --- /dev/null +++ b/src/main/java/firok/spring/mvci/runtime/CurrentControllerNames.java @@ -0,0 +1,38 @@ +package firok.spring.mvci.runtime; + +/** + * @since 17.2.0 + */ +@SuppressWarnings("all") +public final class CurrentControllerNames +{ + private CurrentControllerNames() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + + + /** + *

当前项目中由 MVCI 生成的所有实体类 Controller 完整限定名

+ *

An array contains full qualified names of all controller-class generated by MVCI

+ * + * @implNote 此字段会在编译期填充内容 this field will be filled during compiling phase + */ + public static final String[] NAMES = new String[] {}; + + + + /** + *

从类完整限定名获取对应 Controller 的完整限定名

+ *

To get full qualified name of controller-class by full qualified name of bean-class

+ * + * @param fullQualifiedBeanName 类完整限定名 + * @return Controller 完整限定名 + * @implNote 此方法会在编译期填充内容 this method will be filled during compiling phase + */ + public static String getByFullQualifiedBeanName(String fullQualifiedBeanName) + { + return switch (fullQualifiedBeanName) + { + default -> null; + }; + } +} diff --git a/src/main/java/firok/spring/mvci/runtime/CurrentMapperClasses.java b/src/main/java/firok/spring/mvci/runtime/CurrentMapperClasses.java new file mode 100644 index 0000000..ba05e35 --- /dev/null +++ b/src/main/java/firok/spring/mvci/runtime/CurrentMapperClasses.java @@ -0,0 +1,38 @@ +package firok.spring.mvci.runtime; + +/** + * @since 17.2.0 + */ +@SuppressWarnings("all") +public final class CurrentMapperClasses +{ + private CurrentMapperClasses() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + + + /** + *

当前项目中所有由 MVCI 生成的 Service 类对象

+ *

An array contains Class instances of all service-class generated by MVCI

+ * + * @implNote 此字段会在编译期填充内容 this field will be filled during compiling phase + */ + public static final Class[] CLASSES = new Class[] {}; + + + + /** + *

如果不希望使用 {@code Class.forName(xxx)} 获取实体类 Class 对象, 可以使用此方法.

+ *

This method is available for the case to get Class instances without {@code Class.forName(xxx)}

+ * + * @param fullQualifiedBeanName 类完整限定名 + * @return 类 Class 对象 + * @implNote 此方法会在编译期填充内容 this method will be filled during compiling phase + */ + public static Class getByFullQualifiedBeanName(String fullQualifiedBeanName) + { + return switch (fullQualifiedBeanName) + { + default -> null; + }; + } +} diff --git a/src/main/java/firok/spring/mvci/runtime/CurrentMapperNames.java b/src/main/java/firok/spring/mvci/runtime/CurrentMapperNames.java new file mode 100644 index 0000000..93d2d59 --- /dev/null +++ b/src/main/java/firok/spring/mvci/runtime/CurrentMapperNames.java @@ -0,0 +1,38 @@ +package firok.spring.mvci.runtime; + +/** + * @since 17.2.0 + */ +@SuppressWarnings("all") +public final class CurrentMapperNames +{ + private CurrentMapperNames() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + + + /** + *

当前项目中由 MVCI 生成的所有实体类 Mapper 完整限定名

+ *

An array contains full qualified names of all mapper-class generated by MVCI

+ * + * @implNote 此字段会在编译期填充内容 this field will be filled during compiling phase + */ + public static final String[] NAMES = new String[] {}; + + + + /** + *

从类完整限定名获取对应 Mapper 的完整限定名

+ *

To get full qualified name of mapper-class by full qualified name of bean-class

+ * + * @param fullQualifiedBeanName 类完整限定名 + * @return Mapper 完整限定名 + * @implNote 此方法会在编译期填充内容 this method will be filled during compiling phase + */ + public static String getByFullQualifiedBeanName(String fullQualifiedBeanName) + { + return switch (fullQualifiedBeanName) + { + default -> null; + }; + } +} diff --git a/src/main/java/firok/spring/mvci/runtime/CurrentServiceClasses.java b/src/main/java/firok/spring/mvci/runtime/CurrentServiceClasses.java new file mode 100644 index 0000000..9f26017 --- /dev/null +++ b/src/main/java/firok/spring/mvci/runtime/CurrentServiceClasses.java @@ -0,0 +1,38 @@ +package firok.spring.mvci.runtime; + +/** + * @since 17.2.0 + */ +@SuppressWarnings("all") +public final class CurrentServiceClasses +{ + private CurrentServiceClasses() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + + + /** + *

当前项目中所有由 MVCI 生成的 Service 类对象

+ *

An array contains Class instances of all service-class generated by MVCI

+ * + * @implNote 此字段会在编译期填充内容 this field will be filled during compiling phase + */ + public static final Class[] CLASSES = new Class[] {}; + + + + /** + *

如果不希望使用 {@code Class.forName(xxx)} 获取实体类 Class 对象, 可以使用此方法.

+ *

This method is available for the case to get Class instances without {@code Class.forName(xxx)}

+ * + * @param fullQualifiedBeanName 类完整限定名 + * @return 类 Class 对象 + * @implNote 此方法会在编译期填充内容 this method will be filled during compiling phase + */ + public static Class getByFullQualifiedBeanName(String fullQualifiedBeanName) + { + return switch (fullQualifiedBeanName) + { + default -> null; + }; + } +} diff --git a/src/main/java/firok/spring/mvci/runtime/CurrentServiceImplClasses.java b/src/main/java/firok/spring/mvci/runtime/CurrentServiceImplClasses.java new file mode 100644 index 0000000..d548212 --- /dev/null +++ b/src/main/java/firok/spring/mvci/runtime/CurrentServiceImplClasses.java @@ -0,0 +1,38 @@ +package firok.spring.mvci.runtime; + +/** + * @since 17.2.0 + */ +@SuppressWarnings("all") +public final class CurrentServiceImplClasses +{ + private CurrentServiceImplClasses() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + + + /** + *

当前项目中所有由 MVCI 生成的 Service Impl 类对象

+ *

An array contains Class instances of all service-impl-class generated by MVCI

+ * + * @implNote 此字段会在编译期填充内容 this field will be filled during compiling phase + */ + public static final Class[] CLASSES = new Class[] {}; + + + + /** + *

如果不希望使用 {@code Class.forName(xxx)} 获取实体类 Class 对象, 可以使用此方法.

+ *

This method is available for the case to get Class instances without {@code Class.forName(xxx)}

+ * + * @param fullQualifiedBeanName 类完整限定名 + * @return 类 Class 对象 + * @implNote 此方法会在编译期填充内容 this method will be filled during compiling phase + */ + public static Class getByFullQualifiedBeanName(String fullQualifiedBeanName) + { + return switch (fullQualifiedBeanName) + { + default -> null; + }; + } +} diff --git a/src/main/java/firok/spring/mvci/runtime/CurrentServiceImplNames.java b/src/main/java/firok/spring/mvci/runtime/CurrentServiceImplNames.java new file mode 100644 index 0000000..0e75059 --- /dev/null +++ b/src/main/java/firok/spring/mvci/runtime/CurrentServiceImplNames.java @@ -0,0 +1,38 @@ +package firok.spring.mvci.runtime; + +/** + * @since 17.2.0 + */ +@SuppressWarnings("all") +public final class CurrentServiceImplNames +{ + private CurrentServiceImplNames() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + + + /** + *

当前项目中由 MVCI 生成的所有实体类 Service Impl 完整限定名

+ *

An array contains full qualified names of all service-impl-class generated by MVCI

+ * + * @implNote 此字段会在编译期填充内容 this field will be filled during compiling phase + */ + public static final String[] NAMES = new String[] {}; + + + + /** + *

从类完整限定名获取对应 Service Impl 的完整限定名

+ *

To get full qualified name of service-impl-class by full qualified name of bean-class

+ * + * @param fullQualifiedBeanName 类完整限定名 + * @return Service Impl 完整限定名 + * @implNote 此方法会在编译期填充内容 this method will be filled during compiling phase + */ + public static String getByFullQualifiedBeanName(String fullQualifiedBeanName) + { + return switch (fullQualifiedBeanName) + { + default -> null; + }; + } +} diff --git a/src/main/java/firok/spring/mvci/runtime/CurrentServiceNames.java b/src/main/java/firok/spring/mvci/runtime/CurrentServiceNames.java new file mode 100644 index 0000000..b1de3c7 --- /dev/null +++ b/src/main/java/firok/spring/mvci/runtime/CurrentServiceNames.java @@ -0,0 +1,38 @@ +package firok.spring.mvci.runtime; + +/** + * @since 17.2.0 + */ +@SuppressWarnings("all") +public final class CurrentServiceNames +{ + private CurrentServiceNames() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + + + /** + *

当前项目中由 MVCI 生成的所有实体类 Service 完整限定名

+ *

An array contains full qualified names of all service-class generated by MVCI

+ * + * @implNote 此字段会在编译期填充内容 this field will be filled during compiling phase + */ + public static final String[] NAMES = new String[] {}; + + + + /** + *

从类完整限定名获取对应 Service 的完整限定名

+ *

To get full qualified name of service-class by full qualified name of bean-class

+ * + * @param fullQualifiedBeanName 类完整限定名 + * @return Service 完整限定名 + * @implNote 此方法会在编译期填充内容 this method will be filled during compiling phase + */ + public static String getByFullQualifiedBeanName(String fullQualifiedBeanName) + { + return switch (fullQualifiedBeanName) + { + default -> null; + }; + } +} diff --git a/src/main/java/firok/spring/mvci/runtime/package-info.java b/src/main/java/firok/spring/mvci/runtime/package-info.java new file mode 100644 index 0000000..2603fea --- /dev/null +++ b/src/main/java/firok/spring/mvci/runtime/package-info.java @@ -0,0 +1,6 @@ +/** + * 这个包下包含数个类, 记录了 MVCI 进行各种操作时的信息 + * + * @since 17.2.0 + */ +package firok.spring.mvci.runtime; \ No newline at end of file diff --git a/src/main/resources/current_classes.txt b/src/main/resources/current_classes.txt new file mode 100644 index 0000000..54a8663 --- /dev/null +++ b/src/main/resources/current_classes.txt @@ -0,0 +1,17 @@ +package firok.spring.mvci.runtime; + +public final class Current##TYPE_CLASS##Classes +{ + private Current##TYPE_CLASS##Classes() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + public static final Class[] CLASSES = new Class[] { ##CLASSES_CLASS## + }; + + public static Class getByFullQualifiedBeanName(String fullQualifiedBeanName) + { + return switch (fullQualifiedBeanName) + { ##SWITCHES_CLASS## + default -> null; + }; + } +} diff --git a/src/main/resources/current_names_with_mapping.txt b/src/main/resources/current_names_with_mapping.txt new file mode 100644 index 0000000..081084f --- /dev/null +++ b/src/main/resources/current_names_with_mapping.txt @@ -0,0 +1,17 @@ +package firok.spring.mvci.runtime; + +public final class Current##TYPE_NAME##Names +{ + private Current##TYPE_NAME##Names() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + public static final String[] NAMES = new String[] { ##NAMES_NAME## + }; + + public static String getByFullQualifiedBeanName(String fullQualifiedBeanName) + { + return switch (fullQualifiedBeanName) + { ##MAPPINGS_NAME## + default -> null; + }; + } +} diff --git a/src/main/resources/current_names_without_mapping.txt b/src/main/resources/current_names_without_mapping.txt new file mode 100644 index 0000000..53df2b5 --- /dev/null +++ b/src/main/resources/current_names_without_mapping.txt @@ -0,0 +1,9 @@ +package firok.spring.mvci.runtime; + +public final class Current##TYPE_NAME##Names +{ + private Current##TYPE_NAME##Names() throws InstantiationException { throw new InstantiationException("不允许初始化"); } + + public static final String[] NAMES = new String[] { ##NAMES_NAME## + }; +}