1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "generator/internal/idempotency_policy_generator.h"
16 #include "google/cloud/internal/absl_str_cat_quiet.h"
17 #include "absl/memory/memory.h"
18 #include "generator/internal/codegen_utils.h"
19 #include "generator/internal/descriptor_utils.h"
20 #include "generator/internal/predicate_utils.h"
21 #include "generator/internal/printer.h"
22 #include <google/api/client.pb.h>
23 #include <google/protobuf/descriptor.h>
24 
25 namespace google {
26 namespace cloud {
27 namespace generator_internal {
28 
IdempotencyPolicyGenerator(google::protobuf::ServiceDescriptor const * service_descriptor,VarsDictionary service_vars,std::map<std::string,VarsDictionary> service_method_vars,google::protobuf::compiler::GeneratorContext * context)29 IdempotencyPolicyGenerator::IdempotencyPolicyGenerator(
30     google::protobuf::ServiceDescriptor const* service_descriptor,
31     VarsDictionary service_vars,
32     std::map<std::string, VarsDictionary> service_method_vars,
33     google::protobuf::compiler::GeneratorContext* context)
34     : ServiceCodeGenerator("idempotency_policy_header_path",
35                            "idempotency_policy_cc_path", service_descriptor,
36                            std::move(service_vars),
37                            std::move(service_method_vars), context) {}
38 
GenerateHeader()39 Status IdempotencyPolicyGenerator::GenerateHeader() {
40   HeaderPrint(CopyrightLicenseFileHeader());
41   HeaderPrint(  // clang-format off
42     "// Generated by the Codegen C++ plugin.\n"
43     "// If you make any local changes, they will be lost.\n"
44     "// source: $proto_file_name$\n"
45     "#ifndef $header_include_guard$\n"
46     "#define $header_include_guard$\n"
47     "\n");
48   // clang-format on
49 
50   // includes
51   HeaderLocalIncludes({"google/cloud/future.h",
52                        "google/cloud/internal/retry_policy.h",
53                        "google/cloud/status_or.h", "google/cloud/version.h"});
54   HeaderSystemIncludes({vars("proto_grpc_header_path"),
55                         "google/longrunning/operations.grpc.pb.h", "memory"});
56   HeaderPrint("\n");
57 
58   auto result = HeaderOpenNamespaces();
59   if (!result.ok()) return result;
60 
61   // Abstract interface ConnectionIdempotencyPolicy base class
62   HeaderPrint(  // clang-format off
63     "class $idempotency_class_name$ {\n"
64     " public:\n"
65     "  virtual ~$idempotency_class_name$() = 0;\n"
66     "\n");
67   // clang-format on
68 
69   HeaderPrint(  // clang-format off
70     "  /// Create a new copy of this object.\n"
71     "  virtual std::unique_ptr<$idempotency_class_name$> clone() const = 0;\n\n");
72   // clang-format on
73 
74   for (auto const& method : methods()) {
75     HeaderPrintMethod(
76         method,
77         {MethodPattern(
78              {
79                  // clang-format off
80    {"  virtual google::cloud::internal::Idempotency\n"
81     "  $method_name$($request_type$ const& request) = 0;\n"
82         "\n",}
83                  // clang-format on
84              },
85              All(IsNonStreaming, Not(IsPaginated))),
86          MethodPattern(
87              {
88                  // clang-format off
89    {"  virtual google::cloud::internal::Idempotency\n"
90     "  $method_name$($request_type$ request) = 0;\n"
91         "\n",}
92                  // clang-format on
93              },
94              All(IsNonStreaming, IsPaginated))},
95         __FILE__, __LINE__);
96   }
97 
98   // close abstract interface Connection base class
99   HeaderPrint(  // clang-format off
100     "};\n\n");
101   // clang-format on
102 
103   HeaderPrint(  // clang-format off
104       "std::unique_ptr<$idempotency_class_name$>\n"
105       "    MakeDefault$idempotency_class_name$();\n\n");
106   // clang-format on
107 
108   HeaderCloseNamespaces();
109   // close header guard
110   HeaderPrint(  // clang-format off
111       "#endif  // $header_include_guard$\n");
112   // clang-format on
113   return {};
114 }
115 
GenerateCc()116 Status IdempotencyPolicyGenerator::GenerateCc() {
117   CcPrint(CopyrightLicenseFileHeader());
118   CcPrint(  // clang-format off
119     "// Generated by the Codegen C++ plugin.\n"
120     "// If you make any local changes, they will be lost.\n"
121     "// source: $proto_file_name$\n\n");
122   // clang-format on
123 
124   // includes
125   CcLocalIncludes({vars("idempotency_policy_header_path")});
126   CcSystemIncludes({"memory"});
127   CcPrint("\n");
128 
129   auto result = CcOpenNamespaces();
130   if (!result.ok()) return result;
131 
132   CcPrint("using google::cloud::internal::Idempotency;\n\n");
133 
134   CcPrint(  // clang-format off
135     "$idempotency_class_name$::~$idempotency_class_name$() = default;\n\n");
136   // clang-format on
137 
138   // open anonymous namespace
139   CcPrint("namespace {\n");
140 
141   CcPrint(  // clang_format off
142       "class Default$idempotency_class_name$ : public "
143       "$idempotency_class_name$ {\n"
144       " public:\n"
145       "  ~Default$idempotency_class_name$() override = default;\n\n"
146       //  clang-format on
147   );
148 
149   CcPrint(  // clang-format off
150     "  /// Create a new copy of this object.\n"
151     "  std::unique_ptr<$idempotency_class_name$> clone() const override {\n"
152     "    return absl::make_unique<Default$idempotency_class_name$>(*this);\n"
153     "  }\n\n");
154   // clang-format on
155 
156   for (auto const& method : methods()) {
157     CcPrintMethod(
158         method,
159         {MethodPattern(
160              {
161                  // clang-format off
162    {"  Idempotency\n"
163     "  $method_name$($request_type$ const&) override {\n"
164     "    return Idempotency::$default_idempotency$;\n"
165     "  }\n\n",}
166                  // clang-format on
167              },
168              All(IsNonStreaming, Not(IsPaginated))),
169          MethodPattern(
170              {
171                  // clang-format off
172    {"  Idempotency\n"
173     "  $method_name$($request_type$) override {\n"
174     "    return Idempotency::$default_idempotency$;\n"
175     "  }\n\n",}
176                  // clang-format on
177              },
178              All(IsNonStreaming, IsPaginated))},
179         __FILE__, __LINE__);
180   }
181   CcPrint(  // clang-format off
182     "};\n"
183     "}  // namespace\n\n");
184   // clang-format on
185 
186   CcPrint(  // clang-format off
187       "std::unique_ptr<$idempotency_class_name$>\n"
188       "    MakeDefault$idempotency_class_name$() {\n"
189       "  return absl::make_unique<Default$idempotency_class_name$>();\n"
190       "}\n\n");
191   // clang-format on
192 
193   CcCloseNamespaces();
194   return {};
195 }
196 
197 }  // namespace generator_internal
198 }  // namespace cloud
199 }  // namespace google
200