forked from CesiumGS/cesium-native
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPagedList.h
More file actions
164 lines (143 loc) · 5 KB
/
PagedList.h
File metadata and controls
164 lines (143 loc) · 5 KB
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#pragma once
#include <CesiumAsync/AsyncSystem.h>
#include <CesiumAsync/Future.h>
#include <CesiumUtility/JsonHelpers.h>
#include <CesiumUtility/Result.h>
#include <rapidjson/document.h>
#include <functional>
#include <optional>
#include <string>
#include <vector>
namespace CesiumITwinClient {
class Connection;
/**
* @brief Allows access to a set of resources from a paginated list.
*
* Many endpoints in the iTwin API return links to the previous and next pages,
* if any, in their results. This class allows these links to be easily
* traversed.
*/
template <typename T> class PagedList {
public:
/**
* @brief Callback used to obtain a page of results from a URL.
*/
using PageOperation = std::function<CesiumAsync::Future<
CesiumUtility::Result<PagedList<T>>>(Connection&, const std::string&)>;
/**
* @brief Creates a new `PagedList` from a set of items, an iTwin API
* response, and a callback to retrieve more items.
*
* @param doc The JSON document obtained from the iTwin API.
* @param items The parsed items that should be returned to the user.
* @param operation Callback that can obtain a new page of results from a
* given URL.
*/
PagedList(
rapidjson::Document& doc,
std::vector<T>&& items,
PageOperation&& operation)
: _operation(std::move(operation)), _items(std::move(items)) {
const auto& linksMember = doc.FindMember("_links");
if (linksMember != doc.MemberEnd() && linksMember->value.IsObject()) {
const auto& selfMember = linksMember->value.FindMember("self");
if (selfMember != doc.MemberEnd() && selfMember->value.IsObject()) {
this->_selfUrl = CesiumUtility::JsonHelpers::getStringOrDefault(
selfMember->value,
"href",
"");
}
const auto& nextMember = linksMember->value.FindMember("next");
if (nextMember != doc.MemberEnd() && nextMember->value.IsObject()) {
this->_nextUrl = CesiumUtility::JsonHelpers::getStringOrDefault(
nextMember->value,
"href",
"");
}
const auto& prevMember = linksMember->value.FindMember("prev");
if (prevMember != doc.MemberEnd() && prevMember->value.IsObject()) {
this->_prevUrl = CesiumUtility::JsonHelpers::getStringOrDefault(
prevMember->value,
"href",
"");
}
}
}
/**
* @brief Returns the contained item at `index`.
*/
T& operator[](size_t index) { return _items[index]; }
/**
* @brief Returns the contained item at `index`.
*/
const T& operator[](size_t index) const { return _items[index]; }
/**
* @brief Returns the number of contained items.
*/
size_t size() const { return _items.size(); }
/**
* @brief The `begin` iterator of the underlying vector.
*/
auto begin() { return _items.begin(); }
/**
* @brief The `begin` iterator of the underlying vector.
*/
auto begin() const { return _items.begin(); }
/**
* @brief The `end` iterator of the underlying vector.
*/
auto end() { return _items.end(); }
/**
* @brief The `end` iterator of the underlying vector.
*/
auto end() const { return _items.end(); }
/**
* @brief Checks whether this PagedList contains a URL to another page that
* can be fetched.
*/
bool hasNextUrl() const { return this->_nextUrl.has_value(); }
/**
* @brief Checks whether this PagedList contains a URL to a previous page that
* can be fetched.
*/
bool hasPrevUrl() const { return this->_prevUrl.has_value(); }
/**
* @brief Returns a future that will return the next page of items.
*
* @param asyncSystem The `AsyncSystem` to use.
* @param connection The `Connection` to use to fetch the next page of
* results.
*/
CesiumAsync::Future<CesiumUtility::Result<PagedList<T>>>
next(CesiumAsync::AsyncSystem& asyncSystem, Connection& connection) const {
if (!this->_nextUrl.has_value()) {
return asyncSystem
.createResolvedFuture<CesiumUtility::Result<PagedList<T>>>(
CesiumUtility::Result<PagedList<T>>(CesiumUtility::ErrorList{}));
}
return _operation(connection, *this->_nextUrl);
}
/**
* @brief Returns a future that will return the previous page of items.
*
* @param asyncSystem The `AsyncSystem` to use.
* @param connection The `Connection` to use to fetch the previous page of
* results.
*/
CesiumAsync::Future<CesiumUtility::Result<PagedList<T>>>
prev(CesiumAsync::AsyncSystem& asyncSystem, Connection& connection) const {
if (!this->_prevUrl.has_value()) {
return asyncSystem
.createResolvedFuture<CesiumUtility::Result<PagedList<T>>>(
CesiumUtility::Result<PagedList<T>>(CesiumUtility::ErrorList{}));
}
return _operation(connection, *this->_prevUrl);
}
private:
PageOperation _operation;
std::vector<T> _items;
std::optional<std::string> _selfUrl = std::nullopt;
std::optional<std::string> _nextUrl = std::nullopt;
std::optional<std::string> _prevUrl = std::nullopt;
};
}; // namespace CesiumITwinClient