maven fmpp+javacc 集成使用简单说明
dremio 以及apache calcite 使用到fmpp + javacc 进行代码生成处理,以下是一个简单的集成测试
fmpp 的作用
fmpp 实际上是包装了freemarker ,提供了cli 以及java api 可以方便的进行模版处理,目前apache calcite 就基于了fmpp 进行sql 解析的代码生成
实际上fmpp 是一个很不错而且强大的模版处理工具,以下是一个简单的试用(基于前边包装的fmpp maven 扩展)
fmpp 支持基于配置对于生成模版的控制,我们可以以工程化的模式进行模版的管理以及数据处理
javacc 与fmpp 的集成
实际上就是fmpp 插件与javacc 插件集成,同时控制好不同插件的执行生命周期,一般推荐代码模版放到与src/main 同级的位置,最好别放到resources
下边(编译会打包,而且很多是否我们并不想暴露)
参考使用
- 项目结构
├── pom.xml
└── src
└── main
├── codegen // 模版代码
│ ├── config.fmpp
│ ├── data
│ │ ├── app.json
│ │ └── style.tdd
│ ├── includes
│ │ ├── footer.html
│ │ ├── func
│ │ │ └── agg.ftl
│ │ └── macros
│ │ └── login.ftl
│ └── templates
│ ├── app.jj
│ └── index.html
├── java
└── resources
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dalong</groupId>
<artifactId>javacc-app</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>github</id>
<url>https://maven.pkg.github.com/rongfengliang/fmpp-maven-plugin</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
# initialize 阶段拷贝文件到构建位置的特定目录,方便fmpp 以及javacc 使用
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>copy-fmpp-resources</id>
<phase>initialize</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/codegen</outputDirectory>
<resources>
<resource>
<directory>src/main/codegen</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
# 基于dremio fmpp 扩展独立的fmpp 插件,基于fmpp 进行配置生成
<groupId>com.rongfengliang</groupId>
<artifactId>fmpp-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>generate-fmpp-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<config>${project.build.directory}/codegen/config.fmpp</config>
<output>${project.build.directory}/generated-sources/fmpp</output>
<templates>${project.build.directory}/codegen/templates</templates>
</configuration>
</execution>
</executions>
</plugin>
# 使用javacc 扩展进行代码生成
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>javacc-maven-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<id>javacc</id>
<goals>
<goal>javacc</goal>
</goals>
<configuration>
<sourceDirectory>${project.build.directory}/generated-sources/</sourceDirectory>
<includes>
<include>**/app.jj</include>
</includes>
<lookAhead>2</lookAhead>
<isStatic>false</isStatic>
<outputDirectory>${project.build.directory}/generated-sources/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
- fmpp 项目代码说明
config.fmpp 属于通用配置,编译进行的通用设置
recommendedDefaults: 0.9.16
sourceRoot: templates
dataRoot: data
data: {
app: tdd(style.tdd),
parser:json(parser.json)
myappinfo: {
version: "v1",
author: "dalong"
},
items:json(app.json)
}
freemarkerLinks: {
inc: includes/
}
app.jj 一个特别简单的基于javacc 定义的解析
PARSER_BEGIN(${parser.parserName})
package ${parser.packageName};
/** Simple brace matcher. */
public class ${parser.parserName} {
/** Main entry point. */
public static void main(String args[]) throws ParseException {
MyApp parser = new MyApp(System.in);
parser.Input();
}
}
PARSER_END(${parser.parserName})
/** Root production. */
void Input() :
{}
{
MatchedBraces() ("\n"|"\r")* <EOF>
}
/** Brace matching production. */
void MatchedBraces() :
{}
{
"{" [ MatchedBraces() ] "}"
}
数据定义
主要说明 app.jj 依赖的数据项(使用了json dataloader)
{
"parserName":"MyApp",
"packageName":"com.dalongapp"
}
运行
- 命令
mvn clean package
- 效果
说明
很多时候我们需要集成maven-dependency-plugin 对于三方依赖jj 文件的加载,注意应该在maven 的initialize 阶段处理通过unpack copy
依赖到我们的项目中,比如当我们如果需要扩展apache calcite 的时候就需要了(dremio 也是使用了此方法)
参考资料
https://github.com/mojohaus/javacc-maven-plugin
https://www.mojohaus.org/javacc-maven-plugin/plugin-info.html
https://github.com/rongfengliang/fmpp-maven-plugin-learning
https://github.com/rongfengliang/fmpp-maven-plugin
https://maven.apache.org/plugins/maven-dependency-plugin/index.html