| // Copyright 2015 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package java |
| |
| import ( |
| "bytes" |
| "log" |
| |
| "v.io/v23/vdl" |
| "v.io/x/ref/lib/vdl/compile" |
| "v.io/x/ref/lib/vdl/vdlutil" |
| ) |
| |
| const structTmpl = header + ` |
| // Source: {{.Source}} |
| package {{.PackagePath}}; |
| |
| /** |
| * type {{.Name}} {{.VdlTypeString}} {{.Doc}} |
| **/ |
| @io.v.v23.vdl.GeneratedFromVdl(name = "{{.VdlTypeName}}") |
| {{ .AccessModifier }} final class {{.Name}} extends io.v.v23.vdl.AbstractVdlStruct { |
| private static final long serialVersionUID = 1L; |
| |
| {{/* Field declarations */}} |
| {{ range $index, $field := .Fields }} |
| @io.v.v23.vdl.GeneratedFromVdl(name = "{{$field.Name}}", index = {{$index}}) |
| private {{$field.Type}} {{$field.LowercaseName}}; |
| {{ end }} |
| |
| public static final io.v.v23.vdl.VdlType VDL_TYPE = |
| io.v.v23.vdl.Types.getVdlTypeFromReflect({{.Name}}.class); |
| |
| {{/* Constructors */}} |
| public {{.Name}}() { |
| super(VDL_TYPE); |
| {{ range $field := .Fields }} |
| this.{{$field.LowercaseName}} = {{$field.ZeroValue}}; |
| {{ end }} |
| } |
| |
| {{ if .FieldsAsArgs }} |
| public {{.Name}}({{ .FieldsAsArgs }}) { |
| super(VDL_TYPE); |
| {{ range $field := .Fields }} |
| this.{{$field.LowercaseName}} = {{$field.LowercaseName}}; |
| {{ end }} |
| } |
| {{ end }} |
| |
| {{/* Getters and setters */}} |
| {{ range $field := .Fields }} |
| {{ $field.AccessModifier }} {{$field.Type}} get{{$field.Name}}() { |
| return this.{{$field.LowercaseName}}; |
| } |
| |
| {{ $field.AccessModifier }} void set{{$field.Name}}({{$field.Type}} {{$field.LowercaseName}}) { |
| this.{{$field.LowercaseName}} = {{$field.LowercaseName}}; |
| } |
| {{ end }} |
| |
| @Override |
| public boolean equals(java.lang.Object obj) { |
| if (this == obj) return true; |
| if (obj == null) return false; |
| if (this.getClass() != obj.getClass()) return false; |
| {{ if gt (len .Fields) 0 }} final {{.Name}} other = ({{.Name}})obj; {{ end }} |
| |
| {{ range $field := .Fields }} |
| {{ if .IsArray }} |
| if (!java.util.Arrays.equals(this.{{$field.LowercaseName}}, other.{{$field.LowercaseName}})) { |
| return false; |
| } |
| {{ else }} |
| {{ if .IsClass }} |
| if (this.{{$field.LowercaseName}} == null) { |
| if (other.{{$field.LowercaseName}} != null) { |
| return false; |
| } |
| } else if (!this.{{$field.LowercaseName}}.equals(other.{{$field.LowercaseName}})) { |
| return false; |
| } |
| {{ else }} |
| if (this.{{$field.LowercaseName}} != other.{{$field.LowercaseName}}) { |
| return false; |
| } |
| {{ end }} {{/* if is class */}} |
| {{ end }} {{/* if is array */}} |
| {{ end }} {{/* range over fields */}} |
| return true; |
| } |
| |
| @Override |
| public int hashCode() { |
| int result = 1; |
| final int prime = 31; |
| {{ range $field := .Fields }} |
| result = prime * result + {{$field.HashcodeComputation}}; |
| {{ end }} |
| return result; |
| } |
| |
| @Override |
| public java.lang.String toString() { |
| String result = "{"; |
| {{ range $index, $field := .Fields }} |
| {{ if gt $index 0 }} |
| result += ", "; |
| {{ end }} |
| {{ if .IsArray }} |
| result += "{{$field.LowercaseName}}:" + java.util.Arrays.toString({{$field.LowercaseName}}); |
| {{ else }} |
| result += "{{$field.LowercaseName}}:" + {{$field.LowercaseName}}; |
| {{ end}} {{/* if is array */}} |
| {{ end }} {{/* range over fields */}} |
| return result + "}"; |
| } |
| }` |
| |
| type structDefinitionField struct { |
| AccessModifier string |
| Class string |
| HashcodeComputation string |
| IsClass bool |
| IsArray bool |
| LowercaseName string |
| Name string |
| Type string |
| ZeroValue string |
| } |
| |
| func javaFieldArgStr(structType *vdl.Type, env *compile.Env) string { |
| var buf bytes.Buffer |
| for i := 0; i < structType.NumField(); i++ { |
| if i > 0 { |
| buf.WriteString(", ") |
| } |
| fld := structType.Field(i) |
| buf.WriteString("final ") |
| buf.WriteString(javaType(fld.Type, false, env)) |
| buf.WriteString(" ") |
| buf.WriteString(vdlutil.FirstRuneToLower(fld.Name)) |
| } |
| return buf.String() |
| } |
| |
| // genJavaStructFile generates the Java class file for the provided user-defined type. |
| func genJavaStructFile(tdef *compile.TypeDef, env *compile.Env) JavaFileInfo { |
| fields := make([]structDefinitionField, tdef.Type.NumField()) |
| for i := 0; i < tdef.Type.NumField(); i++ { |
| fld := tdef.Type.Field(i) |
| fields[i] = structDefinitionField{ |
| AccessModifier: accessModifierForName(fld.Name), |
| Class: javaType(fld.Type, true, env), |
| HashcodeComputation: javaHashCode(vdlutil.FirstRuneToLower(fld.Name), fld.Type, env), |
| IsClass: isClass(fld.Type, env), |
| IsArray: isJavaNativeArray(fld.Type, env), |
| LowercaseName: vdlutil.FirstRuneToLower(fld.Name), |
| Name: fld.Name, |
| Type: javaType(fld.Type, false, env), |
| ZeroValue: javaZeroValue(fld.Type, env), |
| } |
| } |
| |
| javaTypeName := vdlutil.FirstRuneToUpper(tdef.Name) |
| data := struct { |
| FileDoc string |
| AccessModifier string |
| Doc string |
| Fields []structDefinitionField |
| FieldsAsArgs string |
| Name string |
| PackagePath string |
| Source string |
| VdlTypeName string |
| VdlTypeString string |
| }{ |
| FileDoc: tdef.File.Package.FileDoc, |
| AccessModifier: accessModifierForName(tdef.Name), |
| Doc: javaDocInComment(tdef.Doc), |
| Fields: fields, |
| FieldsAsArgs: javaFieldArgStr(tdef.Type, env), |
| Name: javaTypeName, |
| PackagePath: javaPath(javaGenPkgPath(tdef.File.Package.GenPath)), |
| Source: tdef.File.BaseName, |
| VdlTypeName: tdef.Type.Name(), |
| VdlTypeString: tdef.Type.String(), |
| } |
| var buf bytes.Buffer |
| err := parseTmpl("struct", structTmpl).Execute(&buf, data) |
| if err != nil { |
| log.Fatalf("vdl: couldn't execute struct template: %v", err) |
| } |
| return JavaFileInfo{ |
| Name: javaTypeName + ".java", |
| Data: buf.Bytes(), |
| } |
| } |