-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathpagination.go
123 lines (99 loc) · 3.5 KB
/
pagination.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package testing
import (
"container/list"
"strings"
"github.com/hyperledger/fabric-chaincode-go/shim"
"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
pb "github.com/hyperledger/fabric-protos-go/peer"
"github.com/pkg/errors"
)
// MockStateRangeQueryPagedIterator represents paged version of shimtest.MockStateRangeQueryIterator
type MockStateRangeQueryPagedIterator struct {
Closed bool
Stub *MockStub
Keys *list.List
Current *list.Element
nextBookmark string
}
func (iter *MockStateRangeQueryPagedIterator) Len() int32 {
return int32(iter.Keys.Len())
}
func (iter *MockStateRangeQueryPagedIterator) NextBookmark() string {
return iter.nextBookmark
}
func (iter *MockStateRangeQueryPagedIterator) Close() error {
iter.Closed = true
return nil
}
func (iter *MockStateRangeQueryPagedIterator) HasNext() bool {
return iter.Current != nil
}
func (iter *MockStateRangeQueryPagedIterator) Next() (*queryresult.KV, error) {
if iter.Closed {
err := errors.New("MockStateRangeQueryPagedIterator.Next() called after Close()")
return nil, err
}
if !iter.HasNext() {
err := errors.New("MockStateRangeQueryPagedIterator.Next() called when it does not HaveNext()")
return nil, err
}
key := iter.Current.Value.(string)
value, err := iter.Stub.GetState(key)
iter.Current = iter.Current.Next()
return &queryresult.KV{Key: key, Value: value}, err
}
// NewMockStatesRangeQueryPagedIterator creates iterator starting from bookmark
// and limited by pageSize
func NewMockStatesRangeQueryPagedIterator(stub *MockStub, startKey string, endKey string, pageSize int32, bookmark string) *MockStateRangeQueryPagedIterator {
iter := new(MockStateRangeQueryPagedIterator)
iter.Stub = stub
iter.Keys = new(list.List)
var elem = stub.Keys.Front()
// rewind until bookmark if is set
for bookmark != "" && elem != nil {
if elem.Value.(string) == bookmark {
break
}
elem = elem.Next()
}
// Loop through keys until pageSize exceeded and find bookmark for next page
for elem != nil {
comp1 := strings.Compare(elem.Value.(string), startKey)
comp2 := strings.Compare(elem.Value.(string), endKey)
if (comp1 >= 0 && comp2 < 0) || (startKey == "" && endKey == "") {
if iter.Keys.Len() < int(pageSize) {
iter.Keys.PushBack(elem.Value)
elem = elem.Next()
continue
}
iter.nextBookmark = elem.Value.(string)
break
}
elem = elem.Next()
}
iter.Current = iter.Keys.Front()
return iter
}
// GetStateByPartialCompositeKeyWithPagination mocked
func (stub *MockStub) GetStateByPartialCompositeKeyWithPagination(objectType string, keys []string,
pageSize int32, bookmark string) (shim.StateQueryIteratorInterface, *pb.QueryResponseMetadata, error) {
partialCompositeKey, err := stub.CreateCompositeKey(objectType, keys)
if err != nil {
return nil, nil, err
}
iter := NewMockStatesRangeQueryPagedIterator(
stub, partialCompositeKey, partialCompositeKey+string(maxUnicodeRuneValue), pageSize, bookmark)
return iter, &pb.QueryResponseMetadata{
FetchedRecordsCount: iter.Len(),
Bookmark: iter.NextBookmark(),
}, nil
}
// GetStateByRangeWithPagination mocked
func (stub *MockStub) GetStateByRangeWithPagination(startKey, endKey string, pageSize int32,
bookmark string) (shim.StateQueryIteratorInterface, *pb.QueryResponseMetadata, error) {
iter := NewMockStatesRangeQueryPagedIterator(stub, startKey, endKey, pageSize, bookmark)
return iter, &pb.QueryResponseMetadata{
FetchedRecordsCount: iter.Len(),
Bookmark: iter.NextBookmark(),
}, nil
}