214 lines
4.3 KiB
Go
214 lines
4.3 KiB
Go
package f5
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"q5"
|
|
"reflect"
|
|
)
|
|
|
|
type MetaTable interface {
|
|
IsNoLoad() bool
|
|
Load()
|
|
PreInit1()
|
|
ElementsInit(int)
|
|
PostInit1()
|
|
}
|
|
|
|
type LoadFromKeyValue interface {
|
|
LoadFromKv(map[string]interface{})
|
|
}
|
|
|
|
type RawMetaTable[T any] struct {
|
|
FileName string
|
|
PrimKey string
|
|
NoLoad bool
|
|
rawList []*T
|
|
}
|
|
|
|
type IdMetaTable[T any] struct {
|
|
RawMetaTable[T]
|
|
idHash map[int64]*T
|
|
}
|
|
|
|
type NameMetaTable[T any] struct {
|
|
RawMetaTable[T]
|
|
nameHash map[string]*T
|
|
}
|
|
|
|
func (this *RawMetaTable[T]) Traverse(cb func(*T) bool) {
|
|
for _, val := range this.rawList {
|
|
if !cb(val) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func (this *RawMetaTable[T]) IsNoLoad() bool {
|
|
return this.NoLoad
|
|
}
|
|
|
|
func (this *RawMetaTable[T]) PreInit1() {
|
|
}
|
|
|
|
func (this *RawMetaTable[T]) PostInit1() {
|
|
}
|
|
|
|
func (this *RawMetaTable[T]) ElementsInit(round int) {
|
|
type RoundInit1 interface {
|
|
Init1()
|
|
}
|
|
type RoundInit2 interface {
|
|
Init2()
|
|
}
|
|
type RoundInit3 interface {
|
|
Init3()
|
|
}
|
|
this.Traverse(func(obj *T) bool {
|
|
var x interface{} = obj
|
|
switch round {
|
|
case 0:
|
|
if init, ok := x.(RoundInit1); ok {
|
|
init.Init1()
|
|
}
|
|
case 1:
|
|
if init, ok := x.(RoundInit2); ok {
|
|
init.Init2()
|
|
}
|
|
case 2:
|
|
if init, ok := x.(RoundInit3); ok {
|
|
init.Init3()
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
}
|
|
|
|
func (this *IdMetaTable[T]) GetById(id int64) *T {
|
|
if v, ok := this.idHash[id]; ok {
|
|
return v
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (this *RawMetaTable[T]) Load() {
|
|
if this.NoLoad {
|
|
return
|
|
}
|
|
if f, err := os.Open(this.FileName); err == nil {
|
|
jsonStr, _ := bufio.NewReader(f).ReadString(0)
|
|
switch q5.JsonStrType(jsonStr) {
|
|
case q5.JSON_ARRAY:
|
|
break
|
|
case q5.JSON_OBJECT:
|
|
jsonStr = "[" + jsonStr + "]"
|
|
default:
|
|
panic(fmt.Sprintf("error json format %s", this.FileName))
|
|
}
|
|
var rows []map[string]interface{}
|
|
json.Unmarshal([]byte(jsonStr), &rows)
|
|
for _, row := range rows {
|
|
var obj = new(T)
|
|
var x interface{} = obj
|
|
if loader, ok := x.(LoadFromKeyValue); ok {
|
|
loader.LoadFromKv(row)
|
|
}
|
|
this.rawList = append(this.rawList, obj)
|
|
}
|
|
} else {
|
|
panic(fmt.Sprintf("load metafile error %s %s", this.FileName, err))
|
|
}
|
|
}
|
|
|
|
func (this *IdMetaTable[T]) Load() {
|
|
this.RawMetaTable.Load()
|
|
this.idHash = make(map[int64]*T)
|
|
i := int64(0)
|
|
getFuncName := "Get" + q5.ConvertUpperCamelCase(this.PrimKey)
|
|
this.Traverse(func(obj *T) bool {
|
|
if this.PrimKey == "" {
|
|
this.idHash[i] = obj
|
|
} else {
|
|
in := []reflect.Value{}
|
|
method := reflect.ValueOf(obj).MethodByName(getFuncName)
|
|
out := method.Call(in)
|
|
if key, err := q5.ToInt64Ex(out[0].Interface()); err == nil {
|
|
this.idHash[key] = obj
|
|
} else {
|
|
panic("IdMetaTable load PrimKey error")
|
|
}
|
|
}
|
|
i++
|
|
return true
|
|
})
|
|
}
|
|
|
|
func (this *NameMetaTable[T]) GetByName(name string) *T {
|
|
if v, ok := this.nameHash[name]; ok {
|
|
return v
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (this *NameMetaTable[T]) Load() {
|
|
this.RawMetaTable.Load()
|
|
this.nameHash = make(map[string]*T)
|
|
i := int64(0)
|
|
getFuncName := "Get" + q5.ConvertUpperCamelCase(this.PrimKey)
|
|
this.Traverse(func(obj *T) bool {
|
|
in := []reflect.Value{}
|
|
method := reflect.ValueOf(obj).MethodByName(getFuncName)
|
|
out := method.Call(in)
|
|
if key, err := q5.ToStringEx(out[0].Interface()); err == nil {
|
|
this.nameHash[key] = obj
|
|
} else {
|
|
panic("NameMetaTable load PrimKey error")
|
|
}
|
|
i++
|
|
return true
|
|
})
|
|
}
|
|
|
|
func ReadMetaTableField[T string | int | int32 | int64 | float32 | float64](
|
|
fieldPtr *T, fieldName string, flags *uint64, flagIdx uint64,
|
|
kv map[string]interface{}) {
|
|
if val, ok := kv[fieldName]; ok {
|
|
if !q5.DuckToSimple(val, fieldPtr) {
|
|
panic("ReadMetaTableField error")
|
|
}
|
|
*flags |= uint64(1) << flagIdx
|
|
}
|
|
}
|
|
|
|
func LoadMetaTable(table interface{}) {
|
|
ele := reflect.ValueOf(table).Elem()
|
|
for i := 0; i < ele.NumField(); i++ {
|
|
var tbl MetaTable = ele.Field(i).Interface().(MetaTable)
|
|
if !tbl.IsNoLoad() {
|
|
tbl.PreInit1()
|
|
}
|
|
}
|
|
for i := 0; i < ele.NumField(); i++ {
|
|
var tbl MetaTable = ele.Field(i).Interface().(MetaTable)
|
|
if !tbl.IsNoLoad() {
|
|
tbl.Load()
|
|
}
|
|
}
|
|
for i := 0; i < 3; i++ {
|
|
for ii := 0; ii < ele.NumField(); ii++ {
|
|
var tbl MetaTable = ele.Field(ii).Interface().(MetaTable)
|
|
tbl.ElementsInit(i)
|
|
}
|
|
}
|
|
for i := 0; i < ele.NumField(); i++ {
|
|
var tbl MetaTable = ele.Field(i).Interface().(MetaTable)
|
|
if !tbl.IsNoLoad() {
|
|
tbl.PostInit1()
|
|
}
|
|
}
|
|
}
|