blob: a5058f832a0f442a40c112985e40a07d8efb4984 [file] [log] [blame]
// 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(),
}
}