Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 :
6 : #ifndef IROHA_PROTO_QUERY_BUILDER_TEMPLATE_HPP
7 : #define IROHA_PROTO_QUERY_BUILDER_TEMPLATE_HPP
8 :
9 : #include <boost/range/algorithm/for_each.hpp>
10 :
11 : #include "backend/protobuf/queries/proto_query.hpp"
12 : #include "builders/protobuf/unsigned_proto.hpp"
13 : #include "interfaces/common_objects/types.hpp"
14 : #include "interfaces/transaction.hpp"
15 : #include "queries.pb.h"
16 : #include "validators/default_validator.hpp"
17 :
18 : namespace shared_model {
19 : namespace proto {
20 :
21 : /**
22 : * Template query builder for creating new types of query builders by
23 : * means of replacing template parameters
24 : * @tparam S -- field counter for checking that all required fields are
25 : * set
26 : * @tparam SV -- stateless validator called when build method is invoked
27 : * @tparam BT -- build type of built object returned by build method
28 : */
29 : template <int S = 0,
30 : typename SV = validation::DefaultUnsignedQueryValidator,
31 : typename BT = UnsignedWrapper<Query>>
32 : class DEPRECATED TemplateQueryBuilder {
33 : private:
34 : template <int, typename, typename>
35 : friend class TemplateQueryBuilder;
36 :
37 : enum RequiredFields {
38 : CreatedTime,
39 : CreatorAccountId,
40 : QueryField,
41 : QueryCounter,
42 : TOTAL
43 : };
44 :
45 : template <int s>
46 : using NextBuilder = TemplateQueryBuilder<S | (1 << s), SV, BT>;
47 :
48 : using ProtoQuery = iroha::protocol::Query;
49 :
50 : template <int Sp>
51 : TemplateQueryBuilder(const TemplateQueryBuilder<Sp, SV, BT> &o)
52 19 : : query_(o.query_), stateless_validator_(o.stateless_validator_) {}
53 :
54 : /**
55 : * Make transformation on copied content
56 : * @tparam Transformation - callable type for changing the copy
57 : * @param t - transform function for proto object
58 : * @return new builder with updated state
59 : */
60 : template <int Fields, typename Transformation>
61 : auto transform(Transformation t) const {
62 326 : NextBuilder<Fields> copy = *this;
63 326 : t(copy.query_);
64 326 : return copy;
65 326 : }
66 :
67 : /**
68 : * Make query field transformation on copied object
69 : * @tparam Transformation - callable type for changing query
70 : * @param t - transform function for proto query
71 : * @return new builder with set query
72 : */
73 : template <typename Transformation>
74 : auto queryField(Transformation t) const {
75 182 : NextBuilder<QueryField> copy = *this;
76 182 : t(copy.query_.mutable_payload());
77 182 : return copy;
78 182 : }
79 :
80 : public:
81 : TemplateQueryBuilder(const SV &validator = SV())
82 223 : : stateless_validator_(validator) {}
83 :
84 : auto createdTime(interface::types::TimestampType created_time) const {
85 : return transform<CreatedTime>([&](auto &qry) {
86 176 : qry.mutable_payload()->mutable_meta()->set_created_time(created_time);
87 176 : });
88 : }
89 :
90 : auto creatorAccountId(
91 : const interface::types::AccountIdType &creator_account_id) const {
92 : return transform<CreatorAccountId>([&](auto &qry) {
93 226 : qry.mutable_payload()->mutable_meta()->set_creator_account_id(
94 226 : creator_account_id);
95 226 : });
96 : }
97 :
98 : auto queryCounter(interface::types::CounterType query_counter) const {
99 : return transform<QueryCounter>([&](auto &qry) {
100 212 : qry.mutable_payload()->mutable_meta()->set_query_counter(
101 212 : query_counter);
102 212 : });
103 : }
104 :
105 : auto getAccount(const interface::types::AccountIdType &account_id) const {
106 : return queryField([&](auto proto_query) {
107 39 : auto query = proto_query->mutable_get_account();
108 39 : query->set_account_id(account_id);
109 39 : });
110 : }
111 :
112 : auto getSignatories(
113 : const interface::types::AccountIdType &account_id) const {
114 : return queryField([&](auto proto_query) {
115 23 : auto query = proto_query->mutable_get_signatories();
116 23 : query->set_account_id(account_id);
117 23 : });
118 : }
119 :
120 : auto getAccountTransactions(
121 : const interface::types::AccountIdType &account_id) const {
122 : return queryField([&](auto proto_query) {
123 19 : auto query = proto_query->mutable_get_account_transactions();
124 19 : query->set_account_id(account_id);
125 19 : });
126 : }
127 :
128 : auto getAccountAssetTransactions(
129 : const interface::types::AccountIdType &account_id,
130 : const interface::types::AssetIdType &asset_id) const {
131 : return queryField([&](auto proto_query) {
132 17 : auto query = proto_query->mutable_get_account_asset_transactions();
133 17 : query->set_account_id(account_id);
134 17 : query->set_asset_id(asset_id);
135 17 : });
136 : }
137 :
138 : auto getAccountAssets(
139 : const interface::types::AccountIdType &account_id) const {
140 : return queryField([&](auto proto_query) {
141 23 : auto query = proto_query->mutable_get_account_assets();
142 23 : query->set_account_id(account_id);
143 23 : });
144 : }
145 :
146 : auto getAccountDetail(
147 : const interface::types::AccountIdType &account_id = "",
148 : const interface::types::AccountDetailKeyType &key = "",
149 : const interface::types::AccountIdType &writer = "") {
150 : return queryField([&](auto proto_query) {
151 24 : auto query = proto_query->mutable_get_account_detail();
152 24 : if (not account_id.empty()) {
153 23 : query->set_account_id(account_id);
154 23 : }
155 24 : if (not key.empty()) {
156 2 : query->set_key(key);
157 2 : }
158 24 : if (not writer.empty()) {
159 2 : query->set_writer(writer);
160 2 : }
161 24 : });
162 : }
163 :
164 : auto getRoles() const {
165 21 : return queryField(
166 : [&](auto proto_query) { proto_query->mutable_get_roles(); });
167 : }
168 :
169 : auto getAssetInfo(const interface::types::AssetIdType &asset_id) const {
170 : return queryField([&](auto proto_query) {
171 6 : auto query = proto_query->mutable_get_asset_info();
172 6 : query->set_asset_id(asset_id);
173 6 : });
174 : }
175 :
176 : auto getRolePermissions(
177 : const interface::types::RoleIdType &role_id) const {
178 : return queryField([&](auto proto_query) {
179 5 : auto query = proto_query->mutable_get_role_permissions();
180 5 : query->set_role_id(role_id);
181 5 : });
182 : }
183 :
184 : template <typename Collection>
185 : auto getTransactions(const Collection &hashes) const {
186 : return queryField([&](auto proto_query) {
187 40 : auto query = proto_query->mutable_get_transactions();
188 : boost::for_each(hashes, [&query](const auto &hash) {
189 42 : query->add_tx_hashes(toBinaryString(hash));
190 42 : });
191 40 : });
192 : }
193 :
194 : auto getTransactions(
195 : std::initializer_list<interface::types::HashType> hashes) const {
196 : return getTransactions(hashes);
197 : }
198 :
199 : template <typename... Hash>
200 : auto getTransactions(const Hash &... hashes) const {
201 : return getTransactions({hashes...});
202 : }
203 :
204 : auto getPendingTransactions() const {
205 : return queryField([&](auto proto_query) {
206 5 : proto_query->mutable_get_pending_transactions();
207 5 : });
208 : }
209 :
210 : auto build() const {
211 : static_assert(S == (1 << TOTAL) - 1, "Required fields are not set");
212 223 : if (not query_.has_payload()) {
213 0 : throw std::invalid_argument("Query missing payload");
214 : }
215 223 : if (query_.payload().query_case()
216 223 : == iroha::protocol::Query_Payload::QueryCase::QUERY_NOT_SET) {
217 1 : throw std::invalid_argument("Missing concrete query");
218 : }
219 222 : auto result = Query(iroha::protocol::Query(query_));
220 222 : auto answer = stateless_validator_.validate(result);
221 221 : if (answer.hasErrors()) {
222 0 : throw std::invalid_argument(answer.reason());
223 : }
224 221 : return BT(std::move(result));
225 221 : }
226 :
227 : static const int total = RequiredFields::TOTAL;
228 :
229 : private:
230 : ProtoQuery query_;
231 : SV stateless_validator_;
232 : };
233 : } // namespace proto
234 : } // namespace shared_model
235 :
236 : #endif // IROHA_PROTO_QUERY_BUILDER_TEMPLATE_HPP
|