1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#include <google/protobuf/compiler/java/map_field.h>
32
33#include <google/protobuf/io/printer.h>
34#include <google/protobuf/compiler/java/context.h>
35#include <google/protobuf/compiler/java/doc_comment.h>
36#include <google/protobuf/compiler/java/helpers.h>
37#include <google/protobuf/compiler/java/name_resolver.h>
38
39// Must be last.
40#include <google/protobuf/port_def.inc>
41
42namespace google {
43namespace protobuf {
44namespace compiler {
45namespace java {
46
47namespace {
48
49const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
50 GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
51 const Descriptor* message = descriptor->message_type();
52 GOOGLE_CHECK(message->options().map_entry());
53 return message->map_key();
54}
55
56const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
57 GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
58 const Descriptor* message = descriptor->message_type();
59 GOOGLE_CHECK(message->options().map_entry());
60 return message->map_value();
61}
62
63std::string TypeName(const FieldDescriptor* field,
64 ClassNameResolver* name_resolver, bool boxed) {
65 if (GetJavaType(field) == JAVATYPE_MESSAGE) {
66 return name_resolver->GetImmutableClassName(descriptor: field->message_type());
67 } else if (GetJavaType(field) == JAVATYPE_ENUM) {
68 return name_resolver->GetImmutableClassName(descriptor: field->enum_type());
69 } else {
70 return boxed ? BoxedPrimitiveTypeName(type: GetJavaType(field))
71 : PrimitiveTypeName(type: GetJavaType(field));
72 }
73}
74
75std::string KotlinTypeName(const FieldDescriptor* field,
76 ClassNameResolver* name_resolver) {
77 if (GetJavaType(field) == JAVATYPE_MESSAGE) {
78 return name_resolver->GetImmutableClassName(descriptor: field->message_type());
79 } else if (GetJavaType(field) == JAVATYPE_ENUM) {
80 return name_resolver->GetImmutableClassName(descriptor: field->enum_type());
81 } else {
82 return KotlinTypeName(type: GetJavaType(field));
83 }
84}
85
86std::string WireType(const FieldDescriptor* field) {
87 return "com.google.protobuf.WireFormat.FieldType." +
88 std::string(FieldTypeName(field_type: field->type()));
89}
90
91void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
92 int builderBitIndex, const FieldGeneratorInfo* info,
93 Context* context,
94 std::map<std::string, std::string>* variables) {
95 SetCommonFieldVariables(descriptor, info, variables);
96 ClassNameResolver* name_resolver = context->GetNameResolver();
97
98 (*variables)["type"] =
99 name_resolver->GetImmutableClassName(descriptor: descriptor->message_type());
100 const FieldDescriptor* key = KeyField(descriptor);
101 const FieldDescriptor* value = ValueField(descriptor);
102 const JavaType keyJavaType = GetJavaType(field: key);
103 const JavaType valueJavaType = GetJavaType(field: value);
104
105 std::string pass_through_nullness = "/* nullable */\n";
106
107 (*variables)["key_type"] = TypeName(field: key, name_resolver, boxed: false);
108 std::string boxed_key_type = TypeName(field: key, name_resolver, boxed: true);
109 (*variables)["boxed_key_type"] = boxed_key_type;
110 (*variables)["kt_key_type"] = KotlinTypeName(field: key, name_resolver);
111 (*variables)["kt_value_type"] = KotlinTypeName(field: value, name_resolver);
112 // Used for calling the serialization function.
113 (*variables)["short_key_type"] =
114 boxed_key_type.substr(pos: boxed_key_type.rfind(c: '.') + 1);
115 (*variables)["key_wire_type"] = WireType(field: key);
116 (*variables)["key_default_value"] = DefaultValue(field: key, immutable: true, name_resolver);
117 (*variables)["key_null_check"] =
118 IsReferenceType(type: keyJavaType)
119 ? "if (key == null) { throw new NullPointerException(\"map key\"); }"
120 : "";
121 (*variables)["value_null_check"] =
122 valueJavaType != JAVATYPE_ENUM && IsReferenceType(type: valueJavaType)
123 ? "if (value == null) {\n"
124 " throw new NullPointerException(\"map value\");\n"
125 "}\n"
126 : "";
127 if (valueJavaType == JAVATYPE_ENUM) {
128 // We store enums as Integers internally.
129 (*variables)["value_type"] = "int";
130 (*variables)["boxed_value_type"] = "java.lang.Integer";
131 (*variables)["value_wire_type"] = WireType(field: value);
132 (*variables)["value_default_value"] =
133 DefaultValue(field: value, immutable: true, name_resolver) + ".getNumber()";
134
135 (*variables)["value_enum_type"] = TypeName(field: value, name_resolver, boxed: false);
136
137 (*variables)["value_enum_type_pass_through_nullness"] =
138 pass_through_nullness + (*variables)["value_enum_type"];
139
140 if (SupportUnknownEnumValue(descriptor: descriptor->file())) {
141 // Map unknown values to a special UNRECOGNIZED value if supported.
142 (*variables)["unrecognized_value"] =
143 (*variables)["value_enum_type"] + ".UNRECOGNIZED";
144 } else {
145 // Map unknown values to the default value if we don't have UNRECOGNIZED.
146 (*variables)["unrecognized_value"] =
147 DefaultValue(field: value, immutable: true, name_resolver);
148 }
149 } else {
150 (*variables)["value_type"] = TypeName(field: value, name_resolver, boxed: false);
151
152 (*variables)["value_type_pass_through_nullness"] =
153 (IsReferenceType(type: valueJavaType) ? pass_through_nullness : "") +
154 (*variables)["value_type"];
155
156 (*variables)["boxed_value_type"] = TypeName(field: value, name_resolver, boxed: true);
157 (*variables)["value_wire_type"] = WireType(field: value);
158 (*variables)["value_default_value"] =
159 DefaultValue(field: value, immutable: true, name_resolver);
160 }
161 (*variables)["type_parameters"] =
162 (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
163 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
164 // by the proto compiler
165 (*variables)["deprecation"] =
166 descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
167 (*variables)["kt_deprecation"] =
168 descriptor->options().deprecated()
169 ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
170 " is deprecated\") "
171 : "";
172 (*variables)["on_changed"] = "onChanged();";
173
174 // For repeated fields, one bit is used for whether the array is immutable
175 // in the parsing constructor.
176 (*variables)["get_mutable_bit_parser"] =
177 GenerateGetBitMutableLocal(bitIndex: builderBitIndex);
178 (*variables)["set_mutable_bit_parser"] =
179 GenerateSetBitMutableLocal(bitIndex: builderBitIndex);
180
181 (*variables)["default_entry"] =
182 (*variables)["capitalized_name"] + "DefaultEntryHolder.defaultEntry";
183 (*variables)["map_field_parameter"] = (*variables)["default_entry"];
184 (*variables)["descriptor"] =
185 name_resolver->GetImmutableClassName(descriptor: descriptor->file()) + ".internal_" +
186 UniqueFileScopeIdentifier(descriptor: descriptor->message_type()) + "_descriptor, ";
187 (*variables)["ver"] = GeneratedCodeVersionSuffix();
188}
189
190} // namespace
191
192ImmutableMapFieldGenerator::ImmutableMapFieldGenerator(
193 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
194 Context* context)
195 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
196 SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
197 info: context->GetFieldGeneratorInfo(field: descriptor), context,
198 variables: &variables_);
199}
200
201ImmutableMapFieldGenerator::~ImmutableMapFieldGenerator() {}
202
203int ImmutableMapFieldGenerator::GetNumBitsForMessage() const { return 0; }
204
205int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const { return 1; }
206
207void ImmutableMapFieldGenerator::GenerateInterfaceMembers(
208 io::Printer* printer) const {
209 WriteFieldDocComment(printer, field: descriptor_);
210 printer->Print(variables: variables_,
211 text: "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
212 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
213 WriteFieldDocComment(printer, field: descriptor_);
214 printer->Print(variables: variables_,
215 text: "$deprecation$boolean ${$contains$capitalized_name$$}$(\n"
216 " $key_type$ key);\n");
217 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
218 if (GetJavaType(field: ValueField(descriptor: descriptor_)) == JAVATYPE_ENUM) {
219 printer->Print(variables: variables_,
220 text: "/**\n"
221 " * Use {@link #get$capitalized_name$Map()} instead.\n"
222 " */\n"
223 "@java.lang.Deprecated\n"
224 "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
225 "${$get$capitalized_name$$}$();\n");
226 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
227 WriteFieldDocComment(printer, field: descriptor_);
228 printer->Print(
229 variables: variables_,
230 text: "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
231 "${$get$capitalized_name$Map$}$();\n");
232 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
233 WriteFieldDocComment(printer, field: descriptor_);
234 printer->Print(variables: variables_,
235 text: "$deprecation$$value_enum_type_pass_through_nullness$ "
236 "${$get$capitalized_name$OrDefault$}$(\n"
237 " $key_type$ key,\n"
238 " $value_enum_type_pass_through_nullness$ "
239 " defaultValue);\n");
240 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
241 WriteFieldDocComment(printer, field: descriptor_);
242 printer->Print(
243 variables: variables_,
244 text: "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
245 " $key_type$ key);\n");
246 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
247 if (SupportUnknownEnumValue(descriptor: descriptor_->file())) {
248 printer->Print(
249 variables: variables_,
250 text: "/**\n"
251 " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
252 " */\n"
253 "@java.lang.Deprecated\n"
254 "java.util.Map<$type_parameters$>\n"
255 "${$get$capitalized_name$Value$}$();\n");
256 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
257 WriteFieldDocComment(printer, field: descriptor_);
258 printer->Print(variables: variables_,
259 text: "$deprecation$java.util.Map<$type_parameters$>\n"
260 "${$get$capitalized_name$ValueMap$}$();\n");
261 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
262 WriteFieldDocComment(printer, field: descriptor_);
263 printer->Print(variables: variables_,
264 text: "$deprecation$\n"
265 "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
266 " $key_type$ key,\n"
267 " $value_type$ defaultValue);\n");
268 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
269 WriteFieldDocComment(printer, field: descriptor_);
270 printer->Print(variables: variables_,
271 text: "$deprecation$\n"
272 "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
273 " $key_type$ key);\n");
274 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
275 }
276 } else {
277 printer->Print(variables: variables_,
278 text: "/**\n"
279 " * Use {@link #get$capitalized_name$Map()} instead.\n"
280 " */\n"
281 "@java.lang.Deprecated\n"
282 "java.util.Map<$type_parameters$>\n"
283 "${$get$capitalized_name$$}$();\n");
284 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
285 WriteFieldDocComment(printer, field: descriptor_);
286 printer->Print(variables: variables_,
287 text: "$deprecation$java.util.Map<$type_parameters$>\n"
288 "${$get$capitalized_name$Map$}$();\n");
289 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
290 WriteFieldDocComment(printer, field: descriptor_);
291 printer->Print(variables: variables_,
292 text: "$deprecation$\n"
293 "$value_type_pass_through_nullness$ "
294 "${$get$capitalized_name$OrDefault$}$(\n"
295 " $key_type$ key,\n"
296 " $value_type_pass_through_nullness$ defaultValue);\n");
297 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
298 WriteFieldDocComment(printer, field: descriptor_);
299 printer->Print(variables: variables_,
300 text: "$deprecation$\n"
301 "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
302 " $key_type$ key);\n");
303 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
304 }
305}
306
307void ImmutableMapFieldGenerator::GenerateMembers(io::Printer* printer) const {
308 printer->Print(
309 variables: variables_,
310 text: "private static final class $capitalized_name$DefaultEntryHolder {\n"
311 " static final com.google.protobuf.MapEntry<\n"
312 " $type_parameters$> defaultEntry =\n"
313 " com.google.protobuf.MapEntry\n"
314 " .<$type_parameters$>newDefaultInstance(\n"
315 " $descriptor$\n"
316 " $key_wire_type$,\n"
317 " $key_default_value$,\n"
318 " $value_wire_type$,\n"
319 " $value_default_value$);\n"
320 "}\n");
321 printer->Print(variables: variables_,
322 text: "private com.google.protobuf.MapField<\n"
323 " $type_parameters$> $name$_;\n"
324 "private com.google.protobuf.MapField<$type_parameters$>\n"
325 "internalGet$capitalized_name$() {\n"
326 " if ($name$_ == null) {\n"
327 " return com.google.protobuf.MapField.emptyMapField(\n"
328 " $map_field_parameter$);\n"
329 " }\n"
330 " return $name$_;\n"
331 "}\n");
332 if (GetJavaType(field: ValueField(descriptor: descriptor_)) == JAVATYPE_ENUM) {
333 printer->Print(
334 variables: variables_,
335 text: "private static final\n"
336 "com.google.protobuf.Internal.MapAdapter.Converter<\n"
337 " java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
338 " com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
339 " $value_enum_type$.internalGetValueMap(),\n"
340 " $unrecognized_value$);\n");
341 printer->Print(
342 variables: variables_,
343 text: "private static final java.util.Map<$boxed_key_type$, "
344 "$value_enum_type$>\n"
345 "internalGetAdapted$capitalized_name$Map(\n"
346 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map) {\n"
347 " return new com.google.protobuf.Internal.MapAdapter<\n"
348 " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
349 " map, $name$ValueConverter);\n"
350 "}\n");
351 }
352 GenerateMapGetters(printer);
353}
354
355void ImmutableMapFieldGenerator::GenerateBuilderMembers(
356 io::Printer* printer) const {
357 printer->Print(variables: variables_,
358 text: "private com.google.protobuf.MapField<\n"
359 " $type_parameters$> $name$_;\n"
360 "private com.google.protobuf.MapField<$type_parameters$>\n"
361 "internalGet$capitalized_name$() {\n"
362 " if ($name$_ == null) {\n"
363 " return com.google.protobuf.MapField.emptyMapField(\n"
364 " $map_field_parameter$);\n"
365 " }\n"
366 " return $name$_;\n"
367 "}\n"
368 "private com.google.protobuf.MapField<$type_parameters$>\n"
369 "internalGetMutable$capitalized_name$() {\n"
370 " $on_changed$;\n"
371 " if ($name$_ == null) {\n"
372 " $name$_ = com.google.protobuf.MapField.newMapField(\n"
373 " $map_field_parameter$);\n"
374 " }\n"
375 " if (!$name$_.isMutable()) {\n"
376 " $name$_ = $name$_.copy();\n"
377 " }\n"
378 " return $name$_;\n"
379 "}\n");
380 GenerateMapGetters(printer);
381 printer->Print(variables: variables_,
382 text: "$deprecation$\n"
383 "public Builder ${$clear$capitalized_name$$}$() {\n"
384 " internalGetMutable$capitalized_name$().getMutableMap()\n"
385 " .clear();\n"
386 " return this;\n"
387 "}\n");
388 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
389 WriteFieldDocComment(printer, field: descriptor_);
390 printer->Print(variables: variables_,
391 text: "$deprecation$\n"
392 "public Builder ${$remove$capitalized_name$$}$(\n"
393 " $key_type$ key) {\n"
394 " $key_null_check$\n"
395 " internalGetMutable$capitalized_name$().getMutableMap()\n"
396 " .remove(key);\n"
397 " return this;\n"
398 "}\n");
399 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
400 if (GetJavaType(field: ValueField(descriptor: descriptor_)) == JAVATYPE_ENUM) {
401 printer->Print(
402 variables: variables_,
403 text: "/**\n"
404 " * Use alternate mutation accessors instead.\n"
405 " */\n"
406 "@java.lang.Deprecated\n"
407 "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
408 "${$getMutable$capitalized_name$$}$() {\n"
409 " return internalGetAdapted$capitalized_name$Map(\n"
410 " internalGetMutable$capitalized_name$().getMutableMap());\n"
411 "}\n");
412 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
413 WriteFieldDocComment(printer, field: descriptor_);
414 printer->Print(variables: variables_,
415 text: "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
416 " $key_type$ key,\n"
417 " $value_enum_type$ value) {\n"
418 " $key_null_check$\n"
419 " $value_null_check$\n"
420 " internalGetMutable$capitalized_name$().getMutableMap()\n"
421 " .put(key, $name$ValueConverter.doBackward(value));\n"
422 " return this;\n"
423 "}\n");
424 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
425 WriteFieldDocComment(printer, field: descriptor_);
426 printer->Print(
427 variables: variables_,
428 text: "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n"
429 " java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
430 " internalGetAdapted$capitalized_name$Map(\n"
431 " internalGetMutable$capitalized_name$().getMutableMap())\n"
432 " .putAll(values);\n"
433 " return this;\n"
434 "}\n");
435 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
436 if (SupportUnknownEnumValue(descriptor: descriptor_->file())) {
437 printer->Print(
438 variables: variables_,
439 text: "/**\n"
440 " * Use alternate mutation accessors instead.\n"
441 " */\n"
442 "@java.lang.Deprecated\n"
443 "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
444 "${$getMutable$capitalized_name$Value$}$() {\n"
445 " return internalGetMutable$capitalized_name$().getMutableMap();\n"
446 "}\n");
447 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
448 WriteFieldDocComment(printer, field: descriptor_);
449 printer->Print(
450 variables: variables_,
451 text: "$deprecation$public Builder ${$put$capitalized_name$Value$}$(\n"
452 " $key_type$ key,\n"
453 " $value_type$ value) {\n"
454 " $key_null_check$\n"
455 " $value_null_check$\n"
456 " internalGetMutable$capitalized_name$().getMutableMap()\n"
457 " .put(key, value);\n"
458 " return this;\n"
459 "}\n");
460 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
461 WriteFieldDocComment(printer, field: descriptor_);
462 printer->Print(
463 variables: variables_,
464 text: "$deprecation$public Builder ${$putAll$capitalized_name$Value$}$(\n"
465 " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
466 " internalGetMutable$capitalized_name$().getMutableMap()\n"
467 " .putAll(values);\n"
468 " return this;\n"
469 "}\n");
470 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
471 }
472 } else {
473 printer->Print(
474 variables: variables_,
475 text: "/**\n"
476 " * Use alternate mutation accessors instead.\n"
477 " */\n"
478 "@java.lang.Deprecated\n"
479 "public java.util.Map<$type_parameters$>\n"
480 "${$getMutable$capitalized_name$$}$() {\n"
481 " return internalGetMutable$capitalized_name$().getMutableMap();\n"
482 "}\n");
483 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
484 WriteFieldDocComment(printer, field: descriptor_);
485 printer->Print(variables: variables_,
486 text: "$deprecation$"
487 "public Builder ${$put$capitalized_name$$}$(\n"
488 " $key_type$ key,\n"
489 " $value_type$ value) {\n"
490 " $key_null_check$\n"
491 " $value_null_check$\n"
492 " internalGetMutable$capitalized_name$().getMutableMap()\n"
493 " .put(key, value);\n"
494 " return this;\n"
495 "}\n");
496 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
497 WriteFieldDocComment(printer, field: descriptor_);
498 printer->Print(variables: variables_,
499 text: "$deprecation$\n"
500 "public Builder ${$putAll$capitalized_name$$}$(\n"
501 " java.util.Map<$type_parameters$> values) {\n"
502 " internalGetMutable$capitalized_name$().getMutableMap()\n"
503 " .putAll(values);\n"
504 " return this;\n"
505 "}\n");
506 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
507 }
508}
509
510void ImmutableMapFieldGenerator::GenerateMapGetters(
511 io::Printer* printer) const {
512 printer->Print(variables: variables_,
513 text: "$deprecation$\n"
514 "public int ${$get$capitalized_name$Count$}$() {\n"
515 " return internalGet$capitalized_name$().getMap().size();\n"
516 "}\n");
517 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
518 WriteFieldDocComment(printer, field: descriptor_);
519 printer->Print(
520 variables: variables_,
521 text: "$deprecation$\n"
522 "@java.lang.Override\n"
523 "public boolean ${$contains$capitalized_name$$}$(\n"
524 " $key_type$ key) {\n"
525 " $key_null_check$\n"
526 " return internalGet$capitalized_name$().getMap().containsKey(key);\n"
527 "}\n");
528 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
529 if (GetJavaType(field: ValueField(descriptor: descriptor_)) == JAVATYPE_ENUM) {
530 printer->Print(variables: variables_,
531 text: "/**\n"
532 " * Use {@link #get$capitalized_name$Map()} instead.\n"
533 " */\n"
534 "@java.lang.Override\n"
535 "@java.lang.Deprecated\n"
536 "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
537 "${$get$capitalized_name$$}$() {\n"
538 " return get$capitalized_name$Map();\n"
539 "}\n");
540 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
541 WriteFieldDocComment(printer, field: descriptor_);
542 printer->Print(variables: variables_,
543 text: "@java.lang.Override\n"
544 "$deprecation$\n"
545 "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
546 "${$get$capitalized_name$Map$}$() {\n"
547 " return internalGetAdapted$capitalized_name$Map(\n"
548 " internalGet$capitalized_name$().getMap());"
549 "}\n");
550 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
551 WriteFieldDocComment(printer, field: descriptor_);
552 printer->Print(
553 variables: variables_,
554 text: "@java.lang.Override\n"
555 "$deprecation$\n"
556 "public $value_enum_type_pass_through_nullness$ "
557 "${$get$capitalized_name$OrDefault$}$(\n"
558 " $key_type$ key,\n"
559 " $value_enum_type_pass_through_nullness$ defaultValue) {\n"
560 " $key_null_check$\n"
561 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
562 " internalGet$capitalized_name$().getMap();\n"
563 " return map.containsKey(key)\n"
564 " ? $name$ValueConverter.doForward(map.get(key))\n"
565 " : defaultValue;\n"
566 "}\n");
567 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
568 WriteFieldDocComment(printer, field: descriptor_);
569 printer->Print(
570 variables: variables_,
571 text: "@java.lang.Override\n"
572 "$deprecation$\n"
573 "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
574 " $key_type$ key) {\n"
575 " $key_null_check$\n"
576 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
577 " internalGet$capitalized_name$().getMap();\n"
578 " if (!map.containsKey(key)) {\n"
579 " throw new java.lang.IllegalArgumentException();\n"
580 " }\n"
581 " return $name$ValueConverter.doForward(map.get(key));\n"
582 "}\n");
583 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
584 if (SupportUnknownEnumValue(descriptor: descriptor_->file())) {
585 printer->Print(
586 variables: variables_,
587 text: "/**\n"
588 " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
589 " */\n"
590 "@java.lang.Override\n"
591 "@java.lang.Deprecated\n"
592 "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
593 "${$get$capitalized_name$Value$}$() {\n"
594 " return get$capitalized_name$ValueMap();\n"
595 "}\n");
596 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
597 WriteFieldDocComment(printer, field: descriptor_);
598 printer->Print(
599 variables: variables_,
600 text: "@java.lang.Override\n"
601 "$deprecation$\n"
602 "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
603 "${$get$capitalized_name$ValueMap$}$() {\n"
604 " return internalGet$capitalized_name$().getMap();\n"
605 "}\n");
606 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
607 WriteFieldDocComment(printer, field: descriptor_);
608 printer->Print(
609 variables: variables_,
610 text: "@java.lang.Override\n"
611 "$deprecation$\n"
612 "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
613 " $key_type$ key,\n"
614 " $value_type$ defaultValue) {\n"
615 " $key_null_check$\n"
616 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
617 " internalGet$capitalized_name$().getMap();\n"
618 " return map.containsKey(key) ? map.get(key) : defaultValue;\n"
619 "}\n");
620 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
621 WriteFieldDocComment(printer, field: descriptor_);
622 printer->Print(
623 variables: variables_,
624 text: "@java.lang.Override\n"
625 "$deprecation$\n"
626 "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
627 " $key_type$ key) {\n"
628 " $key_null_check$\n"
629 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
630 " internalGet$capitalized_name$().getMap();\n"
631 " if (!map.containsKey(key)) {\n"
632 " throw new java.lang.IllegalArgumentException();\n"
633 " }\n"
634 " return map.get(key);\n"
635 "}\n");
636 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
637 }
638 } else {
639 printer->Print(variables: variables_,
640 text: "/**\n"
641 " * Use {@link #get$capitalized_name$Map()} instead.\n"
642 " */\n"
643 "@java.lang.Override\n"
644 "@java.lang.Deprecated\n"
645 "public java.util.Map<$type_parameters$> "
646 "${$get$capitalized_name$$}$() {\n"
647 " return get$capitalized_name$Map();\n"
648 "}\n");
649 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
650 WriteFieldDocComment(printer, field: descriptor_);
651 printer->Print(variables: variables_,
652 text: "@java.lang.Override\n"
653 "$deprecation$\n"
654 "public java.util.Map<$type_parameters$> "
655 "${$get$capitalized_name$Map$}$() {\n"
656 " return internalGet$capitalized_name$().getMap();\n"
657 "}\n");
658 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
659 WriteFieldDocComment(printer, field: descriptor_);
660 printer->Print(
661 variables: variables_,
662 text: "@java.lang.Override\n"
663 "$deprecation$\n"
664 "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
665 " $key_type$ key,\n"
666 " $value_type$ defaultValue) {\n"
667 " $key_null_check$\n"
668 " java.util.Map<$type_parameters$> map =\n"
669 " internalGet$capitalized_name$().getMap();\n"
670 " return map.containsKey(key) ? map.get(key) : defaultValue;\n"
671 "}\n");
672 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
673 WriteFieldDocComment(printer, field: descriptor_);
674 printer->Print(variables: variables_,
675 text: "@java.lang.Override\n"
676 "$deprecation$\n"
677 "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
678 " $key_type$ key) {\n"
679 " $key_null_check$\n"
680 " java.util.Map<$type_parameters$> map =\n"
681 " internalGet$capitalized_name$().getMap();\n"
682 " if (!map.containsKey(key)) {\n"
683 " throw new java.lang.IllegalArgumentException();\n"
684 " }\n"
685 " return map.get(key);\n"
686 "}\n");
687 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
688 }
689}
690
691void ImmutableMapFieldGenerator::GenerateKotlinDslMembers(
692 io::Printer* printer) const {
693 printer->Print(
694 variables: variables_,
695 text: "/**\n"
696 " * An uninstantiable, behaviorless type to represent the field in\n"
697 " * generics.\n"
698 " */\n"
699 "@kotlin.OptIn"
700 "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
701 "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
702 " : com.google.protobuf.kotlin.DslProxy()\n");
703
704 WriteFieldDocComment(printer, field: descriptor_);
705 printer->Print(
706 variables: variables_,
707 text: "$kt_deprecation$ val $kt_name$: "
708 "com.google.protobuf.kotlin.DslMap"
709 "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
710 " @kotlin.jvm.JvmSynthetic\n"
711 " @JvmName(\"get$kt_capitalized_name$Map\")\n"
712 " get() = com.google.protobuf.kotlin.DslMap(\n"
713 " $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n"
714 " )\n");
715
716 WriteFieldDocComment(printer, field: descriptor_);
717 printer->Print(
718 variables: variables_,
719 text: "@JvmName(\"put$kt_capitalized_name$\")\n"
720 "fun com.google.protobuf.kotlin.DslMap"
721 "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
722 " .put(key: $kt_key_type$, value: $kt_value_type$) {\n"
723 " $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n"
724 " }\n");
725
726 WriteFieldDocComment(printer, field: descriptor_);
727 printer->Print(
728 variables: variables_,
729 text: "@kotlin.jvm.JvmSynthetic\n"
730 "@JvmName(\"set$kt_capitalized_name$\")\n"
731 "@Suppress(\"NOTHING_TO_INLINE\")\n"
732 "inline operator fun com.google.protobuf.kotlin.DslMap"
733 "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
734 " .set(key: $kt_key_type$, value: $kt_value_type$) {\n"
735 " put(key, value)\n"
736 " }\n");
737
738 WriteFieldDocComment(printer, field: descriptor_);
739 printer->Print(
740 variables: variables_,
741 text: "@kotlin.jvm.JvmSynthetic\n"
742 "@JvmName(\"remove$kt_capitalized_name$\")\n"
743 "fun com.google.protobuf.kotlin.DslMap"
744 "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
745 " .remove(key: $kt_key_type$) {\n"
746 " $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n"
747 " }\n");
748
749 WriteFieldDocComment(printer, field: descriptor_);
750 printer->Print(
751 variables: variables_,
752 text: "@kotlin.jvm.JvmSynthetic\n"
753 "@JvmName(\"putAll$kt_capitalized_name$\")\n"
754 "fun com.google.protobuf.kotlin.DslMap"
755 "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
756 " .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) "
757 "{\n"
758 " $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n"
759 " }\n");
760
761 WriteFieldDocComment(printer, field: descriptor_);
762 printer->Print(
763 variables: variables_,
764 text: "@kotlin.jvm.JvmSynthetic\n"
765 "@JvmName(\"clear$kt_capitalized_name$\")\n"
766 "fun com.google.protobuf.kotlin.DslMap"
767 "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
768 " .clear() {\n"
769 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
770 " }\n");
771}
772
773void ImmutableMapFieldGenerator::GenerateFieldBuilderInitializationCode(
774 io::Printer* printer) const {
775 // Nothing to initialize.
776}
777
778void ImmutableMapFieldGenerator::GenerateInitializationCode(
779 io::Printer* printer) const {
780 // Nothing to initialize.
781}
782
783void ImmutableMapFieldGenerator::GenerateBuilderClearCode(
784 io::Printer* printer) const {
785 printer->Print(variables: variables_,
786 text: "internalGetMutable$capitalized_name$().clear();\n");
787}
788
789void ImmutableMapFieldGenerator::GenerateMergingCode(
790 io::Printer* printer) const {
791 printer->Print(variables: variables_,
792 text: "internalGetMutable$capitalized_name$().mergeFrom(\n"
793 " other.internalGet$capitalized_name$());\n");
794}
795
796void ImmutableMapFieldGenerator::GenerateBuildingCode(
797 io::Printer* printer) const {
798 printer->Print(variables: variables_,
799 text: "result.$name$_ = internalGet$capitalized_name$();\n"
800 "result.$name$_.makeImmutable();\n");
801}
802
803void ImmutableMapFieldGenerator::GenerateParsingCode(
804 io::Printer* printer) const {
805 printer->Print(variables: variables_,
806 text: "if (!$get_mutable_bit_parser$) {\n"
807 " $name$_ = com.google.protobuf.MapField.newMapField(\n"
808 " $map_field_parameter$);\n"
809 " $set_mutable_bit_parser$;\n"
810 "}\n");
811 if (!SupportUnknownEnumValue(descriptor: descriptor_->file()) &&
812 GetJavaType(field: ValueField(descriptor: descriptor_)) == JAVATYPE_ENUM) {
813 printer->Print(
814 variables: variables_,
815 text: "com.google.protobuf.ByteString bytes = input.readBytes();\n"
816 "com.google.protobuf.MapEntry<$type_parameters$>\n"
817 "$name$__ = $default_entry$.getParserForType().parseFrom(bytes);\n");
818 printer->Print(
819 variables: variables_,
820 text: "if ($value_enum_type$.forNumber($name$__.getValue()) == null) {\n"
821 " unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
822 "} else {\n"
823 " $name$_.getMutableMap().put(\n"
824 " $name$__.getKey(), $name$__.getValue());\n"
825 "}\n");
826 } else {
827 printer->Print(
828 variables: variables_,
829 text: "com.google.protobuf.MapEntry<$type_parameters$>\n"
830 "$name$__ = input.readMessage(\n"
831 " $default_entry$.getParserForType(), extensionRegistry);\n"
832 "$name$_.getMutableMap().put(\n"
833 " $name$__.getKey(), $name$__.getValue());\n");
834 }
835}
836
837void ImmutableMapFieldGenerator::GenerateParsingDoneCode(
838 io::Printer* printer) const {
839 // Nothing to do here.
840}
841
842void ImmutableMapFieldGenerator::GenerateSerializationCode(
843 io::Printer* printer) const {
844 printer->Print(variables: variables_,
845 text: "com.google.protobuf.GeneratedMessage$ver$\n"
846 " .serialize$short_key_type$MapTo(\n"
847 " output,\n"
848 " internalGet$capitalized_name$(),\n"
849 " $default_entry$,\n"
850 " $number$);\n");
851}
852
853void ImmutableMapFieldGenerator::GenerateSerializedSizeCode(
854 io::Printer* printer) const {
855 printer->Print(
856 variables: variables_,
857 text: "for (java.util.Map.Entry<$type_parameters$> entry\n"
858 " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
859 " com.google.protobuf.MapEntry<$type_parameters$>\n"
860 " $name$__ = $default_entry$.newBuilderForType()\n"
861 " .setKey(entry.getKey())\n"
862 " .setValue(entry.getValue())\n"
863 " .build();\n"
864 " size += com.google.protobuf.CodedOutputStream\n"
865 " .computeMessageSize($number$, $name$__);\n"
866 "}\n");
867}
868
869void ImmutableMapFieldGenerator::GenerateEqualsCode(
870 io::Printer* printer) const {
871 printer->Print(variables: variables_,
872 text: "if (!internalGet$capitalized_name$().equals(\n"
873 " other.internalGet$capitalized_name$())) return false;\n");
874}
875
876void ImmutableMapFieldGenerator::GenerateHashCode(io::Printer* printer) const {
877 printer->Print(
878 variables: variables_,
879 text: "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
880 " hash = (37 * hash) + $constant_name$;\n"
881 " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
882 "}\n");
883}
884
885std::string ImmutableMapFieldGenerator::GetBoxedType() const {
886 return name_resolver_->GetImmutableClassName(descriptor: descriptor_->message_type());
887}
888
889} // namespace java
890} // namespace compiler
891} // namespace protobuf
892} // namespace google
893
894#include <google/protobuf/port_undef.inc>
895