package wmo import ( "gogs.mikescher.com/BlackForestBytes/goext/langext" "gogs.mikescher.com/BlackForestBytes/goext/reflectext" "reflect" "strings" ) func (c *Coll[TData]) EnsureInitializedReflection(v TData) { if !c.isInterfaceDataType { return // only dynamically load dataTypeMap on interface TData } rval := reflect.ValueOf(v) for rval.Type().Kind() == reflect.Pointer { rval = rval.Elem() } if _, ok := c.implDataTypeMap[rval.Type()]; ok { return // already loaded } m := make(map[string]fullTypeRef) c.initFields("", rval, m, make([]int, 0)) c.implDataTypeMap[rval.Type()] = m } func (c *Coll[TData]) init() { example := *new(TData) datatype := reflect.TypeOf(&example).Elem() if datatype.Kind() == reflect.Interface { c.isInterfaceDataType = true c.dataTypeMap = make(map[string]fullTypeRef) c.implDataTypeMap = make(map[reflect.Type]map[string]fullTypeRef) } else { c.isInterfaceDataType = false c.dataTypeMap = make(map[string]fullTypeRef) c.implDataTypeMap = make(map[reflect.Type]map[string]fullTypeRef) v := reflect.ValueOf(example) c.initFields("", v, c.dataTypeMap, make([]int, 0)) } } func (c *Coll[TData]) initFields(prefix string, rval reflect.Value, m map[string]fullTypeRef, idxarr []int) { rtyp := rval.Type() for i := 0; i < rtyp.NumField(); i++ { rsfield := rtyp.Field(i) rvfield := rval.Field(i) if !rsfield.IsExported() { continue } bsonkey, found := rsfield.Tag.Lookup("bson") if !found { continue } if strings.Contains(bsonkey, ",") { bsonkey = bsonkey[:strings.Index(bsonkey, ",")] } if bsonkey == "-" { continue } fullKey := prefix + bsonkey newIdxArr := langext.ArrCopy(idxarr) newIdxArr = append(newIdxArr, i) if rvfield.Type().Kind() == reflect.Pointer { m[fullKey] = fullTypeRef{ IsPointer: true, RealType: rvfield.Type(), Kind: rvfield.Type().Elem().Kind(), Type: rvfield.Type().Elem(), UnderlyingType: reflectext.Underlying(rvfield.Type().Elem()), Name: rsfield.Name, Index: newIdxArr, } } else { m[fullKey] = fullTypeRef{ IsPointer: false, RealType: rvfield.Type(), Kind: rvfield.Type().Kind(), Type: rvfield.Type(), UnderlyingType: reflectext.Underlying(rvfield.Type()), Name: rsfield.Name, Index: newIdxArr, } } if rvfield.Kind() == reflect.Struct { c.initFields(fullKey+".", rvfield, m, newIdxArr) } } } func (c *Coll[TData]) getTokenValueAsMongoType(value string, fieldName string) (any, error) { fref := c.dataTypeMap[fieldName] pss := reflectext.PrimitiveStringSerializer{} return pss.ValueFromString(value, fref.RealType) } func (c *Coll[TData]) getFieldValueAsTokenString(entity TData, fieldName string) (string, error) { realValue := c.getFieldValue(entity, fieldName) pss := reflectext.PrimitiveStringSerializer{} return pss.ValueToString(realValue) } func (c *Coll[TData]) getFieldType(fieldName string) fullTypeRef { return c.dataTypeMap[fieldName] } func (c *Coll[TData]) getFieldValue(data TData, fieldName string) any { fref := c.dataTypeMap[fieldName] rval := reflect.ValueOf(data) return rval.FieldByIndex(fref.Index).Interface() }