LCOV - code coverage report
Current view: top level - shared_model/builders/protobuf/builder_templates - query_template.hpp (source / functions) Hit Total Coverage
Test: cleared_cor.info Lines: 78 81 96.3 %
Date: 2019-03-07 14:46:43 Functions: 229 229 100.0 %

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

Generated by: LCOV version 1.13