blob: 65c1c4a79e42d8b9e802451b7d982f57978b1504 [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 (
19 "bytes"
20 "encoding/gob"
21 "reflect"
22 "strings"
23)
24
25func IsProtoMessage(object interface{}) bool {
26 var ok bool
27
28 if object != nil {
29 st := reflect.TypeOf(object)
30 _, ok = st.MethodByName("ProtoMessage")
31 }
32 return ok
33}
34
35func FindOwnerType(obj reflect.Value, name string, depth int, found bool) reflect.Type {
36 k := obj.Kind()
37 switch k {
38 case reflect.Ptr:
39 t := obj.Type().Elem()
40 n := reflect.New(t)
41
42 if rc := FindOwnerType(n.Elem(), name, depth+1, false); rc != nil {
43 return rc
44 }
45
46 case reflect.Struct:
47 for i := 0; i < obj.NumField(); i += 1 {
48 v := reflect.Indirect(obj)
49
50 json := strings.Split(v.Type().Field(i).Tag.Get("json"), ",")
51
52 if json[0] == name {
53 return FindOwnerType(obj.Field(i), name, depth+1, true)
54 }
55
56 if rc := FindOwnerType(obj.Field(i), name, depth+1, false); rc != nil {
57 return rc
58 }
59 }
60 case reflect.Slice:
61 s := reflect.MakeSlice(obj.Type(), 1, 1)
62 n := reflect.New(obj.Type())
63 n.Elem().Set(s)
64
65 for i := 0; i < n.Elem().Len(); i += 1 {
66 if found {
67 return reflect.ValueOf(n.Elem().Index(i).Interface()).Type()
68 }
69 }
70
71 for i := 0; i < obj.Len(); i += 1 {
72 if found {
73 return obj.Index(i).Type()
74 }
75
76 if rc := FindOwnerType(obj.Index(i), name, depth+1, false); rc != nil {
77 return rc
78 }
79 }
80 default:
81 //fmt.Printf("%s Unhandled <%+v> ... It's a %+v\n", prefix, obj, k)
82 }
83
84 return nil
85}
86
87func FindKeyOwner(iface interface{}, name string, depth int) interface{} {
88 obj := reflect.ValueOf(iface)
89 k := obj.Kind()
90 switch k {
91 case reflect.Ptr:
92 t := obj.Type().Elem()
93 n := reflect.New(t)
94
95 if rc := FindKeyOwner(n.Elem().Interface(), name, depth+1); rc != nil {
96 return rc
97 }
98
99 case reflect.Struct:
100 for i := 0; i < obj.NumField(); i++ {
101 json := strings.Split(obj.Type().Field(i).Tag.Get("json"), ",")
102
103 if json[0] == name {
104 return obj.Type().Field(i).Type
105 }
106
107 if rc := FindKeyOwner(obj.Field(i).Interface(), name, depth+1); rc != nil {
108 return rc
109 }
110 }
111
112 case reflect.Slice:
113 s := reflect.MakeSlice(obj.Type(), 1, 1)
114 n := reflect.New(obj.Type())
115 n.Elem().Set(s)
116
117 for i := 0; i < n.Elem().Len(); i += 1 {
118 if rc := FindKeyOwner(n.Elem().Index(i).Interface(), name, depth+1); rc != nil {
119 return rc
120 }
121 }
122 default:
123 //fmt.Printf("%s Unhandled <%+v> ... It's a %+v\n", prefix, obj, k)
124 }
125
126 return nil
127}
128
129// FIXME: Need to figure out if GetAttributeValue and GetAttributeStructure can become one
130// Code is repeated in both, but outputs have a different purpose
131// Left as-is for now to get things working
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400132func GetAttributeValue(data interface{}, name string, depth int) (string, reflect.Value) {
133 var attribName string
134 var attribValue reflect.Value
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400135 obj := reflect.ValueOf(data)
136
137 if !obj.IsValid() {
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400138 return attribName, attribValue
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400139 }
140
141 k := obj.Kind()
142 switch k {
143 case reflect.Ptr:
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400144 if obj.IsNil() {
145 return attribName, attribValue
146 }
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400147
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400148 if attribName, attribValue = GetAttributeValue(obj.Elem().Interface(), name, depth+1); attribValue.IsValid() {
149 return attribName, attribValue
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400150 }
151
152 case reflect.Struct:
153 for i := 0; i < obj.NumField(); i++ {
154 json := strings.Split(obj.Type().Field(i).Tag.Get("json"), ",")
155
156 if json[0] == name {
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400157 return obj.Type().Field(i).Name, obj.Field(i)
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400158 }
159
160 if obj.Field(i).IsValid() {
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400161 if attribName, attribValue = GetAttributeValue(obj.Field(i).Interface(), name, depth+1); attribValue.IsValid() {
162 return attribName, attribValue
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400163 }
164 }
165 }
166
167 case reflect.Slice:
168 s := reflect.MakeSlice(obj.Type(), 1, 1)
169 n := reflect.New(obj.Type())
170 n.Elem().Set(s)
171
172 for i := 0; i < obj.Len(); i += 1 {
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400173 if attribName, attribValue = GetAttributeValue(obj.Index(i).Interface(), name, depth+1); attribValue.IsValid() {
174 return attribName, attribValue
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400175 }
176 }
177 default:
178 //fmt.Printf("%s Unhandled <%+v> ... It's a %+v\n", prefix, obj, k)
179 }
180
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400181 return attribName, attribValue
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400182
183}
184
185// FIXME: See GetAttributeValue(...) comment
186func GetAttributeStructure(data interface{}, name string, depth int) reflect.StructField {
187 var result reflect.StructField
188 obj := reflect.ValueOf(data)
189
190 if !obj.IsValid() {
191 return result
192 }
193
194 k := obj.Kind()
195 switch k {
196 case reflect.Ptr:
197 t := obj.Type().Elem()
198 n := reflect.New(t)
199
200 if rc := GetAttributeStructure(n.Elem().Interface(), name, depth+1); rc.Name != "" {
201 return rc
202 }
203
204 case reflect.Struct:
205 for i := 0; i < obj.NumField(); i++ {
206 v := reflect.Indirect(obj)
207 json := strings.Split(obj.Type().Field(i).Tag.Get("json"), ",")
208
209 if json[0] == name {
210 return v.Type().Field(i)
211 }
212
213 if obj.Field(i).IsValid() {
214 if rc := GetAttributeStructure(obj.Field(i).Interface(), name, depth+1); rc.Name != "" {
215 return rc
216 }
217 }
218 }
219
220 case reflect.Slice:
221 s := reflect.MakeSlice(obj.Type(), 1, 1)
222 n := reflect.New(obj.Type())
223 n.Elem().Set(s)
224
225 for i := 0; i < obj.Len(); i += 1 {
226 if rc := GetAttributeStructure(obj.Index(i).Interface(), name, depth+1); rc.Name != "" {
227 return rc
228 }
229
230 }
231 default:
232 //fmt.Printf("%s Unhandled <%+v> ... It's a %+v\n", prefix, obj, k)
233 }
234
235 return result
236
237}
238
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400239func Clone2(a interface{}) interface{} {
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400240 b := reflect.ValueOf(a)
241 buff := new(bytes.Buffer)
242 enc := gob.NewEncoder(buff)
243 dec := gob.NewDecoder(buff)
244 enc.Encode(a)
245 dec.Decode(b.Elem().Interface())
246
247 return b.Interface()
248}
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400249
250func Clone(a, b interface{}) interface{} {
251 buff := new(bytes.Buffer)
252 enc := gob.NewEncoder(buff)
253 dec := gob.NewDecoder(buff)
254 enc.Encode(a)
255 dec.Decode(b)
256 return b
257}