| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package reflectutils
- import (
- "fmt"
- "reflect"
- "yunion.io/x/log"
- )
- /*
- func GetStructFieldName(field *reflect.StructField) string {
- tagMap := utils.TagMap(field.Tag)
- // var name string
- nameStr, _ := tagMap["name"]
- if len(nameStr) > 0 {
- return nameStr
- } else {
- jsonStr, _ := tagMap["json"]
- return toJsonKey(field.Name, jsonStr)
- }
- }
- func toJsonKey(fieldName, jsonTag string) string {
- jsonTag = strings.Replace(jsonTag, "omitempty", "", -1)
- words := utils.FindWords([]byte(jsonTag), 0)
- if len(words) == 0 {
- return utils.CamelSplit(fieldName, "_")
- }
- name := words[0]
- if name == "-" {
- return ""
- }
- return name
- }
- func FetchStructFieldNameValueInterfaces(dataValue reflect.Value) map[string]interface{} {
- fields := make(map[string]interface{})
- fetchStructFieldNameValueInterfaces(dataValue.Type(), dataValue, fields)
- return fields
- }
- func fetchStructFieldNameValueInterfaces(dataType reflect.Type, dataValue reflect.Value, fields map[string]interface{}) {
- for i := 0; i < dataType.NumField(); i += 1 {
- fieldType := dataType.Field(i)
- // log.Infof("%s %s %s", fieldType.Name, fieldType.Type, fieldType.Tag)
- if gotypes.IsFieldExportable(fieldType.Name) {
- fieldValue := dataValue.Field(i)
- if fieldType.Type.Kind() == reflect.Struct && fieldType.Anonymous {
- fetchStructFieldNameValueInterfaces(fieldType.Type, fieldValue, fields)
- } else if fieldValue.IsValid() && fieldValue.CanInterface() {
- val := fieldValue.Interface()
- // log.Debugf("val: %s %s %s", fieldType.Name, reflect.TypeOf(val), val, nil)
- if val != nil && !gotypes.IsNil(val) {
- name := GetStructFieldName(&fieldType)
- fields[name] = val
- }
- }
- }
- }
- }
- func FetchStructFieldNameValues(dataValue reflect.Value) map[string]reflect.Value {
- fields := make(map[string]reflect.Value)
- fetchStructFieldNameValues(dataValue.Type(), dataValue, fields)
- return fields
- }
- func fetchStructFieldNameValues(dataType reflect.Type, dataValue reflect.Value, fields map[string]reflect.Value) {
- for i := 0; i < dataType.NumField(); i += 1 {
- fieldType := dataType.Field(i)
- // log.Infof("%s %s %s", fieldType.Name, fieldType.Type, fieldType.Tag)
- if gotypes.IsFieldExportable(fieldType.Name) {
- fieldValue := dataValue.Field(i)
- if fieldType.Type.Kind() == reflect.Struct && fieldType.Anonymous {
- fetchStructFieldNameValues(fieldType.Type, fieldValue, fields)
- } else if fieldValue.IsValid() && fieldValue.CanSet() {
- name := GetStructFieldName(&fieldType)
- fields[name] = fieldValue
- }
- }
- }
- }
- */
- func FindStructFieldValue(dataValue reflect.Value, name string) (reflect.Value, bool) {
- set := FetchStructFieldValueSet(dataValue)
- val, find := set.GetValue(name)
- if find && val.CanSet() {
- return val, true
- }
- return reflect.Value{}, false
- }
- func FindStructFieldInterface(dataValue reflect.Value, name string) (interface{}, bool) {
- set := FetchStructFieldValueSet(dataValue)
- return set.GetInterface(name)
- }
- func FillEmbededStructValue(container reflect.Value, embed reflect.Value) bool {
- containerType := container.Type()
- for i := 0; i < containerType.NumField(); i += 1 {
- fieldType := containerType.Field(i)
- fieldValue := container.Field(i)
- if fieldType.Type.Kind() == reflect.Struct && fieldType.Anonymous {
- if fieldType.Type == embed.Type() {
- fieldValue.Set(embed)
- return true
- } else {
- filled := FillEmbededStructValue(fieldValue, embed)
- if filled {
- return true
- }
- }
- }
- }
- return false
- }
- func SetStructFieldValue(structValue reflect.Value, fieldName string, val reflect.Value) bool {
- set := FetchStructFieldValueSet(structValue)
- target, find := set.GetValue(fieldName)
- if !find {
- return false
- }
- if !target.CanSet() {
- return false
- }
- target.Set(val)
- return true
- }
- func ExpandInterface(val interface{}) []interface{} {
- value := reflect.Indirect(reflect.ValueOf(val))
- if value.Kind() == reflect.Slice || value.Kind() == reflect.Array {
- ret := make([]interface{}, value.Len())
- for i := 0; i < len(ret); i += 1 {
- ret[i] = value.Index(i).Interface()
- }
- return ret
- } else {
- return []interface{}{val}
- }
- }
- // tagetType must not be a pointer
- func getAnonymouStructPointer(structValue reflect.Value, targetType reflect.Type) interface{} {
- structType := structValue.Type()
- if structType == targetType {
- return structValue.Addr().Interface()
- }
- for i := 0; i < structValue.NumField(); i += 1 {
- fieldType := structType.Field(i)
- if fieldType.Anonymous && fieldType.Type.Kind() == reflect.Struct {
- ptr := getAnonymouStructPointer(structValue.Field(i), targetType)
- if ptr != nil {
- return ptr
- }
- }
- }
- return nil
- }
- func FindAnonymouStructPointer(data interface{}, targetPtr interface{}) error {
- targetValue := reflect.ValueOf(targetPtr)
- if targetValue.Kind() != reflect.Ptr {
- return fmt.Errorf("target must be a pointer to pointer")
- }
- targetValue = targetValue.Elem()
- if targetValue.Kind() != reflect.Ptr {
- return fmt.Errorf("target must be a pointer to pointer")
- }
- targetType := targetValue.Type().Elem()
- if targetType.Kind() != reflect.Struct {
- return fmt.Errorf("target type must be a struct")
- }
- structValue := reflect.ValueOf(data)
- if structValue.Kind() != reflect.Ptr {
- return fmt.Errorf("data type must be a pointer to struct")
- }
- structValue = reflect.ValueOf(data).Elem()
- if structValue.Kind() != reflect.Struct {
- return fmt.Errorf("data type must be a pointer to struct")
- }
- ptr := getAnonymouStructPointer(structValue, targetType)
- if ptr == nil {
- return fmt.Errorf("no anonymous struct found")
- }
- targetValue.Set(reflect.ValueOf(ptr))
- return nil
- }
- func StructContains(type1 reflect.Type, type2 reflect.Type) bool {
- if type1.Kind() != reflect.Struct || type2.Kind() != reflect.Struct {
- log.Errorf("types should be struct!")
- return false
- }
- if type1 == type2 {
- return true
- }
- for i := 0; i < type1.NumField(); i += 1 {
- field := type1.Field(i)
- if field.Anonymous && field.Type.Kind() == reflect.Struct {
- contains := StructContains(field.Type, type2)
- if contains {
- return true
- }
- }
- }
- return false
- }
|