234 lines
5.1 KiB
Go
234 lines
5.1 KiB
Go
package df
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/iancoleman/strcase"
|
|
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
|
|
)
|
|
|
|
func Generate() error {
|
|
a, err := LoadAnalyzeData()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
m, err := createMetadata(a)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return generateCode(m)
|
|
}
|
|
|
|
var allowedTyped = map[string]bool{
|
|
"df_world|historical_events|historical_event": true,
|
|
"df_world|historical_event_collections|historical_event_collection": true,
|
|
}
|
|
|
|
func typeName(k string) string {
|
|
if strings.Contains(k, PATH_SEPARATOR) {
|
|
return k[strings.LastIndex(k, PATH_SEPARATOR)+1:]
|
|
}
|
|
return k
|
|
}
|
|
|
|
type Metadata map[string]Object
|
|
|
|
func createMetadata(a *AnalyzeData) (*Metadata, error) {
|
|
fs := filterSubtypes(&a.Fields)
|
|
|
|
// unique type names
|
|
names := make(map[string]bool)
|
|
for k := range a.Fields {
|
|
path := strings.Split(k, PATH_SEPARATOR)
|
|
if len(path) >= 2 {
|
|
names[strings.Join(path[:len(path)-1], PATH_SEPARATOR)] = true
|
|
}
|
|
}
|
|
objectTypes := util.Keys(names)
|
|
|
|
objects := make(Metadata, 0)
|
|
names = make(map[string]bool)
|
|
double := make(map[string]bool)
|
|
typeNames := make(map[string]string)
|
|
|
|
// check object type names
|
|
for _, k := range objectTypes {
|
|
n := typeName(k)
|
|
if _, ok := names[n]; ok {
|
|
double[n] = true
|
|
}
|
|
names[n] = true
|
|
}
|
|
|
|
for _, k := range objectTypes {
|
|
typeNames[k] = strcase.ToCamel(typeName(k))
|
|
}
|
|
for _, n := range util.Keys(double) {
|
|
fmt.Println(n)
|
|
for _, k := range objectTypes {
|
|
if strings.HasSuffix(k, PATH_SEPARATOR+n) {
|
|
fmt.Println(" ", k)
|
|
path := strings.Split(k, PATH_SEPARATOR)
|
|
for i := len(path) - 1; i > 0; i-- {
|
|
sub := strings.Join(path[:i], PATH_SEPARATOR)
|
|
if ok, _ := isArray(sub, fs); !ok {
|
|
typeNames[k] = strcase.ToCamel(typeName(sub) + "_" + typeName(k))
|
|
fmt.Println(" ", typeNames[k])
|
|
break
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
// build metadata
|
|
for _, k := range objectTypes {
|
|
if ok, _ := isArray(k, fs); !ok {
|
|
n := typeName(k)
|
|
|
|
if n == "" {
|
|
continue
|
|
}
|
|
|
|
objFields := make(map[string]Field, 0)
|
|
|
|
for _, f := range fs {
|
|
if strings.HasPrefix(f, k+PATH_SEPARATOR) {
|
|
fn := f[len(k)+1:]
|
|
if !strings.Contains(fn, PATH_SEPARATOR) {
|
|
legend := ""
|
|
if a.Fields[f].Base && a.Fields[f].Plus {
|
|
legend = "both"
|
|
} else if a.Fields[f].Base {
|
|
legend = "base"
|
|
} else if a.Fields[f].Plus {
|
|
legend = "plus"
|
|
}
|
|
|
|
field := Field{
|
|
Name: strcase.ToCamel(fn),
|
|
Type: "int",
|
|
Multiple: a.Fields[f].Multiple,
|
|
Legend: legend,
|
|
Base: a.Fields[f].Base,
|
|
Plus: a.Fields[f].Plus,
|
|
}
|
|
if ok, elements := isArray(f, fs); ok {
|
|
el := typeNames[elements]
|
|
if _, ok := a.Fields[elements+PATH_SEPARATOR+"id"]; ok {
|
|
field.Type = "map"
|
|
} else {
|
|
field.Type = "array"
|
|
}
|
|
field.ElementType = &(el)
|
|
} else if ok, _ := isObject(f, fs); ok {
|
|
field.Type = "object"
|
|
el := typeNames[f]
|
|
field.ElementType = &el
|
|
} else if a.Fields[f].IsString {
|
|
field.Type = "string"
|
|
}
|
|
objFields[fn] = field
|
|
}
|
|
}
|
|
}
|
|
|
|
objects[typeNames[k]] = Object{
|
|
Name: typeNames[k],
|
|
Id: a.Fields[k+PATH_SEPARATOR+"id"] != nil,
|
|
Named: a.Fields[k+PATH_SEPARATOR+"name"] != nil,
|
|
Typed: a.Fields[k+PATH_SEPARATOR+"type"] != nil,
|
|
SubTypes: getSubtypes(a, k),
|
|
SubTypeOf: getSubtypeOf(k),
|
|
Fields: objFields,
|
|
}
|
|
}
|
|
}
|
|
|
|
return &objects, nil
|
|
}
|
|
|
|
func filterSubtypes(data *map[string]*FieldData) []string {
|
|
filtered := make(map[string]*FieldData)
|
|
for k, v := range *data {
|
|
path := strings.Split(k, PATH_SEPARATOR)
|
|
for index, seg := range path {
|
|
if strings.Contains(seg, "+") {
|
|
base := seg[:strings.Index(seg, "+")]
|
|
basePath := strings.Join(append(path[:index], base), PATH_SEPARATOR)
|
|
if allowedTyped[basePath] {
|
|
path[index] = seg
|
|
}
|
|
}
|
|
}
|
|
filtered[strings.Join(path, PATH_SEPARATOR)] = v
|
|
}
|
|
*data = filtered
|
|
list := util.Keys(filtered)
|
|
sort.Strings(list)
|
|
return list
|
|
}
|
|
|
|
func getSubtypes(a *AnalyzeData, k string) *[]Subtype {
|
|
if allowedTyped[k] {
|
|
if st, ok := a.SubTypes[k]; ok {
|
|
var list []Subtype
|
|
for _, v := range *st {
|
|
list = append(list, *v)
|
|
}
|
|
return &list
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func getSubtypeOf(k string) *string {
|
|
if strings.Contains(k, PATH_SEPARATOR) {
|
|
last := k[strings.LastIndex(k, PATH_SEPARATOR)+1:]
|
|
if strings.Contains(last, "+") {
|
|
base := strcase.ToCamel(last[:strings.Index(last, "+")])
|
|
return &base
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func isArray(typ string, types []string) (bool, string) {
|
|
fc := 0
|
|
elements := ""
|
|
|
|
if !strings.Contains(typ, PATH_SEPARATOR) || strings.Contains(typ[strings.LastIndex(typ, PATH_SEPARATOR):], "+") {
|
|
return false, ""
|
|
}
|
|
|
|
for _, t := range types {
|
|
if !strings.HasPrefix(t, typ+PATH_SEPARATOR) {
|
|
continue
|
|
}
|
|
if strings.Contains(t[len(typ)+1:], PATH_SEPARATOR) {
|
|
continue
|
|
}
|
|
fc++
|
|
elements = t
|
|
}
|
|
return fc == 1, elements
|
|
}
|
|
|
|
func isObject(typ string, types []string) (bool, string) {
|
|
fc := 0
|
|
|
|
for _, t := range types {
|
|
if !strings.HasPrefix(t, typ+PATH_SEPARATOR) {
|
|
continue
|
|
}
|
|
fc++
|
|
}
|
|
return fc > 0, typ
|
|
}
|