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