1
This commit is contained in:
parent
0cea567175
commit
6c4d17e4fe
2
go.mod
2
go.mod
@ -1,6 +1,6 @@
|
|||||||
module f5
|
module f5
|
||||||
|
|
||||||
go 1.14
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golang/protobuf v1.4.2
|
github.com/golang/protobuf v1.4.2
|
||||||
|
316
metamgr.go
316
metamgr.go
@ -1,316 +0,0 @@
|
|||||||
package f5
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"bufio"
|
|
||||||
"strings"
|
|
||||||
"reflect"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"encoding/json"
|
|
||||||
"q5"
|
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
"github.com/golang/protobuf/jsonpb"
|
|
||||||
"google.golang.org/protobuf/reflect/protoreflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
type MetaClass struct {
|
|
||||||
FileName string
|
|
||||||
Idx int
|
|
||||||
RawMeta interface{}
|
|
||||||
WrapMeta interface{}
|
|
||||||
PrimKey string
|
|
||||||
SecKey string
|
|
||||||
eleMeta reflect.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
type MetaMgr struct {
|
|
||||||
metaClasses *[]MetaClass
|
|
||||||
rawList []interface{}
|
|
||||||
wrapList []interface{}
|
|
||||||
wrapIdHash []map[int64]interface{}
|
|
||||||
wrapNameHash []map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) Init() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) UnInit() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) RegisterMetaClasses(metaClasses *[]MetaClass) {
|
|
||||||
for i := 0; i < len(*metaClasses); i++ {
|
|
||||||
metaClass := &(*metaClasses)[i]
|
|
||||||
msgType := reflect.TypeOf(metaClass.RawMeta).Elem()
|
|
||||||
msg := reflect.New(msgType)
|
|
||||||
metaClass.eleMeta = reflect.TypeOf(msg.Elem().FieldByName("Values").Interface()).Elem().Elem()
|
|
||||||
if metaClass.eleMeta == nil {
|
|
||||||
panic(fmt.Sprintf(
|
|
||||||
"registerMetaClasses error not found Values field %s",
|
|
||||||
metaClass.FileName))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.metaClasses = metaClasses
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) Load() {
|
|
||||||
this.rawList = make([]interface{}, len(*this.metaClasses))
|
|
||||||
this.wrapList = make([]interface{}, len(*this.metaClasses))
|
|
||||||
this.wrapIdHash = make([]map[int64]interface{}, len(*this.metaClasses))
|
|
||||||
this.wrapNameHash = make([]map[string]interface{}, len(*this.metaClasses))
|
|
||||||
this.loadRawMetaTable()
|
|
||||||
this.bindPrimKey()
|
|
||||||
this.firstInitMetaList()
|
|
||||||
this.secondInitMetaList()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) loadRawMetaTable() {
|
|
||||||
for _, metaClass := range *this.metaClasses {
|
|
||||||
rawMeta, _ := this.loadJson(&metaClass)
|
|
||||||
values := rawMeta.Elem().FieldByName("Values")
|
|
||||||
wrapMetaType := reflect.TypeOf(metaClass.WrapMeta)
|
|
||||||
wrapMetaList := reflect.MakeSlice(reflect.SliceOf(wrapMetaType), 0, values.Len())
|
|
||||||
for i := 0; i < values.Len(); i++ {
|
|
||||||
val := values.Index(i)
|
|
||||||
|
|
||||||
wrapMeta := reflect.New(reflect.TypeOf(wrapMetaList.Interface()).Elem().Elem())
|
|
||||||
clsName := reflect.TypeOf(val.Elem().Interface()).Name()
|
|
||||||
clsField := wrapMeta.Elem().FieldByName(clsName)
|
|
||||||
clsField.Set(val)
|
|
||||||
|
|
||||||
wrapMetaList = reflect.Append(wrapMetaList, wrapMeta)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.rawList[metaClass.Idx] = rawMeta
|
|
||||||
this.wrapList[metaClass.Idx] = wrapMetaList.Interface()
|
|
||||||
this.wrapIdHash[metaClass.Idx] = map[int64]interface{}{}
|
|
||||||
this.wrapNameHash[metaClass.Idx] = map[string]interface{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) bindPrimKey() {
|
|
||||||
bindFunc := func (metaClass *MetaClass, wrapMeta reflect.Value) {
|
|
||||||
primVal := wrapMeta.Elem().FieldByName(metaClass.PrimKey)
|
|
||||||
secVal := wrapMeta.Elem().FieldByName(metaClass.SecKey)
|
|
||||||
nameHash := this.wrapNameHash[metaClass.Idx]
|
|
||||||
idHash := this.wrapIdHash[metaClass.Idx]
|
|
||||||
if fieldVal, ok := primVal.Interface().(*string); ok {
|
|
||||||
if _, ok := nameHash[*fieldVal]; ok {
|
|
||||||
panic(fmt.Sprintf(
|
|
||||||
"bindPrimKey duplicated key error %s %s",
|
|
||||||
metaClass.FileName,
|
|
||||||
*fieldVal))
|
|
||||||
}
|
|
||||||
nameHash[*fieldVal] = wrapMeta
|
|
||||||
} else if fieldVal, ok := primVal.Interface().(*int32); ok {
|
|
||||||
if metaClass.SecKey == "" {
|
|
||||||
if _, ok := idHash[int64(*fieldVal)]; ok {
|
|
||||||
panic(fmt.Sprintf(
|
|
||||||
"bindPrimKey duplicated key error %s %s",
|
|
||||||
metaClass.FileName,
|
|
||||||
*fieldVal))
|
|
||||||
}
|
|
||||||
idHash[int64(*fieldVal)] = wrapMeta.Interface()
|
|
||||||
} else {
|
|
||||||
if subFieldVal, ok := secVal.Interface().(*int32); ok {
|
|
||||||
if _, ok := idHash[q5.MkInt64(*fieldVal, *subFieldVal)]; ok {
|
|
||||||
panic(fmt.Sprintf(
|
|
||||||
"bindPrimKey duplicated key error %s %s",
|
|
||||||
metaClass.FileName,
|
|
||||||
q5.MkInt64(*fieldVal, *subFieldVal)))
|
|
||||||
}
|
|
||||||
idHash[q5.MkInt64(*fieldVal, *subFieldVal)] = wrapMeta.Interface()
|
|
||||||
} else {
|
|
||||||
panic(fmt.Sprintf("bindPrimKey subField error %s", metaClass.FileName))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic(fmt.Sprintf("bindPrimKey primKey error %s", metaClass.FileName))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, metaClass := range *this.metaClasses {
|
|
||||||
wrapMetaList := reflect.ValueOf(this.wrapList[metaClass.Idx])
|
|
||||||
for i := 0; i < wrapMetaList.Len(); i++ {
|
|
||||||
wrapMeta := wrapMetaList.Index(i)
|
|
||||||
if metaClass.PrimKey == "" {
|
|
||||||
this.wrapIdHash[metaClass.Idx][int64(i + 1)] = wrapMeta.Interface()
|
|
||||||
} else {
|
|
||||||
bindFunc(&metaClass, wrapMeta)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) loadJson(metaClass *MetaClass) (reflect.Value, error) {
|
|
||||||
if f, err := os.Open(metaClass.FileName); err == nil {
|
|
||||||
data, _ := bufio.NewReader(f).ReadString(0)
|
|
||||||
switch q5.JsonStrType(data) {
|
|
||||||
case q5.JSON_ARRAY:
|
|
||||||
break
|
|
||||||
case q5.JSON_OBJECT:
|
|
||||||
data = "[" + data + "]"
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("error json format %s", metaClass.FileName))
|
|
||||||
}
|
|
||||||
data = this.adjustJsonForamt(metaClass, data)
|
|
||||||
data = "{\"values\":" + data + "}"
|
|
||||||
|
|
||||||
msgType := reflect.TypeOf(metaClass.RawMeta).Elem()
|
|
||||||
msg := reflect.New(msgType)
|
|
||||||
msgPb := msg.Interface().(proto.Message)
|
|
||||||
u := jsonpb.Unmarshaler{AllowUnknownFields: true}
|
|
||||||
err := u.Unmarshal(strings.NewReader(data), msgPb)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf(
|
|
||||||
"parse json error %s %s %s",
|
|
||||||
err,
|
|
||||||
metaClass.FileName,
|
|
||||||
msgType.Name()))
|
|
||||||
}
|
|
||||||
return msg, err
|
|
||||||
} else {
|
|
||||||
panic(fmt.Sprintf("open metafile error %s %s", metaClass.FileName, err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) GetMetaById(idx int, id int32) interface{} {
|
|
||||||
return this.GetMetaById64(idx, int64(id))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) GetMetaById64(idx int, id int64) interface{} {
|
|
||||||
if idx >=0 && idx < len(this.wrapIdHash) {
|
|
||||||
idHash := this.wrapIdHash[idx]
|
|
||||||
if v, ok := idHash[id]; ok {
|
|
||||||
return reflect.ValueOf(v).Interface()
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) GetMetaByName(idx int, name string) interface{} {
|
|
||||||
if idx >=0 && idx < len(this.wrapNameHash) {
|
|
||||||
nameHash := this.wrapNameHash[idx]
|
|
||||||
if v, ok := nameHash[name]; ok {
|
|
||||||
return v
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) GetMetaList(idx int) interface{} {
|
|
||||||
if idx >=0 && idx < len(this.wrapList) {
|
|
||||||
return this.wrapList[idx]
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) adjustJsonForamt(metaClass *MetaClass, rawData string) string {
|
|
||||||
adjustFieldFunc := func(msg map[string]interface{}, key string, val interface{}, field protoreflect.FieldDescriptor) {
|
|
||||||
switch field.Kind() {
|
|
||||||
case
|
|
||||||
protoreflect.Int32Kind,
|
|
||||||
protoreflect.Sint32Kind,
|
|
||||||
protoreflect.Int64Kind,
|
|
||||||
protoreflect.Sint64Kind,
|
|
||||||
protoreflect.Uint64Kind,
|
|
||||||
protoreflect.Sfixed32Kind,
|
|
||||||
protoreflect.Fixed32Kind,
|
|
||||||
protoreflect.FloatKind,
|
|
||||||
protoreflect.Sfixed64Kind,
|
|
||||||
protoreflect.Fixed64Kind,
|
|
||||||
protoreflect.DoubleKind:
|
|
||||||
if q5.IsNumberType(val) {
|
|
||||||
} else if reflect.TypeOf(val).Kind() == reflect.String {
|
|
||||||
strVal := val.(string)
|
|
||||||
if strVal == "" {
|
|
||||||
msg[key] = 0
|
|
||||||
} else {
|
|
||||||
intVal, err := strconv.ParseInt(strVal, 10, 64)
|
|
||||||
if err == nil {
|
|
||||||
msg[key] = intVal
|
|
||||||
} else {
|
|
||||||
floatVal, err := strconv.ParseFloat(strVal, 64)
|
|
||||||
if err == nil {
|
|
||||||
msg[key] = floatVal
|
|
||||||
} else {
|
|
||||||
panic(fmt.Sprintf(
|
|
||||||
"adjustJsonFormat error %s %s %s",
|
|
||||||
metaClass.FileName,
|
|
||||||
key,
|
|
||||||
val))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case
|
|
||||||
protoreflect.BoolKind,
|
|
||||||
protoreflect.EnumKind,
|
|
||||||
protoreflect.BytesKind,
|
|
||||||
//protoreflect.MessageKind,
|
|
||||||
protoreflect.GroupKind:
|
|
||||||
panic(fmt.Sprintf(
|
|
||||||
"adjustJsonFormat error %s %s %s",
|
|
||||||
metaClass.FileName,
|
|
||||||
key,
|
|
||||||
val))
|
|
||||||
case protoreflect.MessageKind:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var rawJson []map[string]interface{}
|
|
||||||
err := json.Unmarshal([]byte(rawData), &rawJson)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("adjustJsonFormat unmarshal error %s %s", metaClass.FileName, err))
|
|
||||||
}
|
|
||||||
msgType := proto.MessageReflect(reflect.New(metaClass.eleMeta).Interface().(proto.Message))
|
|
||||||
for i := 0; i < len(rawJson); i++ {
|
|
||||||
msg := rawJson[i]
|
|
||||||
for key, val := range msg {
|
|
||||||
field := msgType.Descriptor().Fields().ByName(protoreflect.Name(key))
|
|
||||||
if field != nil {
|
|
||||||
adjustFieldFunc(msg, key, val, field)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newData, err := json.Marshal(rawJson)
|
|
||||||
//fmt.Println("rawData ", string(rawData))
|
|
||||||
//fmt.Println("newData ", string(newData))
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("adjustJsonFormat marshal error %s %s", metaClass.FileName, err))
|
|
||||||
}
|
|
||||||
return string(newData)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) firstInitMetaList() {
|
|
||||||
for i := 0; i < len(this.wrapList); i++ {
|
|
||||||
metaList := reflect.ValueOf(this.wrapList[i])
|
|
||||||
for ii := 0; ii < metaList.Len(); ii++ {
|
|
||||||
meta := metaList.Index(ii)
|
|
||||||
initFunc := meta.MethodByName("Init")
|
|
||||||
if initFunc.IsValid() {
|
|
||||||
initFunc.Call(nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MetaMgr) secondInitMetaList() {
|
|
||||||
for i := 0; i < len(this.wrapList); i++ {
|
|
||||||
metaList := reflect.ValueOf(this.wrapList[i])
|
|
||||||
for i := 0; i < metaList.Len(); i++ {
|
|
||||||
meta := metaList.Index(i)
|
|
||||||
init2Func := meta.MethodByName("Init2")
|
|
||||||
if init2Func.IsValid() {
|
|
||||||
init2Func.Call(nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
138
metatable.go
Normal file
138
metatable.go
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package f5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MetaTable interface {
|
||||||
|
IsNoLoad() bool
|
||||||
|
Load()
|
||||||
|
PreInit1()
|
||||||
|
ElementsInit(int)
|
||||||
|
PostInit1()
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoadFromJson interface {
|
||||||
|
LoadFromJsonStr(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
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]) ElementInit(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 *IdMetaTable[T]) Load() {
|
||||||
|
if this.NoLoad {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
if this.NoLoad {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
if !tbl.IsNoLoad() {
|
||||||
|
tbl.Load()
|
||||||
|
}
|
||||||
|
tbl.ElementsInit(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < ele.NumField(); i++ {
|
||||||
|
var tbl MetaTable = ele.Field(i).Interface().(MetaTable)
|
||||||
|
if !tbl.IsNoLoad() {
|
||||||
|
tbl.PostInit1()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -71,6 +71,12 @@ func ExtractOpenIdFromAccountId(accountId string) string {
|
|||||||
return strings.Join(tmpStrings[2:], "_")
|
return strings.Join(tmpStrings[2:], "_")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func New[T any](cb func(*T)) *T {
|
||||||
|
obj := new(T)
|
||||||
|
cb(obj)
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
switch os.Getenv("SERVER_ENV") {
|
switch os.Getenv("SERVER_ENV") {
|
||||||
case "TEST":
|
case "TEST":
|
||||||
|
Loading…
x
Reference in New Issue
Block a user