2018-01-24 08:00:59 +09:00
package gen
import (
"bytes"
"fmt"
"github.com/go-fed/activity/tools/defs"
"strings"
)
2018-06-18 01:51:30 +09:00
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 ) {
2018-01-24 08:00:59 +09:00
if isAny ( t ) {
fd , sd , s , d = generateAnyDefinitions ( t , this , i )
} else if isSingleType ( t ) {
fd , sd , s , d = generateSingleTypeDefinitions ( t , this , i )
} else {
2018-06-18 01:51:30 +09:00
fd , sd , s , d = generateMultiTypeDefinitions ( t , this , i , m )
2018-01-24 08:00:59 +09:00
}
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" ,
2018-05-31 04:40:20 +09:00
Comment : fmt . Sprintf ( "The '%sMap' value holds language-specific values for property '%s'" , t . Name , t . Name ) ,
2018-01-24 08:00:59 +09:00
}
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 ) ) ,
2018-05-31 04:40:20 +09:00
Comment : fmt . Sprintf ( "Set%sMap sets the value of the property for the specified language" , strings . Title ( t . Name ) ) ,
2018-01-24 08:00:59 +09:00
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 ) ) ,
2018-05-31 04:40:20 +09:00
Comment : fmt . Sprintf ( "Set%sMap sets the value of the property for the specified language" , strings . Title ( t . Name ) ) ,
2018-01-24 08:00:59 +09:00
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 {
2018-05-28 00:07:40 +09:00
Name : fmt . Sprintf ( "Append%s" , titleName ) ,
Comment : fmt . Sprintf ( "Append%s adds a value to the back of %s" , titleName , t . Name ) ,
2018-01-24 08:00:59 +09:00
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 ( )
} ,
2018-05-28 00:07:40 +09:00
} , & 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 ( )
} ,
2018-01-24 08:00:59 +09:00
} , & 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 ) } } ,
} ,
{
2018-05-28 00:07:40 +09:00
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 ) ,
2018-01-24 08:00:59 +09:00
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 )
2018-05-30 04:57:39 +09:00
isIRI := isIRIType ( member . Type )
2018-01-24 08:00:59 +09:00
returnType := deref ( member . Type )
2018-05-30 04:57:39 +09:00
if isIRI {
returnType = member . Type
}
2018-01-24 08:00:59 +09:00
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 " ) )
2018-05-30 04:57:39 +09:00
if isPtrType && ! isIRI {
2018-01-24 08:00:59 +09:00
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 ) )
2018-05-30 04:57:39 +09:00
if isPtrType && ! isIRI {
2018-01-24 08:00:59 +09:00
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 ) {
2018-05-30 04:57:39 +09:00
isIRI := isIRIType ( Type ( t . Range [ 0 ] ) )
memberType := deref ( Type ( t . Range [ 0 ] ) )
returnType := memberType
if isIRI {
memberType = Type ( t . Range [ 0 ] )
returnType = memberType
}
2018-01-24 08:00:59 +09:00
member := & defs . StructMember {
Name : cleanName ( t . Name ) ,
2018-05-30 04:57:39 +09:00
Type : fmt . Sprintf ( "[]%s" , memberType ) ,
2018-01-24 08:00:59 +09:00
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" } } ,
2018-05-30 04:57:39 +09:00
Return : [ ] * defs . FunctionVarDef { { "v" , returnType } } ,
2018-01-24 08:00:59 +09:00
Body : func ( ) string {
var b bytes . Buffer
b . WriteString ( fmt . Sprintf ( "return t.%s[index]\n" , member . Name ) )
return b . String ( )
} ,
} , & defs . MemberFunctionDef {
2018-05-28 00:07:40 +09:00
Name : fmt . Sprintf ( "Append%s" , titleName ) ,
Comment : fmt . Sprintf ( "Append%s adds a value to the back of %s" , titleName , t . Name ) ,
2018-01-24 08:00:59 +09:00
P : this ,
2018-05-30 04:57:39 +09:00
Args : [ ] * defs . FunctionVarDef { { "v" , returnType } } ,
2018-01-24 08:00:59 +09:00
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 ( )
} ,
2018-05-28 00:07:40 +09:00
} , & 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 ,
2018-05-30 04:57:39 +09:00
Args : [ ] * defs . FunctionVarDef { { "v" , returnType } } ,
2018-05-28 00:07:40 +09:00
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 ( )
} ,
2018-01-24 08:00:59 +09:00
} , & 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" } } ,
2018-05-30 04:57:39 +09:00
Return : [ ] * defs . FunctionVarDef { { "v" , returnType } } ,
2018-01-24 08:00:59 +09:00
} ,
{
2018-05-28 00:07:40 +09:00
Name : fmt . Sprintf ( "Append%s" , titleName ) ,
Comment : fmt . Sprintf ( "Append%s adds a value to the back of %s" , titleName , t . Name ) ,
2018-05-30 04:57:39 +09:00
Args : [ ] * defs . FunctionVarDef { { "v" , returnType } } ,
2018-05-28 00:07:40 +09:00
} ,
{
Name : fmt . Sprintf ( "Prepend%s" , titleName ) ,
Comment : fmt . Sprintf ( "Prepend%s adds a value to the front of %s" , titleName , t . Name ) ,
2018-05-30 04:57:39 +09:00
Args : [ ] * defs . FunctionVarDef { { "v" , returnType } } ,
2018-01-24 08:00:59 +09:00
} ,
{
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
}
2018-06-18 01:51:30 +09:00
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 ) {
2018-01-24 08:00:59 +09:00
if t . Functional {
2018-06-18 01:51:30 +09:00
return generateFunctionalMultiTypeDefinition ( t , this , i , m )
2018-01-24 08:00:59 +09:00
} else {
2018-06-18 01:51:30 +09:00
return generateNonFunctionalMultiTypeDefinition ( t , this , i , m )
2018-01-24 08:00:59 +09:00
}
}
2018-06-18 01:51:30 +09:00
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 ) {
2018-01-24 08:00:59 +09:00
titleName := strings . Title ( t . Name )
2018-06-18 01:51:30 +09:00
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
}
}
2018-01-24 08:00:59 +09:00
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
2018-06-18 01:51:30 +09:00
memberName := cleanName ( Name ( r ) )
memberType := Type ( r )
isIRI := isIRIType ( memberType )
retKind := deref ( memberType )
2018-05-30 04:57:39 +09:00
if isIRI {
2018-06-18 01:51:30 +09:00
retKind = memberType
2018-05-30 04:57:39 +09:00
}
2018-01-24 08:00:59 +09:00
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 {
2018-06-18 01:51:30 +09:00
return fmt . Sprintf ( "return t.%s != nil && t.%s.%s != nil\n" , thisIntermed . Name , thisIntermed . Name , memberName )
2018-01-24 08:00:59 +09:00
} ,
} ,
{
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 " )
2018-05-30 04:57:39 +09:00
if isPtrType ( Type ( r ) ) && ! isIRI {
2018-01-24 08:00:59 +09:00
b . WriteString ( "*" )
}
2018-06-18 01:51:30 +09:00
b . WriteString ( fmt . Sprintf ( "t.%s.%s\n" , thisIntermed . Name , memberName ) )
2018-01-24 08:00:59 +09:00
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
2018-06-18 01:51:30 +09:00
b . WriteString ( fmt . Sprintf ( "t.%s = &%s{%s:" , thisIntermed . Name , intermed . Typename , memberName ) )
2018-05-30 04:57:39 +09:00
if isPtrType ( Type ( r ) ) && ! isIRI {
2018-01-24 08:00:59 +09:00
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 , thisIntermed , intermed )
return
}
2018-06-18 01:51:30 +09:00
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 ) {
2018-01-24 08:00:59 +09:00
titleName := strings . Title ( t . Name )
2018-06-18 01:51:30 +09:00
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
}
}
2018-01-24 08:00:59 +09:00
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
2018-06-18 01:51:30 +09:00
memberName := cleanName ( Name ( r ) )
memberType := Type ( r )
isIRI := isIRIType ( memberType )
retKind := deref ( memberType )
2018-05-30 04:57:39 +09:00
if isIRI {
2018-06-18 01:51:30 +09:00
retKind = memberType
2018-05-30 04:57:39 +09:00
}
2018-01-24 08:00:59 +09:00
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 {
2018-06-18 01:51:30 +09:00
return fmt . Sprintf ( "return t.%s[index].%s != nil\n" , thisIntermed . Name , memberName )
2018-01-24 08:00:59 +09:00
} ,
} ,
{
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 " )
2018-05-30 04:57:39 +09:00
if isPtrType ( Type ( r ) ) && ! isIRI {
2018-01-24 08:00:59 +09:00
b . WriteString ( "*" )
}
2018-06-18 01:51:30 +09:00
b . WriteString ( fmt . Sprintf ( "t.%s[index].%s\n" , thisIntermed . Name , memberName ) )
2018-01-24 08:00:59 +09:00
return b . String ( )
} ,
} ,
{
2018-05-28 00:07:40 +09:00
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 ) ,
2018-01-24 08:00:59 +09:00
P : this ,
Args : [ ] * defs . FunctionVarDef { { "v" , retKind } } ,
Body : func ( ) string {
var b bytes . Buffer
2018-06-18 01:51:30 +09:00
b . WriteString ( fmt . Sprintf ( "t.%s = append(t.%s, &%s{%s:" , thisIntermed . Name , thisIntermed . Name , intermed . Typename , memberName ) )
2018-05-30 04:57:39 +09:00
if isPtrType ( Type ( r ) ) && ! isIRI {
2018-01-24 08:00:59 +09:00
b . WriteString ( "&" )
}
b . WriteString ( "v})\n" )
return b . String ( )
} ,
} ,
2018-05-28 00:07:40 +09:00
{
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
2018-06-18 01:51:30 +09:00
b . WriteString ( fmt . Sprintf ( "t.%s = append([]*%s{&%s{%s:" , thisIntermed . Name , intermed . Typename , intermed . Typename , memberName ) )
2018-05-30 04:57:39 +09:00
if isPtrType ( Type ( r ) ) && ! isIRI {
2018-05-28 00:07:40 +09:00
b . WriteString ( "&" )
}
b . WriteString ( fmt . Sprintf ( "v}}, t.%s...)\n" , thisIntermed . Name ) )
return b . String ( )
} ,
} ,
2018-01-24 08:00:59 +09:00
{
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 } } ,
} ,
{
2018-05-28 00:07:40 +09:00
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 ) ,
2018-01-24 08:00:59 +09:00
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 , thisIntermed , intermed )
return
}
2018-06-18 01:51:30 +09:00
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 ) ) ,
2018-01-24 08:00:59 +09:00
M : [ ] * defs . StructMember { { "unknown_" , "interface{}" , "An unknown value." } } ,
}
2018-06-18 01:51:30 +09:00
d . S . F = [ ] * defs . MemberFunctionDef {
2018-01-24 08:00:59 +09:00
{
Name : "Deserialize" ,
Comment : "Deserialize takes an interface{} and attempts to create a valid intermediate type." ,
2018-06-18 01:51:30 +09:00
P : d . S ,
2018-01-24 08:00:59 +09:00
Args : [ ] * defs . FunctionVarDef { { "i" , "interface{}" } } ,
Return : [ ] * defs . FunctionVarDef { { "err" , "error" } } ,
Body : func ( ) string {
bHasType := false
2018-06-18 01:51:30 +09:00
for _ , t := range types {
for _ , r := range t . Range {
if r . T != nil {
bHasType = true
break
}
2018-01-24 08:00:59 +09:00
}
}
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" )
2018-06-18 01:51:30 +09:00
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" )
2018-01-24 08:00:59 +09:00
}
}
}
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)" )
}
2018-04-28 23:22:17 +09:00
b . WriteString ( "} else if i != nil {\n" )
2018-06-18 01:51:30 +09:00
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" )
}
2018-01-24 08:00:59 +09:00
}
}
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{}." ,
2018-06-18 01:51:30 +09:00
P : d . S ,
2018-01-24 08:00:59 +09:00
Return : [ ] * defs . FunctionVarDef { { "i" , "interface{}" } , { "err" , "error" } } ,
Body : func ( ) string {
var b bytes . Buffer
2018-06-18 01:51:30 +09:00
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" )
2018-01-24 08:00:59 +09:00
}
}
b . WriteString ( fmt . Sprintf ( "i = %s(t.unknown_)\n" , unknownValueSerializeFnName ) )
b . WriteString ( "return" )
return b . String ( )
} ,
} ,
}
2018-06-18 01:51:30 +09:00
d . F = append ( d . F , [ ] * defs . FunctionDef {
2018-01-24 08:00:59 +09:00
{
2018-06-18 01:51:30 +09:00
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 ) ,
2018-01-24 08:00:59 +09:00
Args : [ ] * defs . FunctionVarDef { { "in" , "interface{}" } } ,
2018-06-18 01:51:30 +09:00
Return : [ ] * defs . FunctionVarDef { { "t" , "*" + d . S . Typename } , { "err" , "error" } } ,
2018-01-24 08:00:59 +09:00
Body : func ( ) string {
var b bytes . Buffer
2018-06-18 01:51:30 +09:00
b . WriteString ( fmt . Sprintf ( "tmp := &%s{}\n" , d . S . Typename ) )
2018-01-24 08:00:59 +09:00
b . WriteString ( "err = tmp.Deserialize(in)\n" )
b . WriteString ( "return tmp, err\n" )
return b . String ( )
} ,
} ,
{
2018-06-18 01:51:30 +09:00
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 ) ,
2018-01-24 08:00:59 +09:00
Args : [ ] * defs . FunctionVarDef { { "in" , "[]interface{}" } } ,
2018-06-18 01:51:30 +09:00
Return : [ ] * defs . FunctionVarDef { { "t" , "[]*" + d . S . Typename } , { "err" , "error" } } ,
2018-01-24 08:00:59 +09:00
Body : func ( ) string {
var b bytes . Buffer
b . WriteString ( "for _, i := range in {\n" )
2018-06-18 01:51:30 +09:00
b . WriteString ( fmt . Sprintf ( "tmp := &%s{}\n" , d . S . Typename ) )
2018-01-24 08:00:59 +09:00
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 ( )
} ,
} ,
{
2018-06-18 01:51:30 +09:00
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 } } ,
2018-01-24 08:00:59 +09:00
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 ( )
} ,
} ,
{
2018-06-18 01:51:30 +09:00
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 } } ,
2018-01-24 08:00:59 +09:00
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 ( )
} ,
} ,
} ... )
2018-06-18 01:51:30 +09:00
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 ) ,
} )
}
}
2018-01-24 08:00:59 +09:00
return
}
func generateUnknownFunctions ( t * defs . PropertyType , this * defs . StructDef , 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 ( )
} ,
} ,
} ... )
}
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
}