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
+}