blob: da6f688c7b4ae2777d0443c8cdf3cdb4900fd4c7 [file] [log] [blame]
khenaidoobf6e7bb2018-08-14 22:27:29 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Stephane Barbariedc5022d2018-11-19 15:21:44 -050016
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040017package model
18
19import (
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040020 desc "github.com/golang/protobuf/descriptor"
21 "github.com/golang/protobuf/proto"
22 "github.com/golang/protobuf/protoc-gen-go/descriptor"
Stephane Barbarie8c48b5c2018-10-02 09:45:17 -040023 "github.com/opencord/voltha-go/common/log"
William Kurkiandaa6bb22019-03-07 12:26:28 -050024 "github.com/opencord/voltha-protos/go/common"
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040025 "reflect"
26 "strconv"
27 "sync"
28)
29
Stephane Barbariedc5022d2018-11-19 15:21:44 -050030type singletonChildTypeCache struct {
31 Cache map[interface{}]map[string]*ChildType
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040032}
33
Stephane Barbariedc5022d2018-11-19 15:21:44 -050034var instanceChildTypeCache *singletonChildTypeCache
35var onceChildTypeCache sync.Once
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040036
Stephane Barbariedc5022d2018-11-19 15:21:44 -050037func getChildTypeCache() *singletonChildTypeCache {
38 onceChildTypeCache.Do(func() {
39 instanceChildTypeCache = &singletonChildTypeCache{}
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040040 })
Stephane Barbariedc5022d2018-11-19 15:21:44 -050041 return instanceChildTypeCache
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040042}
43
Stephane Barbariedc5022d2018-11-19 15:21:44 -050044// ChildType structure contains construct details of an object
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040045type ChildType struct {
46 ClassModule string
47 ClassType reflect.Type
48 IsContainer bool
49 Key string
50 KeyFromStr func(s string) interface{}
51}
52
Stephane Barbariedc5022d2018-11-19 15:21:44 -050053// ChildrenFields retrieves list of child objects associated to a given interface
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040054func ChildrenFields(cls interface{}) map[string]*ChildType {
55 if cls == nil {
56 return nil
57 }
58 var names map[string]*ChildType
Stephane Barbariedc5022d2018-11-19 15:21:44 -050059 var namesExist bool
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040060
Stephane Barbariedc5022d2018-11-19 15:21:44 -050061 if getChildTypeCache().Cache == nil {
62 getChildTypeCache().Cache = make(map[interface{}]map[string]*ChildType)
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040063 }
64
65 msgType := reflect.TypeOf(cls)
Stephane Barbariedc5022d2018-11-19 15:21:44 -050066 inst := getChildTypeCache()
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040067
Stephane Barbariedc5022d2018-11-19 15:21:44 -050068 if names, namesExist = inst.Cache[msgType.String()]; !namesExist {
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040069 names = make(map[string]*ChildType)
70
71 _, md := desc.ForMessage(cls.(desc.Message))
72
73 // TODO: Do we need to validate MD for nil, panic or exception?
74 for _, field := range md.Field {
75 if options := field.GetOptions(); options != nil {
76 if proto.HasExtension(options, common.E_ChildNode) {
77 isContainer := *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
78 meta, _ := proto.GetExtension(options, common.E_ChildNode)
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040079
Stephane Barbarie126101e2018-10-11 16:18:48 -040080 var keyFromStr func(string) interface{}
81 var ct ChildType
82
83 parentType := FindOwnerType(reflect.ValueOf(cls), field.GetName(), 0, false)
84 if meta.(*common.ChildNode).GetKey() != "" {
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040085 keyType := FindKeyOwner(reflect.New(parentType).Elem().Interface(), meta.(*common.ChildNode).GetKey(), 0)
86
87 switch keyType.(reflect.Type).Name() {
88 case "string":
89 keyFromStr = func(s string) interface{} {
90 return s
91 }
92 case "int32":
Stephane Barbarie06c4a742018-10-01 11:09:32 -040093 keyFromStr = func(s string) interface{} {
94 i, _ := strconv.Atoi(s)
95 return int32(i)
96 }
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040097 case "int64":
Stephane Barbarie06c4a742018-10-01 11:09:32 -040098 keyFromStr = func(s string) interface{} {
99 i, _ := strconv.Atoi(s)
100 return int64(i)
101 }
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400102 case "uint32":
Stephane Barbarie06c4a742018-10-01 11:09:32 -0400103 keyFromStr = func(s string) interface{} {
104 i, _ := strconv.Atoi(s)
105 return uint32(i)
106 }
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400107 case "uint64":
108 keyFromStr = func(s string) interface{} {
109 i, _ := strconv.Atoi(s)
Stephane Barbarie06c4a742018-10-01 11:09:32 -0400110 return uint64(i)
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400111 }
112 default:
Stephane Barbarie8c48b5c2018-10-02 09:45:17 -0400113 log.Errorf("Key type not implemented - type: %s\n", keyType.(reflect.Type))
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400114 }
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400115 }
Stephane Barbarie126101e2018-10-11 16:18:48 -0400116
117 ct = ChildType{
118 ClassModule: parentType.String(),
119 ClassType: parentType,
120 IsContainer: isContainer,
121 Key: meta.(*common.ChildNode).GetKey(),
122 KeyFromStr: keyFromStr,
123 }
124
125 names[field.GetName()] = &ct
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400126 }
127 }
128 }
129
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500130 getChildTypeCache().Cache[msgType.String()] = names
131 } else {
132 log.Debugf("Cache entry for %s: %+v", msgType.String(), inst.Cache[msgType.String()])
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400133 }
134
135 return names
136}