VOL-1027 : Initial commit of voltha 2.0 data model
Change-Id: Ib8006de1af2166281ccf1c9d7c2b9156991bf4e4
diff --git a/db/model/revision.go b/db/model/revision.go
new file mode 100644
index 0000000..06a04ae
--- /dev/null
+++ b/db/model/revision.go
@@ -0,0 +1,143 @@
+package model
+
+import (
+ "bytes"
+ "crypto/md5"
+ "fmt"
+ "reflect"
+ "sort"
+)
+
+var (
+ RevisionCache = make(map[string]interface{})
+)
+
+type Revision struct {
+ Config *DataRevision
+ Children map[string][]*Revision
+ Hash string
+ branch *Branch
+ WeakRef string
+}
+
+func NewRevision(branch *Branch, data interface{}, children map[string][]*Revision) *Revision {
+ cr := &Revision{}
+ cr.branch = branch
+ cr.Config = NewDataRevision(data)
+ cr.Children = children
+ cr.finalize()
+
+ return cr
+}
+
+func (cr *Revision) finalize() {
+ cr.Hash = cr.hashContent()
+
+ if _, exists := RevisionCache[cr.Hash]; !exists {
+ RevisionCache[cr.Hash] = cr
+ }
+ if _, exists := RevisionCache[cr.Config.Hash]; !exists {
+ RevisionCache[cr.Config.Hash] = cr.Config
+ } else {
+ cr.Config = RevisionCache[cr.Config.Hash].(*DataRevision)
+ }
+}
+
+func (cr *Revision) hashContent() string {
+ var buffer bytes.Buffer
+ var childrenKeys []string
+
+ if cr.Config != nil {
+ buffer.WriteString(cr.Config.Hash)
+ }
+
+ for key, _ := range cr.Children {
+ childrenKeys = append(childrenKeys, key)
+ }
+ sort.Strings(childrenKeys)
+
+ if cr.Children != nil && len(cr.Children) > 0 {
+ // Loop through sorted Children keys
+ for _, key := range childrenKeys {
+ for _, child := range cr.Children[key] {
+ buffer.WriteString(child.Hash)
+ }
+ }
+ }
+
+ return fmt.Sprintf("%x", md5.Sum(buffer.Bytes()))[:12]
+}
+
+func (cr *Revision) getData() interface{} {
+ if cr.Config == nil {
+ return nil
+ }
+ return cr.Config.Data
+}
+
+func (cr *Revision) getNode() *Node {
+ return cr.branch.node
+}
+
+func (cr *Revision) getType() reflect.Type {
+ // TODO: what is this returning really?
+ return reflect.TypeOf(cr.getData())
+}
+
+func (cr *Revision) clearHash() {
+ cr.Hash = ""
+}
+
+func (cr *Revision) Get(depth int) interface{} {
+ originalData := cr.getData()
+ data := Clone(originalData)
+
+ if depth > 0 {
+ for fieldName, field := range ChildrenFields(cr.getType()) {
+ if field.IsContainer {
+ for _, rev := range cr.Children[fieldName] {
+ childData := rev.Get(depth - 1)
+ childDataHolder := GetAttributeValue(data, fieldName, 0)
+ // TODO: merge with childData
+ fmt.Printf("data:%+v, dataHolder:%+v", childData, childDataHolder)
+ }
+ } else {
+ rev := cr.Children[fieldName][0]
+ childData := rev.Get(depth - 1)
+ childDataHolder := GetAttributeValue(data, fieldName, 0)
+ // TODO: merge with childData
+ fmt.Printf("data:%+v, dataHolder:%+v", childData, childDataHolder)
+ }
+ }
+ }
+ return data
+}
+
+func (cr *Revision) UpdateData(data interface{}, branch *Branch) *Revision {
+ newRev := Clone(cr).(*Revision)
+ newRev.branch = branch
+ newRev.Config = data.(*DataRevision)
+ newRev.finalize()
+
+ return newRev
+}
+
+func (cr *Revision) UpdateChildren(name string, children []*Revision, branch *Branch) *Revision {
+ newChildren := Clone(cr.Children).(map[string][]*Revision)
+ newChildren[name] = children
+ newRev := Clone(cr).(*Revision)
+ newRev.branch = branch
+ newRev.Children = newChildren
+ newRev.finalize()
+
+ return newRev
+}
+
+func (cr *Revision) UpdateAllChildren(children map[string][]*Revision, branch *Branch) *Revision {
+ newRev := Clone(cr).(*Revision)
+ newRev.branch = branch
+ newRev.Children = children
+ newRev.finalize()
+
+ return newRev
+}