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.16sourceRoot: templatesdataRoot: datadata: {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