Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
5d716c3
feat(flow): 添加自动布局功能支持流程设计
cjbi Jul 4, 2026
c132831
feat(ci): 添加服务器原生镜像推送工作流
cjbi Jul 4, 2026
2498786
ci(workflow): 添加原生镜像构建工作流并优化服务器镜像构建配置
cjbi Jul 4, 2026
981eeb9
chore(ci): 移除native工作流中的依赖检查
cjbi Jul 4, 2026
920d0e9
chore(ci): 更新本地工作流配置并启用调试模式
cjbi Jul 4, 2026
b647fb2
refactor(flow): 替换 JavaScript 引擎从 GraalVM 到 QuickJS
cjbi Jul 4, 2026
239255a
refactor(flow): 移除请求脚本上下文类
cjbi Jul 4, 2026
2c1321a
chore(test): 清理 JavaScriptUtilTest 类的格式
cjbi Jul 4, 2026
62c88f5
refactor(auth): 优化 API 密钥生成器的运行时初始化
cjbi Jul 4, 2026
f0873cb
chore(native-image): 配置 ApiKeyGenerator 运行时初始化以支持 Native Image 构建
cjbi Jul 4, 2026
cc37b2a
chore(server): 更新服务器配置以支持S3存储和原生镜像构建
cjbi Jul 4, 2026
85a8825
chore(build): 修复原生镜像构建参数中的逗号转义问题
cjbi Jul 4, 2026
cbef0aa
refactor(storage): 使用 Quarkus Amazon S3 扩展替代手动配置
cjbi Jul 4, 2026
12c0b4e
feat(s3): 更新 S3 客户端配置以使用 URL 连接
cjbi Jul 4, 2026
5722758
deps(build): 添加 HikariCP 的可选依赖 metrics-core
cjbi Jul 4, 2026
e463b58
feat(deps): 添加 Metrics 库依赖
cjbi Jul 4, 2026
80a394f
deps(server): 添加 HikariCP 构建时依赖
cjbi Jul 4, 2026
5fc8687
refactor(deps): 调整 HikariCP 相关依赖配置
cjbi Jul 4, 2026
f1b6942
fix(config): 解决 GraalVM native image 中 JDBC 驱动注册问题
cjbi Jul 4, 2026
dd729a4
refactor(database): 优化 JDBC 驱动注册机制以支持 native image
cjbi Jul 4, 2026
fba70dc
refactor(database): 优化原生镜像中的数据库连接配置
cjbi Jul 4, 2026
68069a9
feat(server): 启用HTTP CORS支持
cjbi Jul 4, 2026
aa0a962
refactor(database): 将数据源从 HikariCP 迁移到 Agroal
cjbi Jul 4, 2026
147eddb
chore(native-image): 更新原生镜像可达性元数据并调整测试配置
cjbi Jul 4, 2026
b4b8670
test(flow): 更新服务任务执行器测试以适配 quickjs4j 引擎
cjbi Jul 4, 2026
2df2ec6
feat(native-image): 添加原生镜像反射配置处理器
cjbi Jul 4, 2026
2722523
fix(query): 解决 GraalVM native image 中 lambda 序列化问题
cjbi Jul 4, 2026
d882d4a
chore(config): 更新原生镜像构建配置以支持随机数生成器
cjbi Jul 4, 2026
2d9e438
fix(query): 解决 GraalVM native image 中 lambda 序列化问题
cjbi Jul 4, 2026
cbc03bd
refactor(config): 简化原生镜像构建配置
cjbi Jul 4, 2026
d0dd8e7
chore(native-image): 添加序列化配置以支持原生镜像构建
cjbi Jul 4, 2026
0c34810
feat(native-image): 添加 lambda writeReplace 特性支持
cjbi Jul 4, 2026
63bd3f3
feat(codegen): 生成实体字段引用和过滤表达式支持
cjbi Jul 5, 2026
9679870
refactor(query): 移除Expressions类中的方法引用功能并更新相关查询
cjbi Jul 5, 2026
7ddb37b
refactor(config): 更新原生镜像构建配置
cjbi Jul 5, 2026
32d77e8
fix(native): 修复原生镜像中SPI实现类的构造函数反射问题
cjbi Jul 5, 2026
cd8c793
feat(session): 添加 BuildItem 直接注册支持以兼容 GraalVM 原生镜像
cjbi Jul 5, 2026
2d4de3c
refactor(codegen): 替换Java原生序列化为Jackson JSON序列化
cjbi Jul 5, 2026
23f7f3a
refactor(session): 重构SessionFactory中的BuildItem应用逻辑
cjbi Jul 5, 2026
7013202
fix(session): 修复无数据源时的模型缓存和表创建逻辑
cjbi Jul 5, 2026
bd8d2c5
feat(datasource): 添加数据源注册日志记录和开发测试数据源配置
cjbi Jul 5, 2026
1851725
```
cjbi Jul 5, 2026
d7dbd8c
chore(native-image): 配置 GraalVM 原生镜像构建参数
cjbi Jul 5, 2026
6730adc
refactor(native-image): 优化数据库驱动的原生镜像配置
cjbi Jul 5, 2026
18115bc
feat(query): 添加字段引用支持并修复数据库字段名映射
cjbi Jul 5, 2026
8bf4845
refactor(database): 优化数据库查询中的字段引用方式
cjbi Jul 5, 2026
d4a1e8a
feat(query): 添加字段引用排序功能
cjbi Jul 5, 2026
ac6843e
feat(scheduler): 添加定时任务执行器的原生镜像元数据支持
cjbi Jul 5, 2026
0b0f1f9
config(server): 配置HTTP请求体大小限制
cjbi Jul 5, 2026
51c765c
chore(config): 更新 GraalVM 原生镜像构建配置
cjbi Jul 5, 2026
018c704
refactor(build): 简化Quartz调度器的原生构建配置
cjbi Jul 5, 2026
19aaefc
refactor(auth): 优化 API 密钥生成器的随机数实例管理
cjbi Jul 5, 2026
f60dd59
refactor(scheduler): 迁移至 Quarkus Quartz 扩展实现
cjbi Jul 5, 2026
85b4a02
feat(scheduling): 添加触发器获取锁机制以支持并发安全
cjbi Jul 5, 2026
e034326
fix(exception): 优化业务异常映射器的日志记录
cjbi Jul 5, 2026
363b4d2
build(native-image): 更新原生镜像可达性元数据配置
cjbi Jul 5, 2026
f764f9c
refactor(nativeimage): 重构原生镜像反射配置
cjbi Jul 5, 2026
78c3357
refactor(native-image): 移除不必要的序列化元数据配置
cjbi Jul 5, 2026
0eb1723
fix(deps): 更新 SQLite JDBC 依赖为 Quarkus 扩展
cjbi Jul 5, 2026
31b7caa
refactor(datasource): 替换 Agroal 连接池为 Quarkus Agroal 扩展
cjbi Jul 5, 2026
86236e6
refactor(nativeimage): 优化原生镜像配置中的反射注册
cjbi Jul 5, 2026
bd21919
refactor(nativeimage): 优化 Agroal 连接池反射配置
cjbi Jul 5, 2026
1f80997
refactor(datasource): 更改数据库连接池配置
cjbi Jul 5, 2026
50bb86b
refactor(native-image): 更新序列化配置以移除不必要的类
cjbi Jul 5, 2026
8417c3d
refactor(docs): 将数据库连接池从 HikariCP 替换为 Agroal 并更新 JavaScript 引擎描述
cjbi Jul 5, 2026
30f457e
feat(api): 更新函数调用接口并升级依赖版本
cjbi Jul 5, 2026
05517b8
refactor(engine): 移除未使用的构建项处理功能并优化配置结构
cjbi Jul 5, 2026
151fe32
refactor(deploy): 调整 Docker Compose 配置和服务器启动配置
cjbi Jul 5, 2026
bf12124
config(server): 添加文件日志记录配置并调整数据库和存储忽略规则
cjbi Jul 5, 2026
b60d286
feat(api-keys): 添加 API 密钥前端警告提示
cjbi Jul 5, 2026
77e1bbe
refactor(test): 优化集成测试中的数据源配置
cjbi Jul 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,31 @@ jobs:
-Dquarkus.container-image.username=${{ secrets.DOCKER_USERNAME }} \
-Dquarkus.container-image.password=${{ secrets.DOCKER_PASSWORD }}

push-server-native-image:
name: Push server native docker image
needs: [ engine-test, server-test ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up JDK 25
uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'temurin'
cache: 'maven'
cache-dependency-path: '**/pom.xml'
- name: Build and push server native image
run: |
mvn -B -Dmaven.test.skip=true clean package -Pnative -pl flexmodel-server -am \
-Dquarkus.container-image.build=true \
-Dquarkus.container-image.push=true \
-Dquarkus.container-image.image=cjbi/flexmodel-server-native:latest \
-Dquarkus.container-image.username=${{ secrets.DOCKER_USERNAME }} \
-Dquarkus.container-image.password=${{ secrets.DOCKER_PASSWORD }}

push-functions-runtime-image:
name: Push functions-runtime docker image
needs: [ functions-runtime-test ]
Expand Down
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@ build/
### Project ###

*.db
flexmodel-server/logs/
flexmodel-server/storage/
/logs/
/storage/
/database/
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Flexmodel 旨在为开发者提供一个开源、灵活且高度可定制的后

## 🛠️ 技术栈

- **后端**: Java 25, Quarkus 3, Maven, GraalVM JavaScript, HikariCP.
- **后端**: Java 25, Quarkus 3, Maven, QuickJS, Agroal.
- **前端**: React, TypeScript, Ant Design v6, Tailwind CSS, Vite, @xyflow/react, ECharts, Monaco Editor.
- **云函数**: Deno, Hono.js.
- **协议**: REST API, GraphQL, MCP, WebSocket, SSE.
Expand Down
4 changes: 1 addition & 3 deletions deploy/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
/docker-compose/mysql/data/
/docker-compose/database/
/docker-compose/storage/
.idea
/docker-compose/flexmodel-sever/
7 changes: 7 additions & 0 deletions deploy/docker-compose/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
CONTAINER_NAME_PREFIX=prod

# 运行模式: native (GraalVM 原生镜像) 或 jvm (JVM 模式)
# 切换方式:修改 FLEXMODEL_RUN_MODE 和 FLEXMODEL_SERVER_IMAGE 两行
# native → FLEXMODEL_SERVER_IMAGE=cjbi/flexmodel-server-native:latest
# jvm → FLEXMODEL_SERVER_IMAGE=cjbi/flexmodel-server:latest
FLEXMODEL_RUN_MODE=native
FLEXMODEL_SERVER_IMAGE=cjbi/flexmodel-server-native:latest

# mysql
MYSQL_DATABASE=flexmodel
MYSQL_ROOT_PASSWORD=123456
Expand Down
28 changes: 12 additions & 16 deletions deploy/docker-compose/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,21 @@ services:
- flexmodel
flexmodel-server:
container_name: ${CONTAINER_NAME_PREFIX}-flexmodel-server
image: cjbi/flexmodel-server:latest
image: ${FLEXMODEL_SERVER_IMAGE:-cjbi/flexmodel-server-native:latest}
restart: always
volumes:
- ./storage:/deployments/storage
- ./database:/deployments/database
- ./logs/flexmodel-server:/deployments/logs
- ./flexmodel-server/storage:/deployments/storage
- ./flexmodel-server/database:/deployments/database
- ./flexmodel-server/logs:/deployments/logs
environment:
- |
JAVA_OPTS=
-Dfile.encoding=UTF-8
-Duser.timezone=GMT+8
-Dflexmodel.datasource.db-kind=mysql
-Dflexmodel.datasource.url=jdbc:mysql://mysql:3306/${MYSQL_DATABASE}
-Dflexmodel.datasource.username=root
-Dflexmodel.datasource.password=${MYSQL_ROOT_PASSWORD}
-Dflexmodel.project-url-template=jdbc:mysql://mysql:3306/{{databaseName}}
-Dflexmodel.datasource.dev_test.db-kind=sqlite
-Dflexmodel.datasource.dev_test.url=jdbc:sqlite:file:database/sqlite_dev_test.db
-Dquarkus.rest-client.function-runtime.url=http://flexmodel-functions-runtime:9999
- TZ=GMT+08
- FLEXMODEL_DATASOURCE_DB_KIND=mysql
- FLEXMODEL_DATASOURCE_URL=jdbc:mysql://mysql:3306/${MYSQL_DATABASE}
- FLEXMODEL_DATASOURCE_USERNAME=root
- FLEXMODEL_DATASOURCE_PASSWORD=${MYSQL_ROOT_PASSWORD}
- FLEXMODEL_PROJECT_URL_TEMPLATE=jdbc:mysql://mysql:3306/{{databaseName}}
- QUARKUS_REST_CLIENT_FUNCTION_RUNTIME_URL=http://flexmodel-functions-runtime:9999
- QUARKUS_HTTP_LIMITS_MAX_BODY_SIZE=100M

networks:
- flexmodel
Expand Down
27 changes: 16 additions & 11 deletions flexmodel-engine/docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,14 @@ schemaOps.dropIndex("User", "name_index");
#### JDBC数据源

```java
// 创建JDBC数据源
DataSource dataSource = new HikariDataSource();
((HikariDataSource) dataSource).setJdbcUrl("jdbc:mysql://localhost:3306/test");
((HikariDataSource) dataSource).setUsername("root");
((HikariDataSource) dataSource).setPassword("password");
// 创建JDBC数据源(以 Agroal 连接池为例)
AgroalDataSourceConfigurationSupplier config = new AgroalDataSourceConfigurationSupplier();
AgroalConnectionPoolConfigurationSupplier poolConfig = config.connectionPoolConfiguration();
AgroalConnectionFactoryConfigurationSupplier factoryConfig = poolConfig.connectionFactoryConfiguration();
factoryConfig.jdbcUrl("jdbc:mysql://localhost:3306/test");
factoryConfig.principal(new NamePrincipal("root"));
factoryConfig.credential(new SimplePassword("password"));
DataSource dataSource = AgroalDataSource.from(config);

JdbcDataSourceProvider jdbcProvider = new JdbcDataSourceProvider(dataSource);
```
Expand Down Expand Up @@ -477,12 +480,14 @@ try (Session session = sessionFactory.createSession("mySchema")) {
### 1. 连接池配置

```java
HikariDataSource dataSource = new HikariDataSource();
dataSource.setMaximumPoolSize(20);
dataSource.setMinimumIdle(5);
dataSource.setConnectionTimeout(30000);
dataSource.setIdleTimeout(600000);
dataSource.setMaxLifetime(1800000);
AgroalDataSourceConfigurationSupplier config = new AgroalDataSourceConfigurationSupplier();
AgroalConnectionPoolConfigurationSupplier poolConfig = config.connectionPoolConfiguration();
poolConfig.maxSize(20);
poolConfig.minSize(5);
poolConfig.acquisitionTimeout(Duration.ofSeconds(30));
poolConfig.reapTimeout(Duration.ofMinutes(10));
poolConfig.maxLifetime(Duration.ofMinutes(30));
DataSource dataSource = AgroalDataSource.from(config);
```

### 2. 查询优化
Expand Down
28 changes: 18 additions & 10 deletions flexmodel-engine/docs/flexmodel-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,11 @@ public class SessionConfig {
@Produces
@ApplicationScoped
public SessionFactory sessionFactory() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:sqlite:file::memory:?cache=shared");
AgroalDataSourceConfigurationSupplier config = new AgroalDataSourceConfigurationSupplier();
config.connectionPoolConfiguration()
.connectionFactoryConfiguration()
.jdbcUrl("jdbc:sqlite:file::memory:?cache=shared");
DataSource dataSource = AgroalDataSource.from(config);

return SessionFactory.builder()
.setDefaultDataSourceProvider(new JdbcDataSourceProvider("system", dataSource))
Expand Down Expand Up @@ -471,10 +474,12 @@ public class FullNameCalculator implements FieldCalculator {
### 连接池配置

```java
// 配置连接池
DataSource datasource = new HikariDataSource();
((HikariDataSource) datasource).setMaximumPoolSize(20);
((HikariDataSource) datasource).setMinimumIdle(5);
// 配置连接池(以 Agroal 为例)
AgroalDataSourceConfigurationSupplier config = new AgroalDataSourceConfigurationSupplier();
AgroalConnectionPoolConfigurationSupplier poolConfig = config.connectionPoolConfiguration();
poolConfig.maxSize(20);
poolConfig.minSize(5);
DataSource datasource = AgroalDataSource.from(config);
```

### 缓存机制
Expand Down Expand Up @@ -514,10 +519,13 @@ public class MySQLIntegrationTests extends AbstractSessionTests {

@BeforeAll
public static void beforeAll() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(container.getJdbcUrl());
dataSource.setUsername(container.getUsername());
dataSource.setPassword(container.getPassword());
AgroalDataSourceConfigurationSupplier config = new AgroalDataSourceConfigurationSupplier();
AgroalConnectionFactoryConfigurationSupplier factoryConfig = config.connectionPoolConfiguration()
.connectionFactoryConfiguration();
factoryConfig.jdbcUrl(container.getJdbcUrl());
factoryConfig.principal(new NamePrincipal(container.getUsername()));
factoryConfig.credential(new SimplePassword(container.getPassword()));
DataSource dataSource = AgroalDataSource.from(config);
initSession(new JdbcDataSourceProvider("default", dataSource));
}
}
Expand Down
4 changes: 2 additions & 2 deletions flexmodel-engine/flexmodel-codegen/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<groupId>io.agroal</groupId>
<artifactId>agroal-pool</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static void run(Configuration configuration) {
new EnumGenerator().generate(context, targetDirectory);
new SchemaGenerator().generate(context, targetDirectory);
context.putVariable("buildItems", buildItems);
new BuildItemSPIFileGenerator().generate(context, schema.getBaseDir());
// new BuildItemSPIFileGenerator().generate(context, schema.getBaseDir());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,70 @@
package dev.flexmodel.codegen;

import java.io.*;
import dev.flexmodel.JsonUtils;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
* Object serialization utilities.
* <p>
* Uses Jackson JSON serialization (wrapped in Base64) instead of Java native
* serialization ({@link ObjectOutputStream}/{@link ObjectInputStream}) to avoid
* {@code serialVersionUID} incompatibility between JDK versions. JDK classes
* like {@link java.util.HashMap} and {@link java.util.ArrayList} change their
* {@code serialVersionUID} across releases, which breaks deserialization when
* the codegen JDK differs from the runtime JDK (e.g., in GraalVM native-image).
* </p>
*
* @author cjbi
*/
public class ObjectUtils {

private ObjectUtils() {
}

/**
* Serialize an object to a Base64-encoded JSON string.
* <p>
* The serialized format embeds the class name as the first line, followed by
* the JSON representation. This allows deserialization to reconstruct the
* exact object type without requiring an explicit type parameter.
* </p>
*/
public static String serialize(Object obj) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.flush();
return Base64.getEncoder().encodeToString(baos.toByteArray());
String json = JsonUtils.toJsonString(obj);
String className = obj.getClass().getName();
String combined = className + "\n" + json;
return Base64.getEncoder().encodeToString(combined.getBytes(StandardCharsets.UTF_8));
}

/**
* Deserialize a Base64-encoded JSON string back to an object.
* <p>
* The first line of the decoded data is the fully qualified class name,
* which is used to determine the target type for Jackson deserialization.
* </p>
*
* @param str Base64-encoded serialized data
* @return the deserialized object
* @throws IOException if I/O error occurs
* @throws ClassNotFoundException if the target class cannot be found
*/
public static Object deserialize(String str) throws IOException, ClassNotFoundException {
byte[] data = Base64.getDecoder().decode(str);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
return ois.readObject();
String combined = new String(data, StandardCharsets.UTF_8);
int newlineIdx = combined.indexOf('\n');
if (newlineIdx < 0) {
throw new IOException("Invalid serialized format: missing class name header");
}
String className = combined.substring(0, newlineIdx);
String json = combined.substring(newlineIdx + 1);
@SuppressWarnings("unchecked")
Class<?> clazz = Class.forName(className);
return JsonUtils.parseToObject(json, clazz);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import java.io.PrintWriter;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
* Generates the schema BuildItem Java class.
Expand Down Expand Up @@ -38,6 +40,26 @@ public void write(PrintWriter out, GenerationContext context) {
out.println("import dev.flexmodel.model.EnumDefinition;");
out.println("import dev.flexmodel.model.SchemaObject;");
out.println("import dev.flexmodel.ModelImportBundle;");
out.println("import dev.flexmodel.query.FilterExpression;");
out.println();

// Collect all imports from entity models' own import lists
Set<String> allEntityImports = new LinkedHashSet<>();
for (ModelClass model : modelClassList) {
for (String imp : model.getImports()) {
if (imp != null && !imp.isEmpty() && !imp.startsWith("dev.flexmodel.annotation")) {
allEntityImports.add(imp);
}
}
// Also add the entity class itself (may be needed for relation field references)
if (model.getFullClassName() != null && !model.getFullClassName().startsWith("null.")) {
allEntityImports.add(model.getFullClassName());
}
}
for (String importType : allEntityImports) {
out.println("import " + importType + ";");
}

out.println();
out.println("import java.util.ArrayList;");
out.println("import java.util.List;");
Expand Down Expand Up @@ -74,6 +96,39 @@ public void write(PrintWriter out, GenerationContext context) {
out.println(" }");
out.println();

// === Entity field models (zero-reflection, instance fields) ===
// e.g.: System.project.enabled.eq(true)
// First pass: declare the nested field class for each entity
for (ModelClass model : modelClassList) {
String entityName = model.getShortClassName();
String fieldsClassName = entityName + "Fields";
out.println(" /** Field references for {@link " + entityName + "} */");
out.println(" public static final class " + fieldsClassName + " {");
for (ModelField field : model.getAllFields()) {
String rawType = field.getShortTypeName();
if (rawType == null || rawType.isEmpty()) {
rawType = "Object";
}
String typeStr = boxType(rawType);
String variableName = field.getVariableName();
out.println(" public final FilterExpression<" + typeStr + "> "
+ variableName + " = new FilterExpression<>(\"" + field.getOriginal().getName() + "\");");
}
out.println(" }");
}
out.println();

// Second pass: declare static instances, one per entity
for (ModelClass model : modelClassList) {
String entityName = model.getShortClassName();
String fieldsClassName = entityName + "Fields";
String instanceName = StringUtils.uncapitalize(entityName);
out.println(" /** {@link " + entityName + "} field references */");
out.println(" public static final " + fieldsClassName + " " + instanceName
+ " = new " + fieldsClassName + "();");
}
out.println();

// getData() method
out.println(" @Override");
out.println(" @SuppressWarnings(\"all\")");
Expand Down Expand Up @@ -122,4 +177,22 @@ private void writeDataBody(PrintWriter out, GenerationContext context) throws IO
}
}
}

/**
* Box primitive types for use in generics (e.g. int → Integer).
*/
private static String boxType(String type) {
return switch (type) {
case "int" -> "Integer";
case "long" -> "Long";
case "boolean" -> "Boolean";
case "double" -> "Double";
case "float" -> "Float";
case "short" -> "Short";
case "byte" -> "Byte";
case "char" -> "Character";
default -> type;
};
}

}
Loading
Loading