Skip to content

Commit e8a2ca0

Browse files
committed
add v4 entities
Signed-off-by: Shijie Sheng <[email protected]>
1 parent 729c884 commit e8a2ca0

File tree

278 files changed

+4473
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

278 files changed

+4473
-0
lines changed
Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"strings"
8+
"sync"
9+
"text/template"
10+
11+
"go.uber.org/thriftrw/ast"
12+
"go.uber.org/thriftrw/idl"
13+
)
14+
15+
const (
16+
baseExceptionClassName = "CadenceError"
17+
)
18+
19+
type Field struct {
20+
Name string
21+
Type string
22+
}
23+
24+
type TemplateEntity struct {
25+
PackageName string
26+
ClassName string
27+
Fields []Field
28+
AdditionalImports []string
29+
}
30+
31+
type TemplateEnum struct {
32+
PackageName string
33+
ClassName string
34+
Fields []string
35+
}
36+
37+
type TemplateException struct {
38+
PackageName string
39+
ClassName string
40+
Fields []Field
41+
BaseExceptionClassName string
42+
}
43+
44+
type TemplateBaseException struct {
45+
PackageName string
46+
ClassName string
47+
}
48+
49+
type Generator struct {
50+
tmplStruct *template.Template
51+
tmplEnum *template.Template
52+
tmplException *template.Template
53+
tmplBaseException *template.Template
54+
log *log.Logger
55+
}
56+
57+
func NewGenerator() *Generator {
58+
return &Generator{
59+
tmplStruct: template.Must(template.ParseFiles("./template/java_struct.tmpl")),
60+
tmplEnum: template.Must(template.ParseFiles("./template/java_enum.tmpl")),
61+
tmplException: template.Must(template.ParseFiles("./template/java_exception.tmpl")),
62+
tmplBaseException: template.Must(template.ParseFiles("./template/java_base_exception.tmpl")),
63+
log: log.New(os.Stdout, "", log.LstdFlags),
64+
}
65+
}
66+
67+
func (g *Generator) Generate(input string, outputDir string, packageNameOverride string, additionalImports ...string) error {
68+
config := &idl.Config{}
69+
70+
content, err := os.ReadFile(input)
71+
if err != nil {
72+
return fmt.Errorf("failed to read file: %w", err)
73+
}
74+
75+
program, err := config.Parse(content)
76+
if err != nil {
77+
return fmt.Errorf("failed to parse file: %w", err)
78+
}
79+
80+
packageName := packageNameOverride
81+
if packageName == "" {
82+
packageName, err = getPackageName(program)
83+
if err != nil {
84+
return fmt.Errorf("failed to get package name: %w", err)
85+
}
86+
}
87+
outputDir = fmt.Sprintf("%s/%s", outputDir, strings.ReplaceAll(packageName, ".", "/"))
88+
89+
err = os.MkdirAll(outputDir, 0755)
90+
if err != nil {
91+
return fmt.Errorf("failed to create output directory: %w", err)
92+
}
93+
94+
ast.Walk(ast.VisitorFunc(func(w ast.Walker, n ast.Node) {
95+
var err error
96+
switch v:=n.(type) {
97+
case *ast.Struct:
98+
switch v.Type {
99+
case ast.ExceptionType:
100+
err = g.generateException(v, outputDir, packageName)
101+
case ast.StructType:
102+
err = g.generateStruct(v, outputDir, packageName, additionalImports)
103+
}
104+
case *ast.Enum:
105+
err = g.generateEnum(v, outputDir, packageName)
106+
}
107+
if err != nil {
108+
g.log.Fatalf("failed to generate: %v", err)
109+
}
110+
}), program)
111+
return nil
112+
}
113+
114+
func (g *Generator) generateStruct(v *ast.Struct, outputDir string, packageName string, additionalImports []string) error {
115+
fields := make([]Field, 0)
116+
for _, field := range v.Fields {
117+
typeStr, err := typeMapper(field.Type, true)
118+
if err != nil {
119+
return fmt.Errorf("failed to map field type: %w", err)
120+
}
121+
122+
fields = append(fields, Field{
123+
Name: field.Name,
124+
Type: typeStr,
125+
})
126+
}
127+
128+
data := TemplateEntity{
129+
PackageName: packageName,
130+
ClassName: v.Name,
131+
Fields: fields,
132+
AdditionalImports: additionalImports,
133+
}
134+
135+
outputFile := fmt.Sprintf("%s/%s.java", outputDir, v.Name)
136+
f, err := os.Create(outputFile)
137+
if err != nil {
138+
return fmt.Errorf("failed to create file: %w", err)
139+
}
140+
defer f.Close()
141+
142+
if err := g.tmplStruct.Execute(f, data); err != nil {
143+
144+
return fmt.Errorf("failed to execute template: %w", err)
145+
}
146+
147+
return nil
148+
}
149+
150+
func (g *Generator) generateException(v *ast.Struct, outputDir string, packageName string) error {
151+
var once sync.Once
152+
once.Do(func(){
153+
err := g.generateBaseException(baseExceptionClassName, outputDir, packageName)
154+
if err != nil {
155+
g.log.Fatalf("failed to generate base exception: %v", err)
156+
}
157+
})
158+
159+
fields := make([]Field, 0)
160+
for _, field := range v.Fields {
161+
if field.Name == "message" { // skip on message field, it is already in the base exception
162+
continue
163+
}
164+
typeStr, err := typeMapper(field.Type, true)
165+
if err != nil {
166+
return fmt.Errorf("failed to map field type: %w", err)
167+
}
168+
fields = append(fields, Field{
169+
Name: field.Name,
170+
Type: typeStr,
171+
})
172+
}
173+
174+
data := TemplateException{
175+
PackageName: packageName,
176+
ClassName: v.Name,
177+
Fields: fields,
178+
BaseExceptionClassName: baseExceptionClassName,
179+
}
180+
181+
outputFile := fmt.Sprintf("%s/%s.java", outputDir, v.Name)
182+
f, err := os.Create(outputFile)
183+
if err != nil {
184+
return fmt.Errorf("failed to create file: %w", err)
185+
}
186+
defer f.Close()
187+
188+
if err := g.tmplException.Execute(f, data); err != nil {
189+
return fmt.Errorf("failed to execute template: %w", err)
190+
}
191+
return nil
192+
}
193+
194+
func (g *Generator) generateBaseException(className string, outputDir string, packageName string) error {
195+
data := TemplateBaseException{
196+
PackageName: packageName,
197+
ClassName: className,
198+
}
199+
200+
outputFile := fmt.Sprintf("%s/%s.java", outputDir, className)
201+
f, err := os.Create(outputFile)
202+
if err != nil {
203+
return fmt.Errorf("failed to create file: %w", err)
204+
}
205+
defer f.Close()
206+
207+
if err := g.tmplBaseException.Execute(f, data); err != nil {
208+
return fmt.Errorf("failed to execute template: %w", err)
209+
}
210+
return nil
211+
}
212+
213+
func (g *Generator) generateEnum(v *ast.Enum, outputDir string, packageName string) error {
214+
data := TemplateEnum{
215+
PackageName: packageName,
216+
ClassName: v.Name,
217+
}
218+
for _, item := range v.Items {
219+
data.Fields = append(data.Fields, item.Name)
220+
}
221+
222+
outputFile := fmt.Sprintf("%s/%s.java", outputDir, v.Name)
223+
f, err := os.Create(outputFile)
224+
if err != nil {
225+
return fmt.Errorf("failed to create file: %w", err)
226+
}
227+
defer f.Close()
228+
229+
if err := g.tmplEnum.Execute(f, data); err != nil {
230+
return fmt.Errorf("failed to execute template: %w", err)
231+
}
232+
return nil
233+
}
234+
235+
func getPackageName(program *ast.Program) (string, error) {
236+
for _, header := range program.Headers {
237+
if header, ok := header.(*ast.Namespace); ok && header.Scope == "java" {
238+
return header.Name, nil
239+
}
240+
}
241+
return "", fmt.Errorf("cannot find package name in the thrift file")
242+
}
243+
244+
func typeMapper(t ast.Type, usePrimitive bool) (string, error) {
245+
switch tt :=t.(type) {
246+
case ast.BaseType:
247+
return baseTypeMapper(tt, usePrimitive)
248+
case ast.MapType:
249+
keyType, err := typeMapper(tt.KeyType, false)
250+
if err != nil {
251+
return "", fmt.Errorf("failed to map key type: %w", err)
252+
}
253+
valueType, err := typeMapper(tt.ValueType, false)
254+
if err != nil {
255+
return "", fmt.Errorf("failed to map value type: %w", err)
256+
}
257+
return "Map<" + keyType + ", " + valueType + ">", nil
258+
case ast.ListType:
259+
valueType, err := typeMapper(tt.ValueType, false)
260+
if err != nil {
261+
return "", fmt.Errorf("failed to map value type: %w", err)
262+
}
263+
return "List<" + valueType + ">", nil
264+
case ast.SetType:
265+
valueType, err := typeMapper(tt.ValueType, false)
266+
if err != nil {
267+
return "", fmt.Errorf("failed to map value type: %w", err)
268+
}
269+
return "Set<" + valueType + ">", nil
270+
case ast.TypeReference:
271+
return trimReference(tt.Name), nil
272+
default:
273+
return "", fmt.Errorf("do not support type: %v", tt)
274+
}
275+
}
276+
277+
// trim the reference from the name, e.g. com.uber.cadence.shared.WorkflowExecution -> WorkflowExecution
278+
func trimReference(name string) string {
279+
return strings.Split(name, ".")[len(strings.Split(name, "."))-1]
280+
}
281+
282+
func baseTypeMapper(t ast.BaseType, usePrimitive bool) (string, error) {
283+
switch t.ID {
284+
case ast.BoolTypeID:
285+
if usePrimitive {
286+
return "boolean", nil
287+
}
288+
return "Boolean", nil
289+
case ast.I8TypeID, ast.I16TypeID, ast.I32TypeID:
290+
if usePrimitive {
291+
return "int", nil
292+
}
293+
return "Integer", nil
294+
case ast.I64TypeID:
295+
if usePrimitive {
296+
return "long", nil
297+
}
298+
return "Long", nil
299+
case ast.DoubleTypeID:
300+
if usePrimitive {
301+
return "double", nil
302+
}
303+
return "Double", nil
304+
case ast.StringTypeID:
305+
return "String", nil
306+
case ast.BinaryTypeID:
307+
return "byte[]", nil
308+
default:
309+
return "", fmt.Errorf("unknown base type: %v", t.ID)
310+
}
311+
}

scripts/v4_entity_generator/go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module github.com/uber/cadence-idl/java/generator
2+
3+
go 1.18
4+
5+
require go.uber.org/thriftrw v1.32.0

scripts/v4_entity_generator/go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
3+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
4+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
5+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6+
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
7+
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
8+
go.uber.org/thriftrw v1.32.0 h1:/d9SS3H0V0lwm5cVcPI29V7EGDWHQQARGLYKeyhzRAM=
9+
go.uber.org/thriftrw v1.32.0/go.mod h1:MTXuf4RAB2SbjKgyvt7PF2SnuLJ8IYajpg8yBo3rEUI=
10+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package main
2+
3+
import "fmt"
4+
5+
func main() {
6+
if err := NewGenerator().Generate("../../src/main/idls/thrift/shared.thrift", "../../src/gen/java", "com.uber.cadence"); err != nil {
7+
panic(fmt.Sprintf("failed to generate: %v", err))
8+
}
9+
if err := NewGenerator().Generate("../../src/main/idls/thrift/shadower.thrift", "../../src/gen/java", "com.uber.cadence.shadower", "com.uber.cadence.*"); err != nil {
10+
panic(fmt.Sprintf("failed to generate: %v", err))
11+
}
12+
}

scripts/v4_entity_generator/run.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#! /bin/bash
2+
3+
# This script is used to generate the java entities from the thrift files. We will eventually remove this script and maintain entities without using thrift.
4+
ROOT_DIR=$(git rev-parse --show-toplevel)
5+
cd $ROOT_DIR/scripts/v4_entity_generator
6+
7+
go run main.go generator.go
8+
9+
cd $ROOT_DIR
10+
./gradlew googleJavaFormat
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package {{.PackageName}};
2+
3+
public class {{.ClassName}} extends RuntimeException {
4+
public {{.ClassName}}() {
5+
super();
6+
}
7+
8+
public {{.ClassName}}(String message) {
9+
super(message);
10+
}
11+
12+
public {{.ClassName}}(String message, Throwable cause) {
13+
super(message, cause);
14+
}
15+
16+
public {{.ClassName}}(Throwable cause) {
17+
super(cause);
18+
}
19+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package {{.PackageName}};
2+
3+
public enum {{.ClassName}} {
4+
{{- range .Fields}}
5+
{{.}},
6+
{{- end}}
7+
}

0 commit comments

Comments
 (0)