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