activity/tools/vocab/gen/generate_property_definitions.go

1231 行
48 KiB
Go

package gen
import (
"bytes"
"fmt"
"github.com/go-fed/activity/tools/defs"
"strings"
)
func generatePropertyDefinitions(t *defs.PropertyType, this *defs.StructDef, i *defs.InterfaceDef, m map[*defs.PropertyType]*intermedDef) (fd []*defs.FunctionDef, sd []*defs.StructDef, s, d string) {
if isAny(t) {
fd, sd, s, d = generateAnyDefinitions(t, this, i)
} else if isSingleType(t) {
fd, sd, s, d = generateSingleTypeDefinitions(t, this, i)
} else {
fd, sd, s, d = generateMultiTypeDefinitions(t, this, i, m)
}
if t.NaturalLanguageMap {
fdMap, sdMap, sMap, dMap := generateNaturalLanguageMap(t, this, i)
fd = append(fd, fdMap...)
sd = append(sd, sdMap...)
s += "\n" + sMap
d += "\n" + dMap
}
return
}
func generateNaturalLanguageMap(t *defs.PropertyType, this *defs.StructDef, i *defs.InterfaceDef) (fd []*defs.FunctionDef, sd []*defs.StructDef, s, d string) {
mapMember := &defs.StructMember{
Name: t.Name + "Map",
Type: "map[string]string",
Comment: fmt.Sprintf("The '%sMap' value holds language-specific values for property '%s'", t.Name, t.Name),
}
this.M = append(this.M, mapMember)
this.F = append(this.F, []*defs.MemberFunctionDef{
{
Name: fmt.Sprintf("%sMapLanguages", strings.Title(t.Name)),
Comment: fmt.Sprintf("%sMapLanguages returns all languages for this property's language mapping, or nil if there are none.", strings.Title(t.Name)),
P: this,
Return: []*defs.FunctionVarDef{{"l", "[]string"}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("if t.%sMap == nil || len(t.%sMap) == 0 {\n", t.Name, t.Name))
b.WriteString("return nil\n")
b.WriteString("}\n")
b.WriteString(fmt.Sprintf("for k := range t.%sMap {\n", t.Name))
b.WriteString("l = append(l, k)\n")
b.WriteString("}\n")
b.WriteString("return\n")
return b.String()
},
},
{
Name: fmt.Sprintf("Get%sMap", strings.Title(t.Name)),
Comment: fmt.Sprintf("Get%sMap retrieves the value of the property for the specified language, or an empty string if it does not exist", strings.Title(t.Name)),
P: this,
Args: []*defs.FunctionVarDef{{"l", "string"}},
Return: []*defs.FunctionVarDef{{"v", "string"}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("if t.%sMap == nil {\n", t.Name))
b.WriteString("return \"\"\n")
b.WriteString("}\n")
b.WriteString("ok := false\n")
b.WriteString(fmt.Sprintf("v, ok = t.%sMap[l]\n", t.Name))
b.WriteString("if !ok {\n")
b.WriteString("return \"\"\n")
b.WriteString("}\n")
b.WriteString("return v\n")
return b.String()
},
},
{
Name: fmt.Sprintf("Set%sMap", strings.Title(t.Name)),
Comment: fmt.Sprintf("Set%sMap sets the value of the property for the specified language", strings.Title(t.Name)),
P: this,
Args: []*defs.FunctionVarDef{{"l", "string"}, {"v", "string"}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("if t.%sMap == nil {\n", t.Name))
b.WriteString(fmt.Sprintf("t.%sMap = make(map[string]string)\n", t.Name))
b.WriteString("}\n")
b.WriteString(fmt.Sprintf("t.%sMap[l] = v\n", t.Name))
return b.String()
},
},
}...)
i.F = append(i.F, []*defs.FunctionDef{
{
Name: fmt.Sprintf("%sMapLanguages", strings.Title(t.Name)),
Comment: fmt.Sprintf("%sMapLanguages returns all languages for this property's language mapping, or nil if there are none.", strings.Title(t.Name)),
Return: []*defs.FunctionVarDef{{"l", "[]string"}},
},
{
Name: fmt.Sprintf("Get%sMap", strings.Title(t.Name)),
Comment: fmt.Sprintf("Get%sMap retrieves the value of the property for the specified language, or an empty string if it does not exist", strings.Title(t.Name)),
Args: []*defs.FunctionVarDef{{"l", "string"}},
Return: []*defs.FunctionVarDef{{"v", "string"}},
},
{
Name: fmt.Sprintf("Set%sMap", strings.Title(t.Name)),
Comment: fmt.Sprintf("Set%sMap sets the value of the property for the specified language", strings.Title(t.Name)),
Args: []*defs.FunctionVarDef{{"l", "string"}, {"v", "string"}},
},
}...)
var b bytes.Buffer
b.WriteString("// Begin generation by generateNaturalLanguageMap\n")
b.WriteString(fmt.Sprintf("if k == \"%sMap\" {\n", t.Name))
b.WriteString("if vMap, ok := v.(map[string]interface{}); ok {\n")
b.WriteString("val := make(map[string]string)\n")
b.WriteString("for k, iVal := range vMap {\n")
b.WriteString("if sVal, ok := iVal.(string); ok {\n")
b.WriteString("val[k] = sVal\n")
b.WriteString("}\n")
b.WriteString("}\n")
b.WriteString(fmt.Sprintf("t.%sMap = val\n", t.Name))
b.WriteString("handled = true\n")
b.WriteString("}\n")
b.WriteString("}\n")
b.WriteString("// End generation by generateNaturalLanguageMap\n")
d = b.String()
var bs bytes.Buffer
bs.WriteString("// Begin generation by generateNaturalLanguageMap\n")
bs.WriteString(fmt.Sprintf("if t.%sMap != nil && len(t.%sMap) >= 0 {\n", t.Name, t.Name))
bs.WriteString(fmt.Sprintf("m[\"%sMap\"] = t.%sMap\n", t.Name, t.Name))
bs.WriteString("}\n")
bs.WriteString("// End generation by generateNaturalLanguageMap\n")
s = bs.String()
return
}
func generateAnyDefinitions(t *defs.PropertyType, this *defs.StructDef, i *defs.InterfaceDef) (fd []*defs.FunctionDef, sd []*defs.StructDef, s, d string) {
if t.Functional {
return generateFunctionalAnyDefinition(t, this, i)
} else {
return generateNonFunctionalAnyDefinition(t, this, i)
}
}
func generateFunctionalAnyDefinition(t *defs.PropertyType, this *defs.StructDef, i *defs.InterfaceDef) (fd []*defs.FunctionDef, sd []*defs.StructDef, s, d string) {
titleName := strings.Title(t.Name)
anyMember := &defs.StructMember{
Name: cleanName(t.Name),
Type: "interface{}",
Comment: fmt.Sprintf("The functional '%s' value can hold any type, but only a single value", t.Name),
}
this.M = append(this.M, anyMember)
this.F = append(this.F, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Get%s", titleName),
Comment: fmt.Sprintf("Get%s returns the value for %s", titleName, t.Name),
P: this,
Return: []*defs.FunctionVarDef{{"v", anyMember.Type}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("return t.%s\n", anyMember.Name))
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Set%s", titleName),
Comment: fmt.Sprintf("Set%s sets the value of %s", titleName, t.Name),
P: this,
Args: []*defs.FunctionVarDef{{"v", anyMember.Type}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("t.%s = v\n", anyMember.Name))
return b.String()
},
})
i.F = append(i.F, []*defs.FunctionDef{
{
Name: fmt.Sprintf("Get%s", titleName),
Comment: fmt.Sprintf("Get%s returns the value for %s", titleName, t.Name),
Return: []*defs.FunctionVarDef{{"v", anyMember.Type}},
},
{
Name: fmt.Sprintf("Set%s", titleName),
Comment: fmt.Sprintf("Set%s sets the value of %s", titleName, t.Name),
Args: []*defs.FunctionVarDef{{"v", anyMember.Type}},
},
}...)
var b bytes.Buffer
b.WriteString("// Begin generation by generateFunctionalAnyDefinition\n")
b.WriteString(fmt.Sprintf("if k == \"%s\" {\n", t.Name))
b.WriteString(fmt.Sprintf("t.%s = v\n", anyMember.Name))
b.WriteString("handled = true\n")
b.WriteString("}\n")
b.WriteString("// End generation by generateFunctionalAnyDefinition\n")
d = b.String()
var bs bytes.Buffer
bs.WriteString("// Begin generation by generateFunctionalAnyDefinition\n")
bs.WriteString(fmt.Sprintf("if t.%s != nil {\n", anyMember.Name))
bs.WriteString(fmt.Sprintf("m[\"%s\"] = t.%s\n", t.Name, anyMember.Name))
bs.WriteString("}\n")
bs.WriteString("// End generation by generateFunctionalAnyDefinition\n")
s = bs.String()
return
}
func generateNonFunctionalAnyDefinition(t *defs.PropertyType, this *defs.StructDef, i *defs.InterfaceDef) (fd []*defs.FunctionDef, sd []*defs.StructDef, s, d string) {
titleName := strings.Title(t.Name)
anyMember := &defs.StructMember{
Name: cleanName(t.Name),
Type: "[]interface{}",
Comment: fmt.Sprintf("The '%s' value can hold any type and any number of values", t.Name),
}
this.M = append(this.M, anyMember)
this.F = append(this.F, &defs.MemberFunctionDef{
Name: fmt.Sprintf("%sLen", titleName),
Comment: fmt.Sprintf("%sLen determines the number of elements able to be used for the Get%s and Remove%s functions", titleName, titleName, titleName),
P: this,
Return: []*defs.FunctionVarDef{{"l", "int"}},
Body: func() string {
return fmt.Sprintf("return len(t.%s)\n", anyMember.Name)
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Get%s", titleName),
Comment: fmt.Sprintf("Get%s returns the value for the specified index", titleName),
P: this,
Args: []*defs.FunctionVarDef{{"index", "int"}},
Return: []*defs.FunctionVarDef{{"v", deSlice(anyMember.Type)}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("return t.%s[index]\n", anyMember.Name))
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Append%s", titleName),
Comment: fmt.Sprintf("Append%s adds a value to the back of %s", titleName, t.Name),
P: this,
Args: []*defs.FunctionVarDef{{"v", deSlice(anyMember.Type)}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("t.%s = append(t.%s, v)\n", anyMember.Name, anyMember.Name))
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Prepend%s", titleName),
Comment: fmt.Sprintf("Prepend%s adds a value to the front of %s", titleName, t.Name),
P: this,
Args: []*defs.FunctionVarDef{{"v", deSlice(anyMember.Type)}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("t.%s = append(%s{v}, t.%s...)\n", anyMember.Name, anyMember.Type, anyMember.Name))
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Remove%s", titleName),
Comment: fmt.Sprintf("Remove%s deletes the value from the specified index", titleName),
P: this,
Args: []*defs.FunctionVarDef{{"index", "int"}},
Body: func() string {
sliceVar := fmt.Sprintf("t.%s", anyMember.Name)
var b bytes.Buffer
b.WriteString(fmt.Sprintf("copy(%s[index:], %s[index+1:])\n", sliceVar, sliceVar))
b.WriteString(fmt.Sprintf("%s[len(%s)-1] = nil\n", sliceVar, sliceVar))
b.WriteString(fmt.Sprintf("%s = %s[:len(%s)-1]\n", sliceVar, sliceVar, sliceVar))
return b.String()
},
})
i.F = append(i.F, []*defs.FunctionDef{
{
Name: fmt.Sprintf("%sLen", titleName),
Comment: fmt.Sprintf("%sLen determines the number of elements able to be used for the Get%s and Remove%s functions", titleName, titleName, titleName),
Return: []*defs.FunctionVarDef{{"l", "int"}},
},
{
Name: fmt.Sprintf("Get%s", titleName),
Comment: fmt.Sprintf("Get%s returns the value for the specified index", titleName),
Args: []*defs.FunctionVarDef{{"index", "int"}},
Return: []*defs.FunctionVarDef{{"v", deSlice(anyMember.Type)}},
},
{
Name: fmt.Sprintf("Append%s", titleName),
Comment: fmt.Sprintf("Append%s adds a value to the back of %s", titleName, t.Name),
Args: []*defs.FunctionVarDef{{"v", deSlice(anyMember.Type)}},
},
{
Name: fmt.Sprintf("Prepend%s", titleName),
Comment: fmt.Sprintf("Prepend%s adds a value to the front of %s", titleName, t.Name),
Args: []*defs.FunctionVarDef{{"v", deSlice(anyMember.Type)}},
},
{
Name: fmt.Sprintf("Remove%s", titleName),
Comment: fmt.Sprintf("Remove%s deletes the value from the specified index", titleName),
Args: []*defs.FunctionVarDef{{"index", "int"}},
},
}...)
tmpVar := fmt.Sprintf("tmp%sSlice", titleName)
var b bytes.Buffer
b.WriteString("// Begin generation by generateNonFunctionalAnyDefinition\n")
b.WriteString(fmt.Sprintf("if k == \"%s\" {\n", t.Name))
b.WriteString(fmt.Sprintf("if %s, ok := v.([]interface{}); ok {\n", tmpVar))
b.WriteString(fmt.Sprintf("t.%s = %s\n", anyMember.Name, tmpVar))
b.WriteString("handled = true\n")
b.WriteString("} else {\n")
b.WriteString(fmt.Sprintf("t.%s = []interface{}{v}\n", anyMember.Name))
b.WriteString("handled = true\n")
b.WriteString("}\n")
b.WriteString("}\n")
b.WriteString("// End generation by generateNonFunctionalAnyDefinition\n")
d = b.String()
var bs bytes.Buffer
bs.WriteString("// Begin generation by generateNonFunctionalAnyDefinition\n")
bs.WriteString(fmt.Sprintf("if t.%s != nil {\n", anyMember.Name))
bs.WriteString(fmt.Sprintf("if len(t.%s) == 1 {\n", anyMember.Name))
bs.WriteString(fmt.Sprintf("m[\"%s\"] = t.%s[0]\n", t.Name, anyMember.Name))
bs.WriteString("} else {\n")
bs.WriteString(fmt.Sprintf("m[\"%s\"] = t.%s\n", t.Name, anyMember.Name))
bs.WriteString("}\n")
bs.WriteString("}\n")
bs.WriteString("// End generation by generateNonFunctionalAnyDefinition\n")
s = bs.String()
return
}
func generateSingleTypeDefinitions(t *defs.PropertyType, this *defs.StructDef, i *defs.InterfaceDef) (fd []*defs.FunctionDef, sd []*defs.StructDef, s, d string) {
if t.Functional {
return generateFunctionalSingleTypeDefinition(t, this, i)
} else {
return generateNonFunctionalSingleTypeDefinition(t, this, i)
}
}
func generateFunctionalSingleTypeDefinition(t *defs.PropertyType, this *defs.StructDef, i *defs.InterfaceDef) (fd []*defs.FunctionDef, sd []*defs.StructDef, s, d string) {
member := &defs.StructMember{
Name: cleanName(t.Name),
Type: Type(t.Range[0]),
Comment: fmt.Sprintf("The functional '%s' value holds a single type and a single value", t.Name),
}
titleName := strings.Title(t.Name)
isPtrType := isPtrType(member.Type)
isIRI := isIRIType(member.Type)
returnType := deref(member.Type)
if isIRI {
returnType = member.Type
}
this.M = append(this.M, member)
this.F = append(this.F, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Has%s", titleName),
Comment: fmt.Sprintf("Has%s determines whether the call to Get%s is safe", titleName, titleName),
P: this,
Return: []*defs.FunctionVarDef{{"ok", "bool"}},
Body: func() string {
return fmt.Sprintf("return t.%s != nil\n", member.Name)
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Get%s", titleName),
Comment: fmt.Sprintf("Get%s returns the value for %s", titleName, t.Name),
P: this,
Return: []*defs.FunctionVarDef{{"v", returnType}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("return "))
if isPtrType && !isIRI {
b.WriteString("*")
}
b.WriteString(fmt.Sprintf("t.%s\n", member.Name))
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Set%s", titleName),
Comment: fmt.Sprintf("Set%s sets the value of %s", titleName, t.Name),
P: this,
Args: []*defs.FunctionVarDef{{"v", returnType}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("t.%s = ", member.Name))
if isPtrType && !isIRI {
b.WriteString("&")
}
b.WriteString("v\n")
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("HasUnknown%s", titleName),
Comment: fmt.Sprintf("HasUnknown%s determines whether the call to GetUnknown%s is safe", titleName, titleName),
P: this,
Return: []*defs.FunctionVarDef{{"ok", "bool"}},
Body: func() string {
return fmt.Sprintf("return t.unknown_ != nil && t.unknown_[\"%s\"] != nil\n", t.Name)
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("GetUnknown%s", titleName),
Comment: fmt.Sprintf("GetUnknown%s returns the unknown value for %s", titleName, t.Name),
P: this,
Return: []*defs.FunctionVarDef{{"v", "interface{}"}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("return t.unknown_[\"%s\"]\n", t.Name))
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("SetUnknown%s", titleName),
Comment: fmt.Sprintf("SetUnknown%s sets the unknown value of %s", titleName, t.Name),
P: this,
Args: []*defs.FunctionVarDef{{"i", "interface{}"}},
Body: func() string {
var b bytes.Buffer
b.WriteString("if t.unknown_ == nil {\n")
b.WriteString("t.unknown_ = make(map[string]interface{})")
b.WriteString("}\n")
b.WriteString(fmt.Sprintf("t.unknown_[\"%s\"] = i\n", t.Name))
return b.String()
},
})
i.F = append(i.F, []*defs.FunctionDef{
{
Name: fmt.Sprintf("Has%s", titleName),
Comment: fmt.Sprintf("Has%s determines whether the call to Get%s is safe", titleName, titleName),
Return: []*defs.FunctionVarDef{{"ok", "bool"}},
},
{
Name: fmt.Sprintf("Get%s", titleName),
Comment: fmt.Sprintf("Get%s returns the value for %s", titleName, t.Name),
Return: []*defs.FunctionVarDef{{"v", returnType}},
},
{
Name: fmt.Sprintf("Set%s", titleName),
Comment: fmt.Sprintf("Set%s sets the value of %s", titleName, t.Name),
Args: []*defs.FunctionVarDef{{"v", returnType}},
},
{
Name: fmt.Sprintf("HasUnknown%s", titleName),
Comment: fmt.Sprintf("HasUnknown%s determines whether the call to GetUnknown%s is safe", titleName, titleName),
Return: []*defs.FunctionVarDef{{"ok", "bool"}},
},
{
Name: fmt.Sprintf("GetUnknown%s", titleName),
Comment: fmt.Sprintf("GetUnknown%s returns the unknown value for %s", titleName, t.Name),
Return: []*defs.FunctionVarDef{{"v", "interface{}"}},
},
{
Name: fmt.Sprintf("SetUnknown%s", titleName),
Comment: fmt.Sprintf("SetUnknown%s sets the unknown value of %s", titleName, t.Name),
Args: []*defs.FunctionVarDef{{"i", "interface{}"}},
},
}...)
d = Deserialize(t.Range[0], t.Name, member.Name, false)
s = Serialize(t.Range[0], t.Name, member.Name, false)
return
}
func generateNonFunctionalSingleTypeDefinition(t *defs.PropertyType, this *defs.StructDef, i *defs.InterfaceDef) (fd []*defs.FunctionDef, sd []*defs.StructDef, s, d string) {
isIRI := isIRIType(Type(t.Range[0]))
memberType := deref(Type(t.Range[0]))
returnType := memberType
if isIRI {
memberType = Type(t.Range[0])
returnType = memberType
}
member := &defs.StructMember{
Name: cleanName(t.Name),
Type: fmt.Sprintf("[]%s", memberType),
Comment: fmt.Sprintf("The '%s' value holds a single type and any number of values", t.Name),
}
titleName := strings.Title(t.Name)
this.M = append(this.M, member)
this.F = append(this.F, &defs.MemberFunctionDef{
Name: fmt.Sprintf("%sLen", titleName),
Comment: fmt.Sprintf("%sLen determines the number of elements able to be used for the Get%s and Remove%s functions", titleName, titleName, titleName),
P: this,
Return: []*defs.FunctionVarDef{{"l", "int"}},
Body: func() string {
return fmt.Sprintf("return len(t.%s)\n", member.Name)
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Get%s", titleName),
Comment: fmt.Sprintf("Get%s returns the value for the specified index", titleName),
P: this,
Args: []*defs.FunctionVarDef{{"index", "int"}},
Return: []*defs.FunctionVarDef{{"v", returnType}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("return t.%s[index]\n", member.Name))
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Append%s", titleName),
Comment: fmt.Sprintf("Append%s adds a value to the back of %s", titleName, t.Name),
P: this,
Args: []*defs.FunctionVarDef{{"v", returnType}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("t.%s = append(t.%s, v)\n", member.Name, member.Name))
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Prepend%s", titleName),
Comment: fmt.Sprintf("Prepend%s adds a value to the front of %s", titleName, t.Name),
P: this,
Args: []*defs.FunctionVarDef{{"v", returnType}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("t.%s = append(%s{v}, t.%s...)\n", member.Name, member.Type, member.Name))
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("Remove%s", titleName),
Comment: fmt.Sprintf("Remove%s deletes the value from the specified index", titleName),
P: this,
Args: []*defs.FunctionVarDef{{"index", "int"}},
Body: func() string {
sliceVar := fmt.Sprintf("t.%s", member.Name)
var b bytes.Buffer
b.WriteString(fmt.Sprintf("copy(%s[index:], %s[index+1:])\n", sliceVar, sliceVar))
if isPtrType(deSlice(member.Type)) {
b.WriteString(fmt.Sprintf("%s[len(%s)-1] = nil\n", sliceVar, sliceVar))
}
b.WriteString(fmt.Sprintf("%s = %s[:len(%s)-1]\n", sliceVar, sliceVar, sliceVar))
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("HasUnknown%s", titleName),
Comment: fmt.Sprintf("HasUnknown%s determines whether the call to GetUnknown%s is safe", titleName, titleName),
P: this,
Return: []*defs.FunctionVarDef{{"ok", "bool"}},
Body: func() string {
return fmt.Sprintf("return t.unknown_ != nil && t.unknown_[\"%s\"] != nil\n", t.Name)
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("GetUnknown%s", titleName),
Comment: fmt.Sprintf("GetUnknown%s returns the unknown value for %s", titleName, t.Name),
P: this,
Return: []*defs.FunctionVarDef{{"v", "interface{}"}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("return t.unknown_[\"%s\"]\n", t.Name))
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("SetUnknown%s", titleName),
Comment: fmt.Sprintf("SetUnknown%s sets the unknown value of %s", titleName, t.Name),
P: this,
Args: []*defs.FunctionVarDef{{"i", "interface{}"}},
Body: func() string {
var b bytes.Buffer
b.WriteString("if t.unknown_ == nil {\n")
b.WriteString("t.unknown_ = make(map[string]interface{})")
b.WriteString("}\n")
b.WriteString(fmt.Sprintf("t.unknown_[\"%s\"] = i\n", t.Name))
return b.String()
},
})
i.F = append(i.F, []*defs.FunctionDef{
{
Name: fmt.Sprintf("%sLen", titleName),
Comment: fmt.Sprintf("%sLen determines the number of elements able to be used for the Get%s and Remove%s functions", titleName, titleName, titleName),
Return: []*defs.FunctionVarDef{{"l", "int"}},
},
{
Name: fmt.Sprintf("Get%s", titleName),
Comment: fmt.Sprintf("Get%s returns the value for the specified index", titleName),
Args: []*defs.FunctionVarDef{{"index", "int"}},
Return: []*defs.FunctionVarDef{{"v", returnType}},
},
{
Name: fmt.Sprintf("Append%s", titleName),
Comment: fmt.Sprintf("Append%s adds a value to the back of %s", titleName, t.Name),
Args: []*defs.FunctionVarDef{{"v", returnType}},
},
{
Name: fmt.Sprintf("Prepend%s", titleName),
Comment: fmt.Sprintf("Prepend%s adds a value to the front of %s", titleName, t.Name),
Args: []*defs.FunctionVarDef{{"v", returnType}},
},
{
Name: fmt.Sprintf("Remove%s", titleName),
Comment: fmt.Sprintf("Remove%s deletes the value from the specified index", titleName),
Args: []*defs.FunctionVarDef{{"index", "int"}},
},
{
Name: fmt.Sprintf("HasUnknown%s", titleName),
Comment: fmt.Sprintf("HasUnknown%s determines whether the call to GetUnknown%s is safe", titleName, titleName),
Return: []*defs.FunctionVarDef{{"ok", "bool"}},
},
{
Name: fmt.Sprintf("GetUnknown%s", titleName),
Comment: fmt.Sprintf("GetUnknown%s returns the unknown value for %s", titleName, t.Name),
Return: []*defs.FunctionVarDef{{"v", "interface{}"}},
},
{
Name: fmt.Sprintf("SetUnknown%s", titleName),
Comment: fmt.Sprintf("SetUnknown%s sets the unknown value of %s", titleName, t.Name),
Args: []*defs.FunctionVarDef{{"i", "interface{}"}},
},
}...)
d = Deserialize(t.Range[0], t.Name, member.Name, true)
s = Serialize(t.Range[0], t.Name, member.Name, true)
return
}
func generateMultiTypeDefinitions(t *defs.PropertyType, this *defs.StructDef, i *defs.InterfaceDef, m map[*defs.PropertyType]*intermedDef) (fd []*defs.FunctionDef, sd []*defs.StructDef, s, d string) {
if t.Functional {
return generateFunctionalMultiTypeDefinition(t, this, i, m)
} else {
return generateNonFunctionalMultiTypeDefinition(t, this, i, m)
}
}
func generateFunctionalMultiTypeDefinition(t *defs.PropertyType, this *defs.StructDef, i *defs.InterfaceDef, intermedMap map[*defs.PropertyType]*intermedDef) (fd []*defs.FunctionDef, sd []*defs.StructDef, s, d string) {
titleName := strings.Title(t.Name)
var intermed *defs.StructDef
if i, ok := intermedMap[t]; ok {
intermed = i.S
} else {
double := false
for k := range intermedMap {
if k.Name == t.Name {
intermedMap[k] = generateIntermediateTypeDefinition([]*defs.PropertyType{k, t})
intermed = intermedMap[k].S
double = true
break
}
}
if !double {
intermedMap[t] = generateIntermediateTypeDefinition([]*defs.PropertyType{t})
intermed = intermedMap[t].S
}
}
thisIntermed := &defs.StructMember{
Name: cleanName(t.Name),
Type: "*" + intermed.Typename,
Comment: fmt.Sprintf("The functional '%s' value could have multiple types, but only a single value", t.Name),
}
this.M = append(this.M, thisIntermed)
for idx, r := range t.Range {
r := r
memberName := cleanName(Name(r))
memberType := Type(r)
isIRI := isIRIType(memberType)
retKind := deref(memberType)
if isIRI {
retKind = memberType
}
typeExtensionName := strings.Title(Name(r))
if defs.IsOnlyOtherPropertyBesidesIRI(idx, t.Range) {
typeExtensionName = ""
}
this.F = append(this.F, []*defs.MemberFunctionDef{
{
Name: fmt.Sprintf("Is%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Is%s%s determines whether the call to Get%s%s is safe", titleName, typeExtensionName, titleName, typeExtensionName),
P: this,
Return: []*defs.FunctionVarDef{{"ok", "bool"}},
Body: func() string {
return fmt.Sprintf("return t.%s != nil && t.%s.%s != nil\n", thisIntermed.Name, thisIntermed.Name, memberName)
},
},
{
Name: fmt.Sprintf("Get%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Get%s%s returns the value safely if Is%s%s returned true", titleName, typeExtensionName, titleName, typeExtensionName),
P: this,
Return: []*defs.FunctionVarDef{{"v", retKind}},
Body: func() string {
var b bytes.Buffer
b.WriteString("return ")
if isPtrType(Type(r)) && !isIRI {
b.WriteString("*")
}
b.WriteString(fmt.Sprintf("t.%s.%s\n", thisIntermed.Name, memberName))
return b.String()
},
},
{
Name: fmt.Sprintf("Set%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Set%s%s sets the value of %s to be of %s type", titleName, typeExtensionName, cleanName(t.Name), retKind),
P: this,
Args: []*defs.FunctionVarDef{{"v", retKind}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("t.%s = &%s{%s:", thisIntermed.Name, intermed.Typename, memberName))
if isPtrType(Type(r)) && !isIRI {
b.WriteString("&")
}
b.WriteString("v}\n")
return b.String()
},
},
}...)
i.F = append(i.F, []*defs.FunctionDef{
{
Name: fmt.Sprintf("Is%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Is%s%s determines whether the call to Get%s%s is safe", titleName, typeExtensionName, titleName, typeExtensionName),
Return: []*defs.FunctionVarDef{{"ok", "bool"}},
},
{
Name: fmt.Sprintf("Get%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Get%s%s returns the value safely if Is%s%s returned true", titleName, typeExtensionName, titleName, typeExtensionName),
Return: []*defs.FunctionVarDef{{"v", retKind}},
},
{
Name: fmt.Sprintf("Set%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Set%s%s sets the value of %s to be of %s type", titleName, typeExtensionName, cleanName(t.Name), retKind),
Args: []*defs.FunctionVarDef{{"v", retKind}},
},
}...)
}
var b bytes.Buffer
b.WriteString("// Begin generation by generateFunctionalMultiTypeDefinition\n")
b.WriteString(fmt.Sprintf("if k == \"%s\" {\n", t.Name))
b.WriteString(fmt.Sprintf("t.%s, err = deserialize%s(v)\n", thisIntermed.Name, strings.Title(intermed.Typename)))
b.WriteString("if err != nil {\nreturn err\n}\n")
b.WriteString("handled = true\n")
b.WriteString("}\n")
b.WriteString("// End generation by generateFunctionalMultiTypeDefinition\n")
d = b.String()
var bs bytes.Buffer
bs.WriteString("// Begin generation by generateFunctionalMultiTypeDefinition\n")
bs.WriteString(fmt.Sprintf("if t.%s != nil {\n", thisIntermed.Name))
bs.WriteString(fmt.Sprintf("if v, err := serialize%s(t.%s); err == nil {\n", strings.Title(intermed.Typename), thisIntermed.Name))
bs.WriteString(fmt.Sprintf("m[\"%s\"] = v\n", t.Name))
bs.WriteString("} else {\n")
bs.WriteString("return m, err\n")
bs.WriteString("}\n")
bs.WriteString("}\n")
bs.WriteString("// End generation by generateFunctionalMultiTypeDefinition\n")
s = bs.String()
generateUnknownFunctions(t, this, i, thisIntermed, intermed)
return
}
func generateNonFunctionalMultiTypeDefinition(t *defs.PropertyType, this *defs.StructDef, i *defs.InterfaceDef, intermedMap map[*defs.PropertyType]*intermedDef) (fd []*defs.FunctionDef, sd []*defs.StructDef, s, d string) {
titleName := strings.Title(t.Name)
var intermed *defs.StructDef
if i, ok := intermedMap[t]; ok {
intermed = i.S
} else {
double := false
for k := range intermedMap {
if k.Name == t.Name {
intermedMap[k] = generateIntermediateTypeDefinition([]*defs.PropertyType{k, t})
intermed = intermedMap[k].S
double = true
break
}
}
if !double {
intermedMap[t] = generateIntermediateTypeDefinition([]*defs.PropertyType{t})
intermed = intermedMap[t].S
}
}
thisIntermed := &defs.StructMember{
Name: cleanName(t.Name),
Type: fmt.Sprintf("[]*%s", intermed.Typename),
Comment: fmt.Sprintf("The '%s' value could have multiple types and values", t.Name),
}
this.M = append(this.M, thisIntermed)
for idx, r := range t.Range {
r := r
memberName := cleanName(Name(r))
memberType := Type(r)
isIRI := isIRIType(memberType)
retKind := deref(memberType)
if isIRI {
retKind = memberType
}
typeExtensionName := strings.Title(Name(r))
if defs.IsOnlyOtherPropertyBesidesIRI(idx, t.Range) {
typeExtensionName = ""
}
if idx == 0 {
this.F = append(this.F, &defs.MemberFunctionDef{
Name: fmt.Sprintf("%sLen", titleName),
Comment: fmt.Sprintf("%sLen determines the number of elements able to be used for the Is%s%s, Get%s%s, and Remove%s%s functions", titleName, titleName, typeExtensionName, titleName, typeExtensionName, titleName, typeExtensionName),
P: this,
Return: []*defs.FunctionVarDef{{"l", "int"}},
Body: func() string {
return fmt.Sprintf("return len(t.%s)\n", thisIntermed.Name)
},
})
i.F = append(i.F, &defs.FunctionDef{
Name: fmt.Sprintf("%sLen", titleName),
Comment: fmt.Sprintf("%sLen determines the number of elements able to be used for the Is%s%s, Get%s%s, and Remove%s%s functions", titleName, titleName, typeExtensionName, titleName, typeExtensionName, titleName, typeExtensionName),
Return: []*defs.FunctionVarDef{{"l", "int"}},
})
}
this.F = append(this.F, []*defs.MemberFunctionDef{
{
Name: fmt.Sprintf("Is%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Is%s%s determines whether the call to Get%s%s is safe for the specified index", titleName, typeExtensionName, titleName, typeExtensionName),
P: this,
Args: []*defs.FunctionVarDef{{"index", "int"}},
Return: []*defs.FunctionVarDef{{"ok", "bool"}},
Body: func() string {
return fmt.Sprintf("return t.%s[index].%s != nil\n", thisIntermed.Name, memberName)
},
},
{
Name: fmt.Sprintf("Get%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Get%s%s returns the value safely if Is%s%s returned true for the specified index", titleName, typeExtensionName, titleName, typeExtensionName),
P: this,
Args: []*defs.FunctionVarDef{{"index", "int"}},
Return: []*defs.FunctionVarDef{{"v", retKind}},
Body: func() string {
var b bytes.Buffer
b.WriteString("return ")
if isPtrType(Type(r)) && !isIRI {
b.WriteString("*")
}
b.WriteString(fmt.Sprintf("t.%s[index].%s\n", thisIntermed.Name, memberName))
return b.String()
},
},
{
Name: fmt.Sprintf("Append%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Append%s%s adds to the back of %s a %s type", titleName, typeExtensionName, cleanName(t.Name), retKind),
P: this,
Args: []*defs.FunctionVarDef{{"v", retKind}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("t.%s = append(t.%s, &%s{%s:", thisIntermed.Name, thisIntermed.Name, intermed.Typename, memberName))
if isPtrType(Type(r)) && !isIRI {
b.WriteString("&")
}
b.WriteString("v})\n")
return b.String()
},
},
{
Name: fmt.Sprintf("Prepend%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Prepend%s%s adds to the front of %s a %s type", titleName, typeExtensionName, cleanName(t.Name), retKind),
P: this,
Args: []*defs.FunctionVarDef{{"v", retKind}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("t.%s = append([]*%s{&%s{%s:", thisIntermed.Name, intermed.Typename, intermed.Typename, memberName))
if isPtrType(Type(r)) && !isIRI {
b.WriteString("&")
}
b.WriteString(fmt.Sprintf("v}}, t.%s...)\n", thisIntermed.Name))
return b.String()
},
},
{
Name: fmt.Sprintf("Remove%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Remove%s%s deletes the value from the specified index", titleName, typeExtensionName),
P: this,
Args: []*defs.FunctionVarDef{{"index", "int"}},
Body: func() string {
sliceVar := fmt.Sprintf("t.%s", thisIntermed.Name)
var b bytes.Buffer
b.WriteString(fmt.Sprintf("copy(%s[index:], %s[index+1:])\n", sliceVar, sliceVar))
b.WriteString(fmt.Sprintf("%s[len(%s)-1] = %s\n", sliceVar, sliceVar, "nil"))
b.WriteString(fmt.Sprintf("%s = %s[:len(%s)-1]\n", sliceVar, sliceVar, sliceVar))
return b.String()
},
},
}...)
i.F = append(i.F, []*defs.FunctionDef{
{
Name: fmt.Sprintf("Is%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Is%s%s determines whether the call to Get%s%s is safe for the specified index", titleName, typeExtensionName, titleName, typeExtensionName),
Args: []*defs.FunctionVarDef{{"index", "int"}},
Return: []*defs.FunctionVarDef{{"ok", "bool"}},
},
{
Name: fmt.Sprintf("Get%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Get%s%s returns the value safely if Is%s%s returned true for the specified index", titleName, typeExtensionName, titleName, typeExtensionName),
Args: []*defs.FunctionVarDef{{"index", "int"}},
Return: []*defs.FunctionVarDef{{"v", retKind}},
},
{
Name: fmt.Sprintf("Append%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Append%s%s adds to the back of %s a %s type", titleName, typeExtensionName, cleanName(t.Name), retKind),
Args: []*defs.FunctionVarDef{{"v", retKind}},
},
{
Name: fmt.Sprintf("Prepend%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Prepend%s%s adds to the front of %s a %s type", titleName, typeExtensionName, cleanName(t.Name), retKind),
Args: []*defs.FunctionVarDef{{"v", retKind}},
},
{
Name: fmt.Sprintf("Remove%s%s", titleName, typeExtensionName),
Comment: fmt.Sprintf("Remove%s%s deletes the value from the specified index", titleName, typeExtensionName),
Args: []*defs.FunctionVarDef{{"index", "int"}},
},
}...)
}
var b bytes.Buffer
b.WriteString("// Begin generation by generateNonFunctionalMultiTypeDefinition\n")
b.WriteString(fmt.Sprintf("if k == \"%s\" {\n", t.Name))
b.WriteString("if tmpMap, ok := v.(map[string]interface{}); ok {\n")
b.WriteString(fmt.Sprintf("tmp, err := deserialize%s(tmpMap)\n", strings.Title(intermed.Typename)))
b.WriteString("if err != nil {\nreturn err\n}\n")
b.WriteString(fmt.Sprintf("t.%s = []*%s{tmp}\n", thisIntermed.Name, intermed.Typename))
b.WriteString("handled = true\n")
b.WriteString("} else if tmpSlice, ok := v.([]interface{}); ok {\n")
b.WriteString(fmt.Sprintf("t.%s, err = deserializeSlice%s(tmpSlice)\n", thisIntermed.Name, strings.Title(intermed.Typename)))
b.WriteString("if err != nil {\nreturn err\n}\n")
b.WriteString("handled = true\n")
b.WriteString("} else {\n")
b.WriteString(fmt.Sprintf("tmp := &%s{}\n", intermed.Typename))
b.WriteString("err = tmp.Deserialize(v)\n")
b.WriteString("if err != nil {\nreturn err\n}\n")
b.WriteString(fmt.Sprintf("t.%s = []*%s{tmp}\n", thisIntermed.Name, intermed.Typename))
b.WriteString("handled = true\n")
b.WriteString("}\n")
b.WriteString("}\n")
b.WriteString("// End generation by generateNonFunctionalMultiTypeDefinition\n")
d = b.String()
var bs bytes.Buffer
bs.WriteString("// Begin generation by generateNonFunctionalMultiTypeDefinition\n")
bs.WriteString(fmt.Sprintf("if v, err := serializeSlice%s(t.%s); err == nil && v != nil {\n", strings.Title(intermed.Typename), thisIntermed.Name))
bs.WriteString("if len(v) == 1 {\n")
bs.WriteString(fmt.Sprintf("m[\"%s\"] = v[0]\n", t.Name))
bs.WriteString("} else {\n")
bs.WriteString(fmt.Sprintf("m[\"%s\"] = v\n", t.Name))
bs.WriteString("}\n")
bs.WriteString("} else if err != nil {\n")
bs.WriteString("return m, err\n")
bs.WriteString("}\n")
bs.WriteString("// End generation by generateNonFunctionalMultiTypeDefinition\n")
s = bs.String()
generateUnknownFunctions(t, this, i, thisIntermed, intermed)
return
}
type intermedDef struct {
Name string
S *defs.StructDef
F []*defs.FunctionDef
}
func generateIntermediateTypeDefinition(types []*defs.PropertyType) (d *intermedDef) {
t := types[0]
d = &intermedDef{}
d.Name = fmt.Sprintf("%sIntermediateType", cleanName(t.Name))
d.S = &defs.StructDef{
Typename: d.Name,
Comment: fmt.Sprintf("%sIntermediateType will only have one of its values set at most", cleanName(t.Name)),
M: []*defs.StructMember{{"unknown_", "interface{}", "An unknown value."}},
}
d.S.F = []*defs.MemberFunctionDef{
{
Name: "Deserialize",
Comment: "Deserialize takes an interface{} and attempts to create a valid intermediate type.",
P: d.S,
Args: []*defs.FunctionVarDef{{"i", "interface{}"}},
Return: []*defs.FunctionVarDef{{"err", "error"}},
Body: func() string {
bHasType := false
for _, t := range types {
for _, r := range t.Range {
if r.T != nil {
bHasType = true
break
}
}
}
var b bytes.Buffer
b.WriteString("matched := false\n")
b.WriteString("if m, ok := i.(map[string]interface{}); ok {\n")
if bHasType {
b.WriteString("if tv, ok := m[\"type\"]; ok {\n")
b.WriteString("var types []string\n")
b.WriteString("if tvs, ok := tv.([]interface{}); ok {\n")
b.WriteString("for _, tvi := range tvs {\n")
b.WriteString("if typeString, ok := tvi.(string); ok {\n")
b.WriteString("types = append(types, typeString)\n")
b.WriteString("}\n")
b.WriteString("}\n")
b.WriteString("} else if typeString, ok := tv.(string); ok {\n")
b.WriteString("types = append(types, typeString)\n")
b.WriteString("}\n")
alreadyMember := make(map[string]bool)
for _, t := range types {
for _, r := range t.Range {
kind := cleanName(Name(r))
if alreadyMember[kind] {
continue
}
alreadyMember[kind] = true
if r.T != nil {
var resolve string
if isALinkType(r.T) {
resolve = resolveLinkName
} else if isAnObjectType(r.T) {
resolve = resolveObjectName
} else {
panic("Unknown resolution function: not object and not link")
}
b.WriteString("if !matched {\n")
b.WriteString("for _, kind := range types {\n")
b.WriteString(fmt.Sprintf("if t.%s, ok = %s(kind).(%sType); t.%s != nil && ok {\n", cleanName(Name(r)), resolve, Name(r), cleanName(Name(r))))
b.WriteString(fmt.Sprintf("err = t.%s.Deserialize(m)\n", cleanName(Name(r))))
b.WriteString("matched = true\n")
b.WriteString("break\n")
b.WriteString("}\n")
b.WriteString("}\n")
b.WriteString("}\n")
}
}
}
b.WriteString("} else {\n")
b.WriteString("t.unknown_ = m\n")
b.WriteString("}\n")
} else {
b.WriteString("err = fmt.Errorf(\"Given map but nothing to do with it for this type: %v\", m)")
}
b.WriteString("} else if i != nil {\n")
alreadyMember := make(map[string]bool)
for _, t := range types {
for _, r := range t.Range {
kind := cleanName(Name(r))
if alreadyMember[kind] {
continue
}
alreadyMember[kind] = true
if r.V != nil {
b.WriteString("if !matched {\n")
b.WriteString(fmt.Sprintf("t.%s, err = %s(i)\n", cleanName(Name(r)), r.V.DeserializeFn.Name))
b.WriteString("if err != nil {\n")
b.WriteString(fmt.Sprintf("t.%s = nil\n", cleanName(Name(r))))
b.WriteString("} else {\n")
b.WriteString("matched = true\n")
b.WriteString("}\n")
b.WriteString("}\n")
}
}
}
b.WriteString("}\n")
b.WriteString("if !matched {\n")
b.WriteString(fmt.Sprintf("t.unknown_ = %s(i)\n", unknownValueDeserializeFnName))
b.WriteString("}\n")
b.WriteString("return\n")
return b.String()
},
},
{
Name: "Serialize",
Comment: "Serialize turns this object into an interface{}.",
P: d.S,
Return: []*defs.FunctionVarDef{{"i", "interface{}"}, {"err", "error"}},
Body: func() string {
var b bytes.Buffer
alreadyMember := make(map[string]bool)
for _, t := range types {
for _, r := range t.Range {
kind := cleanName(Name(r))
if alreadyMember[kind] {
continue
}
alreadyMember[kind] = true
isIRI := isIRIType(Type(r))
deref := "*"
if isIRI {
deref = ""
}
b.WriteString(fmt.Sprintf("if t.%s != nil {\n", cleanName(Name(r))))
if r.T != nil {
b.WriteString(fmt.Sprintf("i, err = t.%s.Serialize()\n", cleanName(Name(r))))
b.WriteString("return\n")
} else if r.V != nil {
b.WriteString(fmt.Sprintf("i = %s(%st.%s)\n", r.V.SerializeFn.Name, deref, cleanName(Name(r))))
b.WriteString("return\n")
} else {
b.WriteString(fmt.Sprintf("i = t.%s\n", cleanName(Name(r))))
b.WriteString("return\n")
}
b.WriteString("}\n")
}
}
b.WriteString(fmt.Sprintf("i = %s(t.unknown_)\n", unknownValueSerializeFnName))
b.WriteString("return")
return b.String()
},
},
}
d.F = append(d.F, []*defs.FunctionDef{
{
Name: fmt.Sprintf("deserialize%s", strings.Title(d.S.Typename)),
Comment: fmt.Sprintf("deserialize%s will accept a map to create a %s", d.S.Typename, d.S.Typename),
Args: []*defs.FunctionVarDef{{"in", "interface{}"}},
Return: []*defs.FunctionVarDef{{"t", "*" + d.S.Typename}, {"err", "error"}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("tmp := &%s{}\n", d.S.Typename))
b.WriteString("err = tmp.Deserialize(in)\n")
b.WriteString("return tmp, err\n")
return b.String()
},
},
{
Name: fmt.Sprintf("deserializeSlice%s", strings.Title(d.S.Typename)),
Comment: fmt.Sprintf("deserializeSlice %s will accept a slice to create a slice of %s", d.S.Typename, d.S.Typename),
Args: []*defs.FunctionVarDef{{"in", "[]interface{}"}},
Return: []*defs.FunctionVarDef{{"t", "[]*" + d.S.Typename}, {"err", "error"}},
Body: func() string {
var b bytes.Buffer
b.WriteString("for _, i := range in {\n")
b.WriteString(fmt.Sprintf("tmp := &%s{}\n", d.S.Typename))
b.WriteString("err = tmp.Deserialize(i)\n")
b.WriteString("if err != nil {\nreturn\n}\n")
b.WriteString("t = append(t, tmp)\n")
b.WriteString("}\n")
b.WriteString("return\n")
return b.String()
},
},
{
Name: fmt.Sprintf("serialize%s", strings.Title(d.S.Typename)),
Comment: fmt.Sprintf("serialize%s will accept a %s to create a map", d.S.Typename, d.S.Typename),
Args: []*defs.FunctionVarDef{{"t", "*" + d.S.Typename}},
Return: []*defs.FunctionVarDef{{"i", "interface{}"}, {"err", "error"}},
Body: func() string {
var b bytes.Buffer
b.WriteString("i, err = t.Serialize()\n")
b.WriteString("return\n")
return b.String()
},
},
{
Name: fmt.Sprintf("serializeSlice%s", strings.Title(d.S.Typename)),
Comment: fmt.Sprintf("serializeSlice%s will accept a slice of %s to create a slice result", d.S.Typename, d.S.Typename),
Args: []*defs.FunctionVarDef{{"s", "[]*" + d.S.Typename}},
Return: []*defs.FunctionVarDef{{"out", "[]interface{}"}, {"err", "error"}},
Body: func() string {
var b bytes.Buffer
b.WriteString("for _, t := range s {\n")
b.WriteString("v, err := t.Serialize()\n")
b.WriteString("if err != nil {\nreturn nil, err\n}\n")
b.WriteString("out = append(out, v)\n")
b.WriteString("}\n")
b.WriteString("return\n")
return b.String()
},
},
}...)
alreadyMember := make(map[string]bool)
for _, t := range types {
for _, r := range t.Range {
kind := cleanName(Name(r))
if alreadyMember[kind] {
continue
}
alreadyMember[kind] = true
d.S.M = append(d.S.M, &defs.StructMember{
Name: kind,
Type: Type(r),
Comment: fmt.Sprintf("Stores possible %s type for %s property", Type(r), t.Name),
})
}
}
return
}
func generateUnknownFunctions(t *defs.PropertyType, this *defs.StructDef, i *defs.InterfaceDef, thisIntermed *defs.StructMember, intermed *defs.StructDef) {
titleName := strings.Title(t.Name)
this.F = append(this.F, []*defs.MemberFunctionDef{
{
Name: fmt.Sprintf("HasUnknown%s", titleName),
Comment: fmt.Sprintf("HasUnknown%s determines whether the call to GetUnknown%s is safe", titleName, titleName),
P: this,
Return: []*defs.FunctionVarDef{{"ok", "bool"}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("return t.%s != nil && t.%s", thisIntermed.Name, thisIntermed.Name))
if !t.Functional {
b.WriteString("[0]")
}
b.WriteString(".unknown_ != nil\n")
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("GetUnknown%s", titleName),
Comment: fmt.Sprintf("GetUnknown%s returns the unknown value for %s", titleName, t.Name),
P: this,
Return: []*defs.FunctionVarDef{{"v", "interface{}"}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("return t.%s", thisIntermed.Name))
if !t.Functional {
b.WriteString("[0]")
}
b.WriteString(".unknown_\n")
return b.String()
},
}, &defs.MemberFunctionDef{
Name: fmt.Sprintf("SetUnknown%s", titleName),
Comment: fmt.Sprintf("SetUnknown%s sets the unknown value of %s", titleName, t.Name),
P: this,
Args: []*defs.FunctionVarDef{{"i", "interface{}"}},
Body: func() string {
var b bytes.Buffer
b.WriteString("if t.unknown_ == nil {\n")
b.WriteString("t.unknown_ = make(map[string]interface{})")
b.WriteString("}\n")
b.WriteString(fmt.Sprintf("tmp := &%s{}\n", intermed.Typename))
b.WriteString("tmp.unknown_ = i\n")
b.WriteString(fmt.Sprintf("t.%s = ", thisIntermed.Name))
if t.Functional {
b.WriteString("tmp\n")
} else {
b.WriteString(fmt.Sprintf("append(t.%s, tmp)\n", thisIntermed.Name))
}
return b.String()
},
},
}...)
i.F = append(i.F, []*defs.FunctionDef{
{
Name: fmt.Sprintf("HasUnknown%s", titleName),
Comment: fmt.Sprintf("HasUnknown%s determines whether the call to GetUnknown%s is safe", titleName, titleName),
Return: []*defs.FunctionVarDef{{"ok", "bool"}},
},
{
Name: fmt.Sprintf("GetUnknown%s", titleName),
Comment: fmt.Sprintf("GetUnknown%s returns the unknown value for %s", titleName, t.Name),
Return: []*defs.FunctionVarDef{{"v", "interface{}"}},
},
{
Name: fmt.Sprintf("SetUnknown%s", titleName),
Comment: fmt.Sprintf("SetUnknown%s sets the unknown value of %s", titleName, t.Name),
Args: []*defs.FunctionVarDef{{"i", "interface{}"}},
},
}...)
}
func isSingleType(t *defs.PropertyType) bool {
return len(t.Range) == 1
}
func isAny(t *defs.PropertyType) bool {
for _, r := range t.Range {
if r.Any {
return true
}
}
return false
}