Skip to content

Commit e0704d1

Browse files
authored
add v4 entities (#1024)
Signed-off-by: Shijie Sheng <[email protected]> What changed? Add new internal entities that will replace thrift ones. These entities will be used in the next few diffs that removed thrift support. To generate entities, ./scripts/v4_entity_generator/run.sh Why? Thrift entities are not easily replaceable by GRPC ones. One quick approach for deprecation is to generate similar interface internal entities to replace thrift ones. How did you test it? These are generated by script
1 parent 729c884 commit e0704d1

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)