194 lines
5.1 KiB
Go
194 lines
5.1 KiB
Go
package f5
|
|
|
|
import (
|
|
"os"
|
|
"bufio"
|
|
"strings"
|
|
"reflect"
|
|
"fmt"
|
|
"q5"
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
"github.com/golang/protobuf/jsonpb"
|
|
)
|
|
|
|
type MetaClass struct {
|
|
FileName string
|
|
Idx int
|
|
RawMeta interface{}
|
|
WrapMeta interface{}
|
|
PrimKey string
|
|
SecKey string
|
|
}
|
|
|
|
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) {
|
|
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()
|
|
}
|
|
|
|
func (this *MetaMgr) loadRawMetaTable() {
|
|
for _, val := range *this.metaClasses {
|
|
rawMeta, _ := this.loadJson(&val)
|
|
values := rawMeta.Elem().FieldByName("Values")
|
|
wrapMetaType := reflect.TypeOf(val.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[val.Idx] = rawMeta
|
|
this.wrapList[val.Idx] = wrapMetaList.Interface()
|
|
this.wrapIdHash[val.Idx] = map[int64]interface{}{}
|
|
this.wrapNameHash[val.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:
|
|
data = "{\"values\":" + data + "}"
|
|
case q5.JSON_OBJECT:
|
|
data = "{\"values\":[" + data + "]}"
|
|
default:
|
|
panic(fmt.Sprintf("error json format %s", metaClass.FileName))
|
|
}
|
|
|
|
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
|
|
}
|