blob: 497b3f67ed8b8f4d0b331bdccb5e1e5c1af79a9f [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
132func GetAttributeValue(data interface{}, name string, depth int) reflect.Value {
133 var result reflect.Value
134 obj := reflect.ValueOf(data)
135
136 if !obj.IsValid() {
137 return result
138 }
139
140 k := obj.Kind()
141 switch k {
142 case reflect.Ptr:
143 t := obj.Type().Elem()
144 n := reflect.New(t)
145
146 if rc := GetAttributeValue(n.Elem().Interface(), name, depth+1); rc.IsValid() {
147 return rc
148 }
149
150 case reflect.Struct:
151 for i := 0; i < obj.NumField(); i++ {
152 json := strings.Split(obj.Type().Field(i).Tag.Get("json"), ",")
153
154 if json[0] == name {
155 return obj.Field(i)
156 }
157
158 if obj.Field(i).IsValid() {
159 if rc := GetAttributeValue(obj.Field(i).Interface(), name, depth+1); rc.IsValid() {
160 return rc
161 }
162 }
163 }
164
165 case reflect.Slice:
166 s := reflect.MakeSlice(obj.Type(), 1, 1)
167 n := reflect.New(obj.Type())
168 n.Elem().Set(s)
169
170 for i := 0; i < obj.Len(); i += 1 {
171 if rc := GetAttributeValue(obj.Index(i).Interface(), name, depth+1); rc.IsValid() {
172 return rc
173 }
174 }
175 default:
176 //fmt.Printf("%s Unhandled <%+v> ... It's a %+v\n", prefix, obj, k)
177 }
178
179 return result
180
181}
182
183// FIXME: See GetAttributeValue(...) comment
184func GetAttributeStructure(data interface{}, name string, depth int) reflect.StructField {
185 var result reflect.StructField
186 obj := reflect.ValueOf(data)
187
188 if !obj.IsValid() {
189 return result
190 }
191
192 k := obj.Kind()
193 switch k {
194 case reflect.Ptr:
195 t := obj.Type().Elem()
196 n := reflect.New(t)
197
198 if rc := GetAttributeStructure(n.Elem().Interface(), name, depth+1); rc.Name != "" {
199 return rc
200 }
201
202 case reflect.Struct:
203 for i := 0; i < obj.NumField(); i++ {
204 v := reflect.Indirect(obj)
205 json := strings.Split(obj.Type().Field(i).Tag.Get("json"), ",")
206
207 if json[0] == name {
208 return v.Type().Field(i)
209 }
210
211 if obj.Field(i).IsValid() {
212 if rc := GetAttributeStructure(obj.Field(i).Interface(), name, depth+1); rc.Name != "" {
213 return rc
214 }
215 }
216 }
217
218 case reflect.Slice:
219 s := reflect.MakeSlice(obj.Type(), 1, 1)
220 n := reflect.New(obj.Type())
221 n.Elem().Set(s)
222
223 for i := 0; i < obj.Len(); i += 1 {
224 if rc := GetAttributeStructure(obj.Index(i).Interface(), name, depth+1); rc.Name != "" {
225 return rc
226 }
227
228 }
229 default:
230 //fmt.Printf("%s Unhandled <%+v> ... It's a %+v\n", prefix, obj, k)
231 }
232
233 return result
234
235}
236
237func Clone(a interface{}) interface{} {
238 b := reflect.ValueOf(a)
239 buff := new(bytes.Buffer)
240 enc := gob.NewEncoder(buff)
241 dec := gob.NewDecoder(buff)
242 enc.Encode(a)
243 dec.Decode(b.Elem().Interface())
244
245 return b.Interface()
246}