blob: a96883c4ca7e116a4d3f51646ca6aa61d6ed1100 [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 Barbarie4a2564d2018-07-26 11:02:58 -040016package model
17
18import (
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040019 desc "github.com/golang/protobuf/descriptor"
20 "github.com/golang/protobuf/proto"
21 "github.com/golang/protobuf/protoc-gen-go/descriptor"
Stephane Barbarie8c48b5c2018-10-02 09:45:17 -040022 "github.com/opencord/voltha-go/common/log"
Stephane Barbarieec0919b2018-09-05 14:14:29 -040023 "github.com/opencord/voltha-go/protos/common"
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040024 "reflect"
25 "strconv"
26 "sync"
27)
28
29type singleton struct {
30 ChildrenFieldsCache map[interface{}]map[string]*ChildType
31}
32
33var instance *singleton
34var once sync.Once
35
36func GetInstance() *singleton {
37 once.Do(func() {
38 instance = &singleton{}
39 })
40 return instance
41}
42
43type ChildType struct {
44 ClassModule string
45 ClassType reflect.Type
46 IsContainer bool
47 Key string
48 KeyFromStr func(s string) interface{}
49}
50
51func ChildrenFields(cls interface{}) map[string]*ChildType {
52 if cls == nil {
53 return nil
54 }
55 var names map[string]*ChildType
56 var names_exist bool
57
58 if GetInstance().ChildrenFieldsCache == nil {
59 GetInstance().ChildrenFieldsCache = make(map[interface{}]map[string]*ChildType)
60 }
61
62 msgType := reflect.TypeOf(cls)
63
Stephane Barbarieec0919b2018-09-05 14:14:29 -040064 inst := GetInstance()
65
66 if names, names_exist = inst.ChildrenFieldsCache[msgType.String()]; !names_exist {
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040067 names = make(map[string]*ChildType)
68
69 _, md := desc.ForMessage(cls.(desc.Message))
70
71 // TODO: Do we need to validate MD for nil, panic or exception?
72 for _, field := range md.Field {
73 if options := field.GetOptions(); options != nil {
74 if proto.HasExtension(options, common.E_ChildNode) {
75 isContainer := *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
76 meta, _ := proto.GetExtension(options, common.E_ChildNode)
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040077
Stephane Barbarie126101e2018-10-11 16:18:48 -040078 var keyFromStr func(string) interface{}
79 var ct ChildType
80
81 parentType := FindOwnerType(reflect.ValueOf(cls), field.GetName(), 0, false)
82 if meta.(*common.ChildNode).GetKey() != "" {
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040083 keyType := FindKeyOwner(reflect.New(parentType).Elem().Interface(), meta.(*common.ChildNode).GetKey(), 0)
84
85 switch keyType.(reflect.Type).Name() {
86 case "string":
87 keyFromStr = func(s string) interface{} {
88 return s
89 }
90 case "int32":
Stephane Barbarie06c4a742018-10-01 11:09:32 -040091 keyFromStr = func(s string) interface{} {
92 i, _ := strconv.Atoi(s)
93 return int32(i)
94 }
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040095 case "int64":
Stephane Barbarie06c4a742018-10-01 11:09:32 -040096 keyFromStr = func(s string) interface{} {
97 i, _ := strconv.Atoi(s)
98 return int64(i)
99 }
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400100 case "uint32":
Stephane Barbarie06c4a742018-10-01 11:09:32 -0400101 keyFromStr = func(s string) interface{} {
102 i, _ := strconv.Atoi(s)
103 return uint32(i)
104 }
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400105 case "uint64":
106 keyFromStr = func(s string) interface{} {
107 i, _ := strconv.Atoi(s)
Stephane Barbarie06c4a742018-10-01 11:09:32 -0400108 return uint64(i)
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400109 }
110 default:
Stephane Barbarie8c48b5c2018-10-02 09:45:17 -0400111 log.Errorf("Key type not implemented - type: %s\n", keyType.(reflect.Type))
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400112 }
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400113 }
Stephane Barbarie126101e2018-10-11 16:18:48 -0400114
115 ct = ChildType{
116 ClassModule: parentType.String(),
117 ClassType: parentType,
118 IsContainer: isContainer,
119 Key: meta.(*common.ChildNode).GetKey(),
120 KeyFromStr: keyFromStr,
121 }
122
123 names[field.GetName()] = &ct
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400124 }
125 }
126 }
127
128 GetInstance().ChildrenFieldsCache[msgType.String()] = names
129 }
130
131 return names
132}