VOL-1027 : Initial commit of voltha 2.0 data model
Change-Id: Ib8006de1af2166281ccf1c9d7c2b9156991bf4e4
diff --git a/db/model/child_type.go b/db/model/child_type.go
new file mode 100644
index 0000000..73f79a3
--- /dev/null
+++ b/db/model/child_type.go
@@ -0,0 +1,107 @@
+package model
+
+import (
+ "fmt"
+ desc "github.com/golang/protobuf/descriptor"
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ "github.com/opencord/voltha/protos/go/common"
+ "reflect"
+ "strconv"
+ "sync"
+)
+
+type singleton struct {
+ ChildrenFieldsCache map[interface{}]map[string]*ChildType
+}
+
+var instance *singleton
+var once sync.Once
+
+func GetInstance() *singleton {
+ once.Do(func() {
+ instance = &singleton{}
+ })
+ return instance
+}
+
+type ChildType struct {
+ ClassModule string
+ ClassType reflect.Type
+ IsContainer bool
+ Key string
+ KeyFromStr func(s string) interface{}
+}
+
+func ChildrenFields(cls interface{}) map[string]*ChildType {
+ if cls == nil {
+ return nil
+ }
+ var names map[string]*ChildType
+ var names_exist bool
+
+ if GetInstance().ChildrenFieldsCache == nil {
+ GetInstance().ChildrenFieldsCache = make(map[interface{}]map[string]*ChildType)
+ }
+
+ msgType := reflect.TypeOf(cls)
+
+ if names, names_exist = GetInstance().ChildrenFieldsCache[msgType.String()]; !names_exist {
+ names = make(map[string]*ChildType)
+
+ _, md := desc.ForMessage(cls.(desc.Message))
+
+ // TODO: Do we need to validate MD for nil, panic or exception?
+ for _, field := range md.Field {
+ if options := field.GetOptions(); options != nil {
+ if proto.HasExtension(options, common.E_ChildNode) {
+ isContainer := *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
+ meta, _ := proto.GetExtension(options, common.E_ChildNode)
+ var keyFromStr func(string) interface{}
+
+ if meta.(*common.ChildNode).GetKey() == "" {
+ fmt.Println("Child key is empty ... moving on")
+ } else {
+ parentType := FindOwnerType(reflect.ValueOf(cls), field.GetName(), 0, false)
+ keyType := FindKeyOwner(reflect.New(parentType).Elem().Interface(), meta.(*common.ChildNode).GetKey(), 0)
+
+ switch keyType.(reflect.Type).Name() {
+ case "string":
+ keyFromStr = func(s string) interface{} {
+ return s
+ }
+ case "int32":
+ fallthrough
+ case "int64":
+ fallthrough
+ case "uint32":
+ fallthrough
+ case "uint64":
+ keyFromStr = func(s string) interface{} {
+ i, _ := strconv.Atoi(s)
+ return i
+ }
+ default:
+ fmt.Errorf("Key type not implemented - type: %s\n", keyType.(reflect.Type))
+ }
+
+ ct := ChildType{
+ ClassModule: parentType.String(),
+ ClassType: parentType,
+ IsContainer: isContainer,
+ Key: meta.(*common.ChildNode).GetKey(),
+ KeyFromStr: keyFromStr,
+ }
+
+ names[field.GetName()] = &ct
+
+ }
+ }
+ }
+ }
+
+ GetInstance().ChildrenFieldsCache[msgType.String()] = names
+ }
+
+ return names
+}