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
42 namespace google {
43 namespace protobuf {
44 namespace compiler {
45 namespace java {
46
47 namespace {
48
KeyField(const FieldDescriptor * descriptor)49 const 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
ValueField(const FieldDescriptor * descriptor)56 const 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
TypeName(const FieldDescriptor * field,ClassNameResolver * name_resolver,bool boxed)63 std::string TypeName(const FieldDescriptor* field,
64 ClassNameResolver* name_resolver, bool boxed) {
65 if (GetJavaType(field) == JAVATYPE_MESSAGE) {
66 return name_resolver->GetImmutableClassName(field->message_type());
67 } else if (GetJavaType(field) == JAVATYPE_ENUM) {
68 return name_resolver->GetImmutableClassName(field->enum_type());
69 } else {
70 return boxed ? BoxedPrimitiveTypeName(GetJavaType(field))
71 : PrimitiveTypeName(GetJavaType(field));
72 }
73 }
74
KotlinTypeName(const FieldDescriptor * field,ClassNameResolver * name_resolver)75 std::string KotlinTypeName(const FieldDescriptor* field,
76 ClassNameResolver* name_resolver) {
77 if (GetJavaType(field) == JAVATYPE_MESSAGE) {
78 return name_resolver->GetImmutableClassName(field->message_type());
79 } else if (GetJavaType(field) == JAVATYPE_ENUM) {
80 return name_resolver->GetImmutableClassName(field->enum_type());
81 } else {
82 return KotlinTypeName(GetJavaType(field));
83 }
84 }
85
WireType(const FieldDescriptor * field)86 std::string WireType(const FieldDescriptor* field) {
87 return "com.google.protobuf.WireFormat.FieldType." +
88 std::string(FieldTypeName(field->type()));
89 }
90
SetMessageVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,Context * context,std::map<std::string,std::string> * variables)91 void SetMessageVariables(
92 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
93 const FieldGeneratorInfo* info, 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->message_type());
100 const FieldDescriptor* key = KeyField(descriptor);
101 const FieldDescriptor* value = ValueField(descriptor);
102 const JavaType keyJavaType = GetJavaType(key);
103 const JavaType valueJavaType = GetJavaType(value);
104
105 std::string pass_through_nullness = "/* nullable */\n";
106
107 (*variables)["key_type"] = TypeName(key, name_resolver, false);
108 std::string boxed_key_type = TypeName(key, name_resolver, true);
109 (*variables)["boxed_key_type"] = boxed_key_type;
110 (*variables)["kt_key_type"] = KotlinTypeName(key, name_resolver);
111 (*variables)["kt_value_type"] = KotlinTypeName(value, name_resolver);
112 // Used for calling the serialization function.
113 (*variables)["short_key_type"] =
114 boxed_key_type.substr(boxed_key_type.rfind('.') + 1);
115 (*variables)["key_wire_type"] = WireType(key);
116 (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
117 (*variables)["key_null_check"] =
118 IsReferenceType(keyJavaType)
119 ? "if (key == null) { throw new NullPointerException(\"map key\"); }"
120 : "";
121 (*variables)["value_null_check"] =
122 valueJavaType != JAVATYPE_ENUM && IsReferenceType(valueJavaType)
123 ? "if (value == null) { "
124 "throw new NullPointerException(\"map value\"); }"
125 : "";
126 if (valueJavaType == JAVATYPE_ENUM) {
127 // We store enums as Integers internally.
128 (*variables)["value_type"] = "int";
129 variables->insert(
130 {"value_type_pass_through_nullness", (*variables)["value_type"]});
131 (*variables)["boxed_value_type"] = "java.lang.Integer";
132 (*variables)["value_wire_type"] = WireType(value);
133 (*variables)["value_default_value"] =
134 DefaultValue(value, true, name_resolver) + ".getNumber()";
135
136 (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
137
138 variables->insert(
139 {"value_enum_type_pass_through_nullness",
140 StrCat(pass_through_nullness, (*variables)["value_enum_type"])});
141
142 if (SupportUnknownEnumValue(descriptor->file())) {
143 // Map unknown values to a special UNRECOGNIZED value if supported.
144 variables->insert(
145 {"unrecognized_value",
146 StrCat((*variables)["value_enum_type"], ".UNRECOGNIZED")});
147 } else {
148 // Map unknown values to the default value if we don't have UNRECOGNIZED.
149 (*variables)["unrecognized_value"] =
150 DefaultValue(value, true, name_resolver);
151 }
152 } else {
153 (*variables)["value_type"] = TypeName(value, name_resolver, false);
154
155 variables->insert(
156 {"value_type_pass_through_nullness",
157 StrCat(
158 (IsReferenceType(valueJavaType) ? pass_through_nullness : ""),
159 (*variables)["value_type"])});
160
161 (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
162 (*variables)["value_wire_type"] = WireType(value);
163 (*variables)["value_default_value"] =
164 DefaultValue(value, true, name_resolver);
165 }
166 variables->insert(
167 {"type_parameters", StrCat((*variables)["boxed_key_type"], ", ",
168 (*variables)["boxed_value_type"])});
169 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
170 // by the proto compiler
171 (*variables)["deprecation"] =
172 descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
173 variables->insert(
174 {"kt_deprecation",
175 descriptor->options().deprecated()
176 ? StrCat("@kotlin.Deprecated(message = \"Field ",
177 (*variables)["name"], " is deprecated\") ")
178 : ""});
179 (*variables)["on_changed"] = "onChanged();";
180
181 variables->insert(
182 {"default_entry", StrCat((*variables)["capitalized_name"],
183 "DefaultEntryHolder.defaultEntry")});
184 variables->insert({"map_field_parameter", (*variables)["default_entry"]});
185 (*variables)["descriptor"] =
186 name_resolver->GetImmutableClassName(descriptor->file()) + ".internal_" +
187 UniqueFileScopeIdentifier(descriptor->message_type()) + "_descriptor, ";
188 (*variables)["ver"] = GeneratedCodeVersionSuffix();
189
190 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
191 (*variables)["get_has_field_bit_from_local"] =
192 GenerateGetBitFromLocal(builderBitIndex);
193 (*variables)["set_has_field_bit_builder"] =
194 GenerateSetBit(builderBitIndex) + ";";
195 (*variables)["clear_has_field_bit_builder"] =
196 GenerateClearBit(builderBitIndex) + ";";
197 }
198
199 } // namespace
200
ImmutableMapFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)201 ImmutableMapFieldGenerator::ImmutableMapFieldGenerator(
202 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
203 Context* context)
204 : descriptor_(descriptor),
205 message_bit_index_(messageBitIndex),
206 builder_bit_index_(builderBitIndex),
207 name_resolver_(context->GetNameResolver()),
208 context_(context) {
209 SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
210 context->GetFieldGeneratorInfo(descriptor), context,
211 &variables_);
212 }
213
~ImmutableMapFieldGenerator()214 ImmutableMapFieldGenerator::~ImmutableMapFieldGenerator() {}
215
GetMessageBitIndex() const216 int ImmutableMapFieldGenerator::GetMessageBitIndex() const {
217 return message_bit_index_;
218 }
219
GetBuilderBitIndex() const220 int ImmutableMapFieldGenerator::GetBuilderBitIndex() const {
221 return builder_bit_index_;
222 }
223
GetNumBitsForMessage() const224 int ImmutableMapFieldGenerator::GetNumBitsForMessage() const { return 0; }
225
GetNumBitsForBuilder() const226 int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const { return 1; }
227
GenerateInterfaceMembers(io::Printer * printer) const228 void ImmutableMapFieldGenerator::GenerateInterfaceMembers(
229 io::Printer* printer) const {
230 WriteFieldDocComment(printer, descriptor_);
231 printer->Print(variables_,
232 "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
233 printer->Annotate("{", "}", descriptor_);
234 WriteFieldDocComment(printer, descriptor_);
235 printer->Print(variables_,
236 "$deprecation$boolean ${$contains$capitalized_name$$}$(\n"
237 " $key_type$ key);\n");
238 printer->Annotate("{", "}", descriptor_);
239 if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
240 printer->Print(variables_,
241 "/**\n"
242 " * Use {@link #get$capitalized_name$Map()} instead.\n"
243 " */\n"
244 "@java.lang.Deprecated\n"
245 "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
246 "${$get$capitalized_name$$}$();\n");
247 printer->Annotate("{", "}", descriptor_);
248 WriteFieldDocComment(printer, descriptor_);
249 printer->Print(
250 variables_,
251 "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
252 "${$get$capitalized_name$Map$}$();\n");
253 printer->Annotate("{", "}", descriptor_);
254 WriteFieldDocComment(printer, descriptor_);
255 printer->Print(variables_,
256 "$deprecation$$value_enum_type_pass_through_nullness$ "
257 "${$get$capitalized_name$OrDefault$}$(\n"
258 " $key_type$ key,\n"
259 " $value_enum_type_pass_through_nullness$ "
260 " defaultValue);\n");
261 printer->Annotate("{", "}", descriptor_);
262 WriteFieldDocComment(printer, descriptor_);
263 printer->Print(
264 variables_,
265 "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
266 " $key_type$ key);\n");
267 printer->Annotate("{", "}", descriptor_);
268 if (SupportUnknownEnumValue(descriptor_->file())) {
269 printer->Print(
270 variables_,
271 "/**\n"
272 " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
273 " */\n"
274 "@java.lang.Deprecated\n"
275 "java.util.Map<$type_parameters$>\n"
276 "${$get$capitalized_name$Value$}$();\n");
277 printer->Annotate("{", "}", descriptor_);
278 WriteFieldDocComment(printer, descriptor_);
279 printer->Print(variables_,
280 "$deprecation$java.util.Map<$type_parameters$>\n"
281 "${$get$capitalized_name$ValueMap$}$();\n");
282 printer->Annotate("{", "}", descriptor_);
283 WriteFieldDocComment(printer, descriptor_);
284 printer->Print(variables_,
285 "$deprecation$$value_type_pass_through_nullness$ "
286 "${$get$capitalized_name$ValueOrDefault$}$(\n"
287 " $key_type$ key,\n"
288 " $value_type_pass_through_nullness$ defaultValue);\n");
289 printer->Annotate("{", "}", descriptor_);
290 WriteFieldDocComment(printer, descriptor_);
291 printer->Print(
292 variables_,
293 "$deprecation$$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
294 " $key_type$ key);\n");
295 printer->Annotate("{", "}", descriptor_);
296 }
297 } else {
298 printer->Print(variables_,
299 "/**\n"
300 " * Use {@link #get$capitalized_name$Map()} instead.\n"
301 " */\n"
302 "@java.lang.Deprecated\n"
303 "java.util.Map<$type_parameters$>\n"
304 "${$get$capitalized_name$$}$();\n");
305 printer->Annotate("{", "}", descriptor_);
306 WriteFieldDocComment(printer, descriptor_);
307 printer->Print(variables_,
308 "$deprecation$java.util.Map<$type_parameters$>\n"
309 "${$get$capitalized_name$Map$}$();\n");
310 printer->Annotate("{", "}", descriptor_);
311 WriteFieldDocComment(printer, descriptor_);
312 printer->Print(variables_,
313 "$deprecation$$value_type_pass_through_nullness$ "
314 "${$get$capitalized_name$OrDefault$}$(\n"
315 " $key_type$ key,\n"
316 " $value_type_pass_through_nullness$ defaultValue);\n");
317 printer->Annotate("{", "}", descriptor_);
318 WriteFieldDocComment(printer, descriptor_);
319 printer->Print(
320 variables_,
321 "$deprecation$$value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
322 " $key_type$ key);\n");
323 printer->Annotate("{", "}", descriptor_);
324 }
325 }
326
GenerateMembers(io::Printer * printer) const327 void ImmutableMapFieldGenerator::GenerateMembers(io::Printer* printer) const {
328 printer->Print(
329 variables_,
330 "private static final class $capitalized_name$DefaultEntryHolder {\n"
331 " static final com.google.protobuf.MapEntry<\n"
332 " $type_parameters$> defaultEntry =\n"
333 " com.google.protobuf.MapEntry\n"
334 " .<$type_parameters$>newDefaultInstance(\n"
335 " $descriptor$\n"
336 " $key_wire_type$,\n"
337 " $key_default_value$,\n"
338 " $value_wire_type$,\n"
339 " $value_default_value$);\n"
340 "}\n");
341 printer->Print(variables_,
342 "@SuppressWarnings(\"serial\")\n"
343 "private com.google.protobuf.MapField<\n"
344 " $type_parameters$> $name$_;\n"
345 "private com.google.protobuf.MapField<$type_parameters$>\n"
346 "internalGet$capitalized_name$() {\n"
347 " if ($name$_ == null) {\n"
348 " return com.google.protobuf.MapField.emptyMapField(\n"
349 " $map_field_parameter$);\n"
350 " }\n"
351 " return $name$_;\n"
352 "}\n");
353 if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
354 printer->Print(
355 variables_,
356 "private static final\n"
357 "com.google.protobuf.Internal.MapAdapter.Converter<\n"
358 " java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
359 " com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
360 " $value_enum_type$.internalGetValueMap(),\n"
361 " $unrecognized_value$);\n");
362 printer->Print(
363 variables_,
364 "private static final java.util.Map<$boxed_key_type$, "
365 "$value_enum_type$>\n"
366 "internalGetAdapted$capitalized_name$Map(\n"
367 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map) {\n"
368 " return new com.google.protobuf.Internal.MapAdapter<\n"
369 " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
370 " map, $name$ValueConverter);\n"
371 "}\n");
372 }
373 GenerateMapGetters(printer);
374 }
375
GenerateBuilderMembers(io::Printer * printer) const376 void ImmutableMapFieldGenerator::GenerateBuilderMembers(
377 io::Printer* printer) const {
378 printer->Print(
379 variables_,
380 "private com.google.protobuf.MapField<\n"
381 " $type_parameters$> $name$_;\n"
382 "$deprecation$private com.google.protobuf.MapField<$type_parameters$>\n"
383 " internalGet$capitalized_name$() {\n"
384 " if ($name$_ == null) {\n"
385 " return com.google.protobuf.MapField.emptyMapField(\n"
386 " $map_field_parameter$);\n"
387 " }\n"
388 " return $name$_;\n"
389 "}\n"
390 "$deprecation$private com.google.protobuf.MapField<$type_parameters$>\n"
391 " internalGetMutable$capitalized_name$() {\n"
392 " if ($name$_ == null) {\n"
393 " $name$_ = com.google.protobuf.MapField.newMapField(\n"
394 " $map_field_parameter$);\n"
395 " }\n"
396 " if (!$name$_.isMutable()) {\n"
397 " $name$_ = $name$_.copy();\n"
398 " }\n"
399 " $set_has_field_bit_builder$\n"
400 " $on_changed$\n"
401 " return $name$_;\n"
402 "}\n");
403 GenerateMapGetters(printer);
404 printer->Print(
405 variables_,
406 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
407 " $clear_has_field_bit_builder$\n"
408 " internalGetMutable$capitalized_name$().getMutableMap()\n"
409 " .clear();\n"
410 " return this;\n"
411 "}\n");
412 printer->Annotate("{", "}", descriptor_);
413
414 WriteFieldDocComment(printer, descriptor_);
415 printer->Print(variables_,
416 "$deprecation$public Builder ${$remove$capitalized_name$$}$(\n"
417 " $key_type$ key) {\n"
418 " $key_null_check$\n"
419 " internalGetMutable$capitalized_name$().getMutableMap()\n"
420 " .remove(key);\n"
421 " return this;\n"
422 "}\n");
423 printer->Annotate("{", "}", descriptor_);
424
425 if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
426 printer->Print(
427 variables_,
428 "/**\n"
429 " * Use alternate mutation accessors instead.\n"
430 " */\n"
431 "@java.lang.Deprecated\n"
432 "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
433 " ${$getMutable$capitalized_name$$}$() {\n"
434 " $set_has_field_bit_builder$\n"
435 " return internalGetAdapted$capitalized_name$Map(\n"
436 " internalGetMutable$capitalized_name$().getMutableMap());\n"
437 "}\n");
438 printer->Annotate("{", "}", descriptor_);
439 WriteFieldDocComment(printer, descriptor_);
440 printer->Print(variables_,
441 "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
442 " $key_type$ key,\n"
443 " $value_enum_type$ value) {\n"
444 " $key_null_check$\n"
445 " $value_null_check$\n"
446 " internalGetMutable$capitalized_name$().getMutableMap()\n"
447 " .put(key, $name$ValueConverter.doBackward(value));\n"
448 " $set_has_field_bit_builder$\n"
449 " return this;\n"
450 "}\n");
451 printer->Annotate("{", "}", descriptor_);
452
453 WriteFieldDocComment(printer, descriptor_);
454 printer->Print(
455 variables_,
456 "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n"
457 " java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
458 " internalGetAdapted$capitalized_name$Map(\n"
459 " internalGetMutable$capitalized_name$().getMutableMap())\n"
460 " .putAll(values);\n"
461 " $set_has_field_bit_builder$\n"
462 " return this;\n"
463 "}\n");
464 printer->Annotate("{", "}", descriptor_);
465
466 if (SupportUnknownEnumValue(descriptor_->file())) {
467 printer->Print(
468 variables_,
469 "/**\n"
470 " * Use alternate mutation accessors instead.\n"
471 " */\n"
472 "@java.lang.Deprecated\n"
473 "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
474 "${$getMutable$capitalized_name$Value$}$() {\n"
475 " $set_has_field_bit_builder$\n"
476 " return internalGetMutable$capitalized_name$().getMutableMap();\n"
477 "}\n");
478 printer->Annotate("{", "}", descriptor_);
479 WriteFieldDocComment(printer, descriptor_);
480 printer->Print(
481 variables_,
482 "$deprecation$public Builder ${$put$capitalized_name$Value$}$(\n"
483 " $key_type$ key,\n"
484 " $value_type$ value) {\n"
485 " $key_null_check$\n"
486 " $value_null_check$\n"
487 " internalGetMutable$capitalized_name$().getMutableMap()\n"
488 " .put(key, value);\n"
489 " $set_has_field_bit_builder$\n"
490 " return this;\n"
491 "}\n");
492 printer->Annotate("{", "}", descriptor_);
493
494 WriteFieldDocComment(printer, descriptor_);
495 printer->Print(
496 variables_,
497 "$deprecation$public Builder ${$putAll$capitalized_name$Value$}$(\n"
498 " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
499 " internalGetMutable$capitalized_name$().getMutableMap()\n"
500 " .putAll(values);\n"
501 " $set_has_field_bit_builder$\n"
502 " return this;\n"
503 "}\n");
504 printer->Annotate("{", "}", descriptor_);
505 }
506 } else {
507 printer->Print(
508 variables_,
509 "/**\n"
510 " * Use alternate mutation accessors instead.\n"
511 " */\n"
512 "@java.lang.Deprecated\n"
513 "public java.util.Map<$type_parameters$>\n"
514 " ${$getMutable$capitalized_name$$}$() {\n"
515 " $set_has_field_bit_builder$\n"
516 " return internalGetMutable$capitalized_name$().getMutableMap();\n"
517 "}\n");
518 printer->Annotate("{", "}", descriptor_);
519 WriteFieldDocComment(printer, descriptor_);
520 printer->Print(variables_,
521 "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
522 " $key_type$ key,\n"
523 " $value_type$ value) {\n"
524 " $key_null_check$\n"
525 " $value_null_check$\n"
526 " internalGetMutable$capitalized_name$().getMutableMap()\n"
527 " .put(key, value);\n"
528 " $set_has_field_bit_builder$\n"
529 " return this;\n"
530 "}\n");
531 printer->Annotate("{", "}", descriptor_);
532
533 WriteFieldDocComment(printer, descriptor_);
534 printer->Print(
535 variables_,
536 "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n"
537 " java.util.Map<$type_parameters$> values) {\n"
538 " internalGetMutable$capitalized_name$().getMutableMap()\n"
539 " .putAll(values);\n"
540 " $set_has_field_bit_builder$\n"
541 " return this;\n"
542 "}\n");
543 printer->Annotate("{", "}", descriptor_);
544 }
545 }
546
GenerateMapGetters(io::Printer * printer) const547 void ImmutableMapFieldGenerator::GenerateMapGetters(
548 io::Printer* printer) const {
549 printer->Print(
550 variables_,
551 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
552 " return internalGet$capitalized_name$().getMap().size();\n"
553 "}\n");
554 printer->Annotate("{", "}", descriptor_);
555
556 WriteFieldDocComment(printer, descriptor_);
557 printer->Print(
558 variables_,
559 "@java.lang.Override\n"
560 "$deprecation$public boolean ${$contains$capitalized_name$$}$(\n"
561 " $key_type$ key) {\n"
562 " $key_null_check$\n"
563 " return internalGet$capitalized_name$().getMap().containsKey(key);\n"
564 "}\n");
565 printer->Annotate("{", "}", descriptor_);
566
567 if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
568 printer->Print(variables_,
569 "/**\n"
570 " * Use {@link #get$capitalized_name$Map()} instead.\n"
571 " */\n"
572 "@java.lang.Override\n"
573 "@java.lang.Deprecated\n"
574 "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
575 "${$get$capitalized_name$$}$() {\n"
576 " return get$capitalized_name$Map();\n"
577 "}\n");
578 printer->Annotate("{", "}", descriptor_);
579 WriteFieldDocComment(printer, descriptor_);
580 printer->Print(variables_,
581 "@java.lang.Override\n"
582 "$deprecation$public java.util.Map<$boxed_key_type$, "
583 "$value_enum_type$>\n"
584 "${$get$capitalized_name$Map$}$() {\n"
585 " return internalGetAdapted$capitalized_name$Map(\n"
586 " internalGet$capitalized_name$().getMap());"
587 "}\n");
588 printer->Annotate("{", "}", descriptor_);
589
590 WriteFieldDocComment(printer, descriptor_);
591 printer->Print(
592 variables_,
593 "@java.lang.Override\n"
594 "$deprecation$public $value_enum_type_pass_through_nullness$ "
595 "${$get$capitalized_name$OrDefault$}$(\n"
596 " $key_type$ key,\n"
597 " $value_enum_type_pass_through_nullness$ defaultValue) {\n"
598 " $key_null_check$\n"
599 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
600 " internalGet$capitalized_name$().getMap();\n"
601 " return map.containsKey(key)\n"
602 " ? $name$ValueConverter.doForward(map.get(key))\n"
603 " : defaultValue;\n"
604 "}\n");
605 printer->Annotate("{", "}", descriptor_);
606
607 WriteFieldDocComment(printer, descriptor_);
608 printer->Print(
609 variables_,
610 "@java.lang.Override\n"
611 "$deprecation$public $value_enum_type$ get$capitalized_name$OrThrow(\n"
612 " $key_type$ key) {\n"
613 " $key_null_check$\n"
614 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
615 " internalGet$capitalized_name$().getMap();\n"
616 " if (!map.containsKey(key)) {\n"
617 " throw new java.lang.IllegalArgumentException();\n"
618 " }\n"
619 " return $name$ValueConverter.doForward(map.get(key));\n"
620 "}\n");
621 printer->Annotate("{", "}", descriptor_);
622
623 if (SupportUnknownEnumValue(descriptor_->file())) {
624 printer->Print(
625 variables_,
626 "/**\n"
627 " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
628 " */\n"
629 "@java.lang.Override\n"
630 "@java.lang.Deprecated\n"
631 "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
632 "${$get$capitalized_name$Value$}$() {\n"
633 " return get$capitalized_name$ValueMap();\n"
634 "}\n");
635 printer->Annotate("{", "}", descriptor_);
636 WriteFieldDocComment(printer, descriptor_);
637 printer->Print(variables_,
638 "@java.lang.Override\n"
639 "$deprecation$public java.util.Map<$boxed_key_type$, "
640 "$boxed_value_type$>\n"
641 "${$get$capitalized_name$ValueMap$}$() {\n"
642 " return internalGet$capitalized_name$().getMap();\n"
643 "}\n");
644 printer->Annotate("{", "}", descriptor_);
645 WriteFieldDocComment(printer, descriptor_);
646 printer->Print(
647 variables_,
648 "@java.lang.Override\n"
649 "$deprecation$public $value_type_pass_through_nullness$ "
650 "${$get$capitalized_name$ValueOrDefault$}$(\n"
651 " $key_type$ key,\n"
652 " $value_type_pass_through_nullness$ defaultValue) {\n"
653 " $key_null_check$\n"
654 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
655 " internalGet$capitalized_name$().getMap();\n"
656 " return map.containsKey(key) ? map.get(key) : defaultValue;\n"
657 "}\n");
658 printer->Annotate("{", "}", descriptor_);
659 WriteFieldDocComment(printer, descriptor_);
660 printer->Print(
661 variables_,
662 "@java.lang.Override\n"
663 "$deprecation$public $value_type$ "
664 "${$get$capitalized_name$ValueOrThrow$}$(\n"
665 " $key_type$ key) {\n"
666 " $key_null_check$\n"
667 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
668 " internalGet$capitalized_name$().getMap();\n"
669 " if (!map.containsKey(key)) {\n"
670 " throw new java.lang.IllegalArgumentException();\n"
671 " }\n"
672 " return map.get(key);\n"
673 "}\n");
674 printer->Annotate("{", "}", descriptor_);
675 }
676 } else {
677 printer->Print(variables_,
678 "/**\n"
679 " * Use {@link #get$capitalized_name$Map()} instead.\n"
680 " */\n"
681 "@java.lang.Override\n"
682 "@java.lang.Deprecated\n"
683 "public java.util.Map<$type_parameters$> "
684 "${$get$capitalized_name$$}$() {\n"
685 " return get$capitalized_name$Map();\n"
686 "}\n");
687 printer->Annotate("{", "}", descriptor_);
688 WriteFieldDocComment(printer, descriptor_);
689 printer->Print(variables_,
690 "@java.lang.Override\n"
691 "$deprecation$public java.util.Map<$type_parameters$> "
692 "${$get$capitalized_name$Map$}$() {\n"
693 " return internalGet$capitalized_name$().getMap();\n"
694 "}\n");
695 printer->Annotate("{", "}", descriptor_);
696 WriteFieldDocComment(printer, descriptor_);
697 printer->Print(
698 variables_,
699 "@java.lang.Override\n"
700 "$deprecation$public $value_type_pass_through_nullness$ "
701 "${$get$capitalized_name$OrDefault$}$(\n"
702 " $key_type$ key,\n"
703 " $value_type_pass_through_nullness$ defaultValue) {\n"
704 " $key_null_check$\n"
705 " java.util.Map<$type_parameters$> map =\n"
706 " internalGet$capitalized_name$().getMap();\n"
707 " return map.containsKey(key) ? map.get(key) : defaultValue;\n"
708 "}\n");
709 printer->Annotate("{", "}", descriptor_);
710 WriteFieldDocComment(printer, descriptor_);
711 printer->Print(
712 variables_,
713 "@java.lang.Override\n"
714 "$deprecation$public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
715 " $key_type$ key) {\n"
716 " $key_null_check$\n"
717 " java.util.Map<$type_parameters$> map =\n"
718 " internalGet$capitalized_name$().getMap();\n"
719 " if (!map.containsKey(key)) {\n"
720 " throw new java.lang.IllegalArgumentException();\n"
721 " }\n"
722 " return map.get(key);\n"
723 "}\n");
724 printer->Annotate("{", "}", descriptor_);
725 }
726 }
727
GenerateKotlinDslMembers(io::Printer * printer) const728 void ImmutableMapFieldGenerator::GenerateKotlinDslMembers(
729 io::Printer* printer) const {
730 printer->Print(
731 variables_,
732 "/**\n"
733 " * An uninstantiable, behaviorless type to represent the field in\n"
734 " * generics.\n"
735 " */\n"
736 "@kotlin.OptIn"
737 "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
738 "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
739 " : com.google.protobuf.kotlin.DslProxy()\n");
740
741 WriteFieldDocComment(printer, descriptor_);
742 printer->Print(
743 variables_,
744 "$kt_deprecation$ public val $kt_name$: "
745 "com.google.protobuf.kotlin.DslMap"
746 "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
747 " @kotlin.jvm.JvmSynthetic\n"
748 " @JvmName(\"get$kt_capitalized_name$Map\")\n"
749 " get() = com.google.protobuf.kotlin.DslMap(\n"
750 " $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n"
751 " )\n");
752
753 WriteFieldDocComment(printer, descriptor_);
754 printer->Print(
755 variables_,
756 "@JvmName(\"put$kt_capitalized_name$\")\n"
757 "public fun com.google.protobuf.kotlin.DslMap"
758 "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
759 " .put(key: $kt_key_type$, value: $kt_value_type$) {\n"
760 " $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n"
761 " }\n");
762
763 WriteFieldDocComment(printer, descriptor_);
764 printer->Print(
765 variables_,
766 "@kotlin.jvm.JvmSynthetic\n"
767 "@JvmName(\"set$kt_capitalized_name$\")\n"
768 "@Suppress(\"NOTHING_TO_INLINE\")\n"
769 "public inline operator fun com.google.protobuf.kotlin.DslMap"
770 "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
771 " .set(key: $kt_key_type$, value: $kt_value_type$) {\n"
772 " put(key, value)\n"
773 " }\n");
774
775 WriteFieldDocComment(printer, descriptor_);
776 printer->Print(
777 variables_,
778 "@kotlin.jvm.JvmSynthetic\n"
779 "@JvmName(\"remove$kt_capitalized_name$\")\n"
780 "public fun com.google.protobuf.kotlin.DslMap"
781 "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
782 " .remove(key: $kt_key_type$) {\n"
783 " $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n"
784 " }\n");
785
786 WriteFieldDocComment(printer, descriptor_);
787 printer->Print(
788 variables_,
789 "@kotlin.jvm.JvmSynthetic\n"
790 "@JvmName(\"putAll$kt_capitalized_name$\")\n"
791 "public fun com.google.protobuf.kotlin.DslMap"
792 "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
793 " .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) "
794 "{\n"
795 " $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n"
796 " }\n");
797
798 WriteFieldDocComment(printer, descriptor_);
799 printer->Print(
800 variables_,
801 "@kotlin.jvm.JvmSynthetic\n"
802 "@JvmName(\"clear$kt_capitalized_name$\")\n"
803 "public fun com.google.protobuf.kotlin.DslMap"
804 "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
805 " .clear() {\n"
806 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
807 " }\n");
808 }
809
GenerateFieldBuilderInitializationCode(io::Printer * printer) const810 void ImmutableMapFieldGenerator::GenerateFieldBuilderInitializationCode(
811 io::Printer* printer) const {
812 // Nothing to initialize.
813 }
814
GenerateInitializationCode(io::Printer * printer) const815 void ImmutableMapFieldGenerator::GenerateInitializationCode(
816 io::Printer* printer) const {
817 // Nothing to initialize.
818 }
819
GenerateBuilderClearCode(io::Printer * printer) const820 void ImmutableMapFieldGenerator::GenerateBuilderClearCode(
821 io::Printer* printer) const {
822 // No need to clear the has-bit since we clear the bitField ints all at once.
823 printer->Print(variables_,
824 "internalGetMutable$capitalized_name$().clear();\n");
825 }
826
GenerateMergingCode(io::Printer * printer) const827 void ImmutableMapFieldGenerator::GenerateMergingCode(
828 io::Printer* printer) const {
829 printer->Print(variables_,
830 "internalGetMutable$capitalized_name$().mergeFrom(\n"
831 " other.internalGet$capitalized_name$());\n"
832 "$set_has_field_bit_builder$\n");
833 }
834
GenerateBuildingCode(io::Printer * printer) const835 void ImmutableMapFieldGenerator::GenerateBuildingCode(
836 io::Printer* printer) const {
837 printer->Print(variables_,
838 "if ($get_has_field_bit_from_local$) {\n"
839 " result.$name$_ = internalGet$capitalized_name$();\n"
840 " result.$name$_.makeImmutable();\n"
841 "}\n");
842 }
843
GenerateBuilderParsingCode(io::Printer * printer) const844 void ImmutableMapFieldGenerator::GenerateBuilderParsingCode(
845 io::Printer* printer) const {
846 if (!SupportUnknownEnumValue(descriptor_->file()) &&
847 GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
848 printer->Print(
849 variables_,
850 "com.google.protobuf.ByteString bytes = input.readBytes();\n"
851 "com.google.protobuf.MapEntry<$type_parameters$>\n"
852 "$name$__ = $default_entry$.getParserForType().parseFrom(bytes);\n"
853 "if ($value_enum_type$.forNumber($name$__.getValue()) == null) {\n"
854 " mergeUnknownLengthDelimitedField($number$, bytes);\n"
855 "} else {\n"
856 " internalGetMutable$capitalized_name$().getMutableMap().put(\n"
857 " $name$__.getKey(), $name$__.getValue());\n"
858 " $set_has_field_bit_builder$\n"
859 "}\n");
860 } else {
861 printer->Print(
862 variables_,
863 "com.google.protobuf.MapEntry<$type_parameters$>\n"
864 "$name$__ = input.readMessage(\n"
865 " $default_entry$.getParserForType(), extensionRegistry);\n"
866 "internalGetMutable$capitalized_name$().getMutableMap().put(\n"
867 " $name$__.getKey(), $name$__.getValue());\n"
868 "$set_has_field_bit_builder$\n");
869 }
870 }
GenerateSerializationCode(io::Printer * printer) const871 void ImmutableMapFieldGenerator::GenerateSerializationCode(
872 io::Printer* printer) const {
873 printer->Print(variables_,
874 "com.google.protobuf.GeneratedMessage$ver$\n"
875 " .serialize$short_key_type$MapTo(\n"
876 " output,\n"
877 " internalGet$capitalized_name$(),\n"
878 " $default_entry$,\n"
879 " $number$);\n");
880 }
881
GenerateSerializedSizeCode(io::Printer * printer) const882 void ImmutableMapFieldGenerator::GenerateSerializedSizeCode(
883 io::Printer* printer) const {
884 printer->Print(
885 variables_,
886 "for (java.util.Map.Entry<$type_parameters$> entry\n"
887 " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
888 " com.google.protobuf.MapEntry<$type_parameters$>\n"
889 " $name$__ = $default_entry$.newBuilderForType()\n"
890 " .setKey(entry.getKey())\n"
891 " .setValue(entry.getValue())\n"
892 " .build();\n"
893 " size += com.google.protobuf.CodedOutputStream\n"
894 " .computeMessageSize($number$, $name$__);\n"
895 "}\n");
896 }
897
GenerateEqualsCode(io::Printer * printer) const898 void ImmutableMapFieldGenerator::GenerateEqualsCode(
899 io::Printer* printer) const {
900 printer->Print(variables_,
901 "if (!internalGet$capitalized_name$().equals(\n"
902 " other.internalGet$capitalized_name$())) return false;\n");
903 }
904
GenerateHashCode(io::Printer * printer) const905 void ImmutableMapFieldGenerator::GenerateHashCode(io::Printer* printer) const {
906 printer->Print(
907 variables_,
908 "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
909 " hash = (37 * hash) + $constant_name$;\n"
910 " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
911 "}\n");
912 }
913
GetBoxedType() const914 std::string ImmutableMapFieldGenerator::GetBoxedType() const {
915 return name_resolver_->GetImmutableClassName(descriptor_->message_type());
916 }
917
918 } // namespace java
919 } // namespace compiler
920 } // namespace protobuf
921 } // namespace google
922
923 #include "google/protobuf/port_undef.inc"
924