本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.1KB

  1. // Copyright (c) 2014 Couchbase, Inc.
  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 mapping
  15. import (
  16. "reflect"
  17. "strings"
  18. )
  19. func lookupPropertyPath(data interface{}, path string) interface{} {
  20. pathParts := decodePath(path)
  21. current := data
  22. for _, part := range pathParts {
  23. current = lookupPropertyPathPart(current, part)
  24. if current == nil {
  25. break
  26. }
  27. }
  28. return current
  29. }
  30. func lookupPropertyPathPart(data interface{}, part string) interface{} {
  31. val := reflect.ValueOf(data)
  32. if !val.IsValid() {
  33. return nil
  34. }
  35. typ := val.Type()
  36. switch typ.Kind() {
  37. case reflect.Map:
  38. // FIXME can add support for other map keys in the future
  39. if typ.Key().Kind() == reflect.String {
  40. key := reflect.ValueOf(part)
  41. entry := val.MapIndex(key)
  42. if entry.IsValid() {
  43. return entry.Interface()
  44. }
  45. }
  46. case reflect.Struct:
  47. field := val.FieldByName(part)
  48. if field.IsValid() && field.CanInterface() {
  49. return field.Interface()
  50. }
  51. case reflect.Ptr:
  52. ptrElem := val.Elem()
  53. if ptrElem.IsValid() && ptrElem.CanInterface() {
  54. return lookupPropertyPathPart(ptrElem.Interface(), part)
  55. }
  56. }
  57. return nil
  58. }
  59. const pathSeparator = "."
  60. func decodePath(path string) []string {
  61. return strings.Split(path, pathSeparator)
  62. }
  63. func encodePath(pathElements []string) string {
  64. return strings.Join(pathElements, pathSeparator)
  65. }
  66. func mustString(data interface{}) (string, bool) {
  67. if data != nil {
  68. str, ok := data.(string)
  69. if ok {
  70. return str, true
  71. }
  72. }
  73. return "", false
  74. }
  75. // parseTagName extracts the field name from a struct tag
  76. func parseTagName(tag string) string {
  77. if idx := strings.Index(tag, ","); idx != -1 {
  78. return tag[:idx]
  79. }
  80. return tag
  81. }
上海开阖软件有限公司 沪ICP备12045867号-1