Files
b2b/app/utils/reflect/reflect.go
2026-03-18 11:39:18 +01:00

91 lines
2.4 KiB
Go

package reflect
import (
"fmt"
"reflect"
"regexp"
"strings"
"git.ma-al.com/goc_daniel/b2b/app/db"
)
// TODO: instead of matching with string.Contains use something less error-prone
func checkIfContainsJSON(i int, t reflect.Type, name string) string {
if wholeTag, ok := t.Field(i).Tag.Lookup("json"); ok {
tags := strings.Split(wholeTag, ",")
for _, tag := range tags {
if name == strings.TrimSpace(tag) {
return db.DB.NamingStrategy.ColumnName(t.Name(), t.Field(i).Name)
}
}
}
return ""
}
// Not tail recursive but should do fine. Goes only as deep as the hierarchy of
// inlined structs.
// TODO: improve used internally checkIfContainsJSON
func GetGormColumnFromJsonField(jsonName string, t reflect.Type) (string, error) {
var res string
for i := range make([]bool, t.NumField()) {
if tag, ok := t.Field(i).Tag.Lookup("json"); ok && strings.Contains(tag, "inline") {
var err error
res, err = GetGormColumnFromJsonField(jsonName, t.Field(i).Type)
if err != nil {
return "", fmt.Errorf("no field of struct %q has a name %q in its json form", t.Name(), jsonName)
}
} else {
res = checkIfContainsJSON(i, t, jsonName)
}
if res != "" {
return res, nil
}
}
return "", fmt.Errorf("no field of struct %q has a name %q in its json form", t.Name(), jsonName)
}
func GetTableName[T any]() string {
var model T
typ := reflect.TypeOf(model).Name()
return db.DB.NamingStrategy.TableName(typ)
}
func GetParamFromFieldTag[T any](object T, fieldname string, tagname string, paramname string) string {
if table, ok := reflect.TypeOf(object).FieldByName(fieldname); ok {
if t, ok := table.Tag.Lookup(tagname); ok {
if paramname == "" {
return t
}
re := regexp.MustCompile(`(?m)` + paramname + `:(\w*)`)
f := re.FindAllStringSubmatch(t, -1)
if len(re.FindAllStringSubmatch(t, -1)) > 0 {
return f[0][1]
}
}
}
return ""
}
func GetPrimaryKey[T any](item T) string {
var search func(T) string = func(item T) string {
val := reflect.ValueOf(item)
typ := reflect.TypeOf(item)
for i := 0; i < val.NumField(); i++ {
if gg, ok := typ.Field(i).Tag.Lookup("gorm"); ok {
xx := strings.Split(gg, ";")
for _, t := range xx {
if strings.HasPrefix(strings.ToLower(t), "primarykey") {
return db.DB.NamingStrategy.TableName(typ.Field(i).Name)
}
}
}
if val.Field(i).Type().String() == "db.Model" {
return db.DB.NamingStrategy.TableName("ID")
}
}
return ""
}
return search(item)
}