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) }