From c8431a63e8b94ac57d506e2af8738b189f578617 Mon Sep 17 00:00:00 2001 From: Pawan Rawal <pawan0201@gmail.com> Date: Thu, 28 Apr 2016 10:21:40 +0530 Subject: [PATCH] Added helper methods for protocol buffer response. Parsing and modifying the subgraph returned in the response. Provided helper methods for the response. --- client/client.go | 105 ++++++++++++++++++++++++++++++++++++------ client/client_test.go | 70 +++++++++++++++++----------- 2 files changed, 135 insertions(+), 40 deletions(-) diff --git a/client/client.go b/client/client.go index 41e7f304..58dfdb32 100644 --- a/client/client.go +++ b/client/client.go @@ -18,25 +18,104 @@ package client import "github.com/dgraph-io/dgraph/query/pb" -func NumChildren(resp *pb.GraphResponse) int { - return len(resp.Children) +type Entity struct { + Attribute string + values map[string][]byte + gr *pb.GraphResponse // Reference to iteratively build the entity + uid uint64 + children []*Entity } -func HasValue(resp *pb.GraphResponse) bool { - for _, val := range resp.Result.Values { - if len(val) > 0 { - return true +// This function performs a binary search on the uids slice and returns the +// index at which it finds the uid, else returns -1 +func search(uid uint64, uids []uint64) int { + low, mid, high := 0, 0, len(uids)-1 + for low <= high { + mid = (low + high) / 2 + if uids[mid] == uid { + return mid + } else if uids[mid] > uid { + high = mid - 1 + } else { + low = mid + 1 } } - return false + return -1 } -func Values(resp *pb.GraphResponse) []string { - values := []string{} - for _, val := range resp.Result.Values { - if len(val) > 0 { - values = append(values, string(val)) +// This method populates the values and children for an entity +func (e *Entity) populate() { + m := make(map[string][]byte) + for _, grChild := range e.gr.Children { + // Index of the uid of the parent node in the query uids of the child. This + // is used to get the appropriate value or uidlist for the child. + // TODO(pawan) - Log error if i == -1 + i := search(e.uid, grChild.Query.Uids) + // This means its a leaf node + if len(grChild.Children) == 0 { + m[grChild.Attribute] = grChild.Result.Values[i] + } else { + // An entity would have as many children as the length of UidList for its + // child node. + for _, uid := range grChild.Result.Uidmatrix[i].Uids { + cEntity := new(Entity) + cEntity.gr = grChild + cEntity.Attribute = grChild.Attribute + cEntity.uid = uid + e.children = append(e.children, cEntity) + } } } - return values + e.values = m +} + +// This method is used to initialize the root entity +func NewEntity(root *pb.GraphResponse) *Entity { + e := new(Entity) + e.Attribute = root.Attribute + e.uid = root.Result.Uidmatrix[0].Uids[0] + e.gr = root + e.populate() + return e +} + +// This method returns the list of properties for an entity. +func (e *Entity) Properties() []string { + properties := make([]string, len(e.values)) + i := 0 + for k := range e.values { + properties[i] = k + i++ + } + return properties +} + +// This method returns whether a property exists for an entity or not. +func (e *Entity) HasValue(property string) bool { + _, ok := e.values[property] + return ok +} + +// This method returns the value corresponding to a property if one exists. +func (e *Entity) Value(property string) []byte { + val, _ := e.values[property] + return val +} + +// This method populates the children for an entity and returns them. +func (e *Entity) Children() []*Entity { + for _, child := range e.children { + // This makes sure that children are populated only once. + // TODO(pawan) - Discuss with Manish if it makes sense to have a flag for + // this. + if len(child.children) == 0 && child.values == nil { + child.populate() + } + } + return e.children +} + +// This method returns the number of children for an entity. +func (e *Entity) NumChildren() int { + return len(e.children) } diff --git a/client/client_test.go b/client/client_test.go index 345f62ac..21ab8372 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -142,43 +142,59 @@ func TestQuery(t *testing.T) { return } - if NumChildren(resp) != 4 { - t.Errorf("Expected 4 children, Got: %v", NumChildren(resp)) + root := NewEntity(resp) + + if root.Attribute != "_root_" { + t.Errorf("Expected attribute _root_, Got: %v", root.Attribute) } - if HasValue(resp) { - t.Errorf("Expected HasValue to return false, Got: true") + if len(root.Properties()) != 3 { + t.Errorf("Expected 3 properties for entity, Got: %v", + len(root.Properties())) } - - child := resp.Children[0] - if child.Attribute != "name" { - t.Errorf("Expected attribute name, Got: %v", child.Attribute) + if !root.HasValue("name") { + t.Errorf("Expected entity to have value for name, Got: false") + } + if root.HasValue("names") { + t.Errorf("Expected entity to not have value for names, Got: true") } - if !HasValue(child) { - t.Errorf("Expected HasValue to return true, Got: false") + if string(root.Value("name")) != "Michonne" { + t.Errorf("Expected value for name to be Michonne, Got: %v", + string(root.Value("name"))) } - if Values(child)[0] != "Michonne" { - t.Errorf("Expected Value to return Michonee, Got %v", Values(child)[0]) + if len(root.Value("names")) != 0 { + t.Errorf("Expected values for names to return empty byte slice, Got: len", + len(root.Value("names"))) + } + if root.NumChildren() != 5 { + t.Errorf("Expected entity to have 5 children, Got: %v", root.NumChildren()) } - child = resp.Children[3] - if child.Attribute != "friend" { - t.Errorf("Expected attribute friend, Got: %v", child.Attribute) + child := root.Children()[0] + if !child.HasValue("name") { + t.Errorf("Expected entity to have value for name, Got: false") } - if NumChildren(child) != 1 { - t.Errorf("Expected 1 child, Got: %v", NumChildren(child)) + if string(child.Value("name")) != "Rick Grimes" { + t.Errorf("Expected child to have name value Rick Grimes, Got: ", + string(child.Value("name"))) } - if HasValue(child) { - t.Errorf("Expected HasValue to return false, Got: true") + child = root.Children()[1] + if string(child.Value("name")) != "Glenn Rhee" { + t.Errorf("Expected child to have name value Glenn Rhee, Got: ", + string(child.Value("name"))) } - - child = child.Children[0] - if child.Attribute != "name" { - t.Errorf("Expected attribute name, Got: %v", child.Attribute) + child = root.Children()[2] + if string(child.Value("name")) != "Daryl Dixon" { + t.Errorf("Expected child to have name value Daryl Dixon, Got: ", + string(child.Value("name"))) } - if !HasValue(child) { - t.Errorf("Expected HasValue to return true, Got: false") + child = root.Children()[3] + if string(child.Value("name")) != "Andrea" { + t.Errorf("Expected child to have name value Andrea, Got: ", + string(child.Value("name"))) } - if len(Values(child)) != 4 { - t.Errorf("Expected 4 Values. Got: %v", len(Values(child))) + child = root.Children()[4] + if string(child.Value("name")) != "" { + t.Errorf("Expected child to have name empty name value, Got: ", + string(child.Value("name"))) } } -- GitLab