reflectutils.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package reflectutils
  15. import (
  16. "fmt"
  17. "reflect"
  18. "yunion.io/x/log"
  19. )
  20. /*
  21. func GetStructFieldName(field *reflect.StructField) string {
  22. tagMap := utils.TagMap(field.Tag)
  23. // var name string
  24. nameStr, _ := tagMap["name"]
  25. if len(nameStr) > 0 {
  26. return nameStr
  27. } else {
  28. jsonStr, _ := tagMap["json"]
  29. return toJsonKey(field.Name, jsonStr)
  30. }
  31. }
  32. func toJsonKey(fieldName, jsonTag string) string {
  33. jsonTag = strings.Replace(jsonTag, "omitempty", "", -1)
  34. words := utils.FindWords([]byte(jsonTag), 0)
  35. if len(words) == 0 {
  36. return utils.CamelSplit(fieldName, "_")
  37. }
  38. name := words[0]
  39. if name == "-" {
  40. return ""
  41. }
  42. return name
  43. }
  44. func FetchStructFieldNameValueInterfaces(dataValue reflect.Value) map[string]interface{} {
  45. fields := make(map[string]interface{})
  46. fetchStructFieldNameValueInterfaces(dataValue.Type(), dataValue, fields)
  47. return fields
  48. }
  49. func fetchStructFieldNameValueInterfaces(dataType reflect.Type, dataValue reflect.Value, fields map[string]interface{}) {
  50. for i := 0; i < dataType.NumField(); i += 1 {
  51. fieldType := dataType.Field(i)
  52. // log.Infof("%s %s %s", fieldType.Name, fieldType.Type, fieldType.Tag)
  53. if gotypes.IsFieldExportable(fieldType.Name) {
  54. fieldValue := dataValue.Field(i)
  55. if fieldType.Type.Kind() == reflect.Struct && fieldType.Anonymous {
  56. fetchStructFieldNameValueInterfaces(fieldType.Type, fieldValue, fields)
  57. } else if fieldValue.IsValid() && fieldValue.CanInterface() {
  58. val := fieldValue.Interface()
  59. // log.Debugf("val: %s %s %s", fieldType.Name, reflect.TypeOf(val), val, nil)
  60. if val != nil && !gotypes.IsNil(val) {
  61. name := GetStructFieldName(&fieldType)
  62. fields[name] = val
  63. }
  64. }
  65. }
  66. }
  67. }
  68. func FetchStructFieldNameValues(dataValue reflect.Value) map[string]reflect.Value {
  69. fields := make(map[string]reflect.Value)
  70. fetchStructFieldNameValues(dataValue.Type(), dataValue, fields)
  71. return fields
  72. }
  73. func fetchStructFieldNameValues(dataType reflect.Type, dataValue reflect.Value, fields map[string]reflect.Value) {
  74. for i := 0; i < dataType.NumField(); i += 1 {
  75. fieldType := dataType.Field(i)
  76. // log.Infof("%s %s %s", fieldType.Name, fieldType.Type, fieldType.Tag)
  77. if gotypes.IsFieldExportable(fieldType.Name) {
  78. fieldValue := dataValue.Field(i)
  79. if fieldType.Type.Kind() == reflect.Struct && fieldType.Anonymous {
  80. fetchStructFieldNameValues(fieldType.Type, fieldValue, fields)
  81. } else if fieldValue.IsValid() && fieldValue.CanSet() {
  82. name := GetStructFieldName(&fieldType)
  83. fields[name] = fieldValue
  84. }
  85. }
  86. }
  87. }
  88. */
  89. func FindStructFieldValue(dataValue reflect.Value, name string) (reflect.Value, bool) {
  90. set := FetchStructFieldValueSet(dataValue)
  91. val, find := set.GetValue(name)
  92. if find && val.CanSet() {
  93. return val, true
  94. }
  95. return reflect.Value{}, false
  96. }
  97. func FindStructFieldInterface(dataValue reflect.Value, name string) (interface{}, bool) {
  98. set := FetchStructFieldValueSet(dataValue)
  99. return set.GetInterface(name)
  100. }
  101. func FillEmbededStructValue(container reflect.Value, embed reflect.Value) bool {
  102. containerType := container.Type()
  103. for i := 0; i < containerType.NumField(); i += 1 {
  104. fieldType := containerType.Field(i)
  105. fieldValue := container.Field(i)
  106. if fieldType.Type.Kind() == reflect.Struct && fieldType.Anonymous {
  107. if fieldType.Type == embed.Type() {
  108. fieldValue.Set(embed)
  109. return true
  110. } else {
  111. filled := FillEmbededStructValue(fieldValue, embed)
  112. if filled {
  113. return true
  114. }
  115. }
  116. }
  117. }
  118. return false
  119. }
  120. func SetStructFieldValue(structValue reflect.Value, fieldName string, val reflect.Value) bool {
  121. set := FetchStructFieldValueSet(structValue)
  122. target, find := set.GetValue(fieldName)
  123. if !find {
  124. return false
  125. }
  126. if !target.CanSet() {
  127. return false
  128. }
  129. target.Set(val)
  130. return true
  131. }
  132. func ExpandInterface(val interface{}) []interface{} {
  133. value := reflect.Indirect(reflect.ValueOf(val))
  134. if value.Kind() == reflect.Slice || value.Kind() == reflect.Array {
  135. ret := make([]interface{}, value.Len())
  136. for i := 0; i < len(ret); i += 1 {
  137. ret[i] = value.Index(i).Interface()
  138. }
  139. return ret
  140. } else {
  141. return []interface{}{val}
  142. }
  143. }
  144. // tagetType must not be a pointer
  145. func getAnonymouStructPointer(structValue reflect.Value, targetType reflect.Type) interface{} {
  146. structType := structValue.Type()
  147. if structType == targetType {
  148. return structValue.Addr().Interface()
  149. }
  150. for i := 0; i < structValue.NumField(); i += 1 {
  151. fieldType := structType.Field(i)
  152. if fieldType.Anonymous && fieldType.Type.Kind() == reflect.Struct {
  153. ptr := getAnonymouStructPointer(structValue.Field(i), targetType)
  154. if ptr != nil {
  155. return ptr
  156. }
  157. }
  158. }
  159. return nil
  160. }
  161. func FindAnonymouStructPointer(data interface{}, targetPtr interface{}) error {
  162. targetValue := reflect.ValueOf(targetPtr)
  163. if targetValue.Kind() != reflect.Ptr {
  164. return fmt.Errorf("target must be a pointer to pointer")
  165. }
  166. targetValue = targetValue.Elem()
  167. if targetValue.Kind() != reflect.Ptr {
  168. return fmt.Errorf("target must be a pointer to pointer")
  169. }
  170. targetType := targetValue.Type().Elem()
  171. if targetType.Kind() != reflect.Struct {
  172. return fmt.Errorf("target type must be a struct")
  173. }
  174. structValue := reflect.ValueOf(data)
  175. if structValue.Kind() != reflect.Ptr {
  176. return fmt.Errorf("data type must be a pointer to struct")
  177. }
  178. structValue = reflect.ValueOf(data).Elem()
  179. if structValue.Kind() != reflect.Struct {
  180. return fmt.Errorf("data type must be a pointer to struct")
  181. }
  182. ptr := getAnonymouStructPointer(structValue, targetType)
  183. if ptr == nil {
  184. return fmt.Errorf("no anonymous struct found")
  185. }
  186. targetValue.Set(reflect.ValueOf(ptr))
  187. return nil
  188. }
  189. func StructContains(type1 reflect.Type, type2 reflect.Type) bool {
  190. if type1.Kind() != reflect.Struct || type2.Kind() != reflect.Struct {
  191. log.Errorf("types should be struct!")
  192. return false
  193. }
  194. if type1 == type2 {
  195. return true
  196. }
  197. for i := 0; i < type1.NumField(); i += 1 {
  198. field := type1.Field(i)
  199. if field.Anonymous && field.Type.Kind() == reflect.Struct {
  200. contains := StructContains(field.Type, type2)
  201. if contains {
  202. return true
  203. }
  204. }
  205. }
  206. return false
  207. }