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 <google/protobuf/compiler/java/java_context.h>
34 #include <google/protobuf/compiler/java/java_doc_comment.h>
35 #include <google/protobuf/compiler/java/java_helpers.h>
36 #include <google/protobuf/compiler/java/java_name_resolver.h>
37 #include <google/protobuf/io/printer.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->FindFieldByName("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->FindFieldByName("value");
58 }
59 
TypeName(const FieldDescriptor * field,ClassNameResolver * name_resolver,bool boxed)60 string TypeName(const FieldDescriptor* field,
61                 ClassNameResolver* name_resolver,
62                 bool boxed) {
63   if (GetJavaType(field) == JAVATYPE_MESSAGE) {
64     return name_resolver->GetImmutableClassName(field->message_type());
65   } else if (GetJavaType(field) == JAVATYPE_ENUM) {
66     return name_resolver->GetImmutableClassName(field->enum_type());
67   } else {
68     return boxed ? BoxedPrimitiveTypeName(GetJavaType(field))
69                  : PrimitiveTypeName(GetJavaType(field));
70   }
71 }
72 
WireType(const FieldDescriptor * field)73 string WireType(const FieldDescriptor* field) {
74   return "com.google.protobuf.WireFormat.FieldType." +
75       string(FieldTypeName(field->type()));
76 }
77 
SetMessageVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,Context * context,map<string,string> * variables)78 void SetMessageVariables(const FieldDescriptor* descriptor,
79                          int messageBitIndex,
80                          int builderBitIndex,
81                          const FieldGeneratorInfo* info,
82                          Context* context,
83                          map<string, string>* variables) {
84   SetCommonFieldVariables(descriptor, info, variables);
85 
86   ClassNameResolver* name_resolver = context->GetNameResolver();
87   (*variables)["type"] =
88       name_resolver->GetImmutableClassName(descriptor->message_type());
89   const FieldDescriptor* key = KeyField(descriptor);
90   const FieldDescriptor* value = ValueField(descriptor);
91   const JavaType keyJavaType = GetJavaType(key);
92   const JavaType valueJavaType = GetJavaType(value);
93 
94   (*variables)["key_type"] = TypeName(key, name_resolver, false);
95   (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
96   (*variables)["key_wire_type"] = WireType(key);
97   (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
98   (*variables)["key_null_check"] = IsReferenceType(keyJavaType) ?
99       "if (key == null) { throw new java.lang.NullPointerException(); }" : "";
100   (*variables)["value_null_check"] = IsReferenceType(valueJavaType) ?
101       "if (value == null) { throw new java.lang.NullPointerException(); }" : "";
102 
103   if (GetJavaType(value) == JAVATYPE_ENUM) {
104     // We store enums as Integers internally.
105     (*variables)["value_type"] = "int";
106     (*variables)["boxed_value_type"] = "java.lang.Integer";
107     (*variables)["value_wire_type"] = WireType(value);
108     (*variables)["value_default_value"] =
109         DefaultValue(value, true, name_resolver) + ".getNumber()";
110 
111     (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
112 
113     if (SupportUnknownEnumValue(descriptor->file())) {
114       // Map unknown values to a special UNRECOGNIZED value if supported.
115       (*variables)["unrecognized_value"] =
116           (*variables)["value_enum_type"] + ".UNRECOGNIZED";
117     } else {
118       // Map unknown values to the default value if we don't have UNRECOGNIZED.
119       (*variables)["unrecognized_value"] =
120           DefaultValue(value, true, name_resolver);
121     }
122   } else {
123     (*variables)["value_type"] = TypeName(value, name_resolver, false);
124     (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
125     (*variables)["value_wire_type"] = WireType(value);
126     (*variables)["value_default_value"] =
127         DefaultValue(value, true, name_resolver);
128   }
129   (*variables)["type_parameters"] =
130       (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
131   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
132   // by the proto compiler
133   (*variables)["deprecation"] = descriptor->options().deprecated()
134       ? "@java.lang.Deprecated " : "";
135 
136   (*variables)["default_entry"] = (*variables)["capitalized_name"] +
137       "DefaultEntryHolder.defaultEntry";
138 }
139 
140 }  // namespace
141 
142 ImmutableMapFieldLiteGenerator::
ImmutableMapFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)143 ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor,
144                                        int messageBitIndex,
145                                        int builderBitIndex,
146                                        Context* context)
147   : descriptor_(descriptor), name_resolver_(context->GetNameResolver())  {
148   SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
149                       context->GetFieldGeneratorInfo(descriptor),
150                       context, &variables_);
151 }
152 
153 ImmutableMapFieldLiteGenerator::
~ImmutableMapFieldLiteGenerator()154 ~ImmutableMapFieldLiteGenerator() {}
155 
GetNumBitsForMessage() const156 int ImmutableMapFieldLiteGenerator::GetNumBitsForMessage() const {
157   return 0;
158 }
159 
GetNumBitsForBuilder() const160 int ImmutableMapFieldLiteGenerator::GetNumBitsForBuilder() const {
161   return 0;
162 }
163 
164 void ImmutableMapFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer * printer) const165 GenerateInterfaceMembers(io::Printer* printer) const {
166   WriteFieldDocComment(printer, descriptor_);
167   printer->Print(
168       variables_,
169       "$deprecation$int get$capitalized_name$Count();\n");
170   WriteFieldDocComment(printer, descriptor_);
171   printer->Print(
172       variables_,
173       "$deprecation$boolean contains$capitalized_name$(\n"
174       "    $key_type$ key);\n");
175   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
176     printer->Print(
177         variables_,
178         "/**\n"
179         " * Use {@link #get$capitalized_name$Map()} instead.\n"
180         " */\n"
181         "@java.lang.Deprecated\n"
182         "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
183         "get$capitalized_name$();\n");
184     WriteFieldDocComment(printer, descriptor_);
185     printer->Print(
186         variables_,
187         "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
188         "get$capitalized_name$Map();\n");
189     WriteFieldDocComment(printer, descriptor_);
190     printer->Print(
191         variables_,
192         "$deprecation$$value_enum_type$ get$capitalized_name$OrDefault(\n"
193         "    $key_type$ key,\n"
194         "    $value_enum_type$ defaultValue);\n");
195     WriteFieldDocComment(printer, descriptor_);
196     printer->Print(
197         variables_,
198         "$deprecation$$value_enum_type$ get$capitalized_name$OrThrow(\n"
199         "    $key_type$ key);\n");
200     if (SupportUnknownEnumValue(descriptor_->file())) {
201       printer->Print(
202           variables_,
203           "/**\n"
204           " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
205           " */\n"
206           "@java.lang.Deprecated\n"
207           "java.util.Map<$type_parameters$>\n"
208           "get$capitalized_name$Value();\n");
209       WriteFieldDocComment(printer, descriptor_);
210       printer->Print(
211           variables_,
212           "$deprecation$java.util.Map<$type_parameters$>\n"
213           "get$capitalized_name$ValueMap();\n");
214       WriteFieldDocComment(printer, descriptor_);
215       printer->Print(
216           variables_,
217           "$deprecation$\n"
218           "$value_type$ get$capitalized_name$ValueOrDefault(\n"
219           "    $key_type$ key,\n"
220           "    $value_type$ defaultValue);\n");
221       WriteFieldDocComment(printer, descriptor_);
222       printer->Print(
223           variables_,
224           "$deprecation$\n"
225           "$value_type$ get$capitalized_name$ValueOrThrow(\n"
226           "    $key_type$ key);\n");
227     }
228   } else {
229     printer->Print(
230         variables_,
231         "/**\n"
232         " * Use {@link #get$capitalized_name$Map()} instead.\n"
233         " */\n"
234         "@java.lang.Deprecated\n"
235         "java.util.Map<$type_parameters$>\n"
236         "get$capitalized_name$();\n");
237     WriteFieldDocComment(printer, descriptor_);
238     printer->Print(
239         variables_,
240         "$deprecation$java.util.Map<$type_parameters$>\n"
241         "get$capitalized_name$Map();\n");
242     WriteFieldDocComment(printer, descriptor_);
243     printer->Print(
244         variables_,
245         "$deprecation$\n"
246         "$value_type$ get$capitalized_name$OrDefault(\n"
247         "    $key_type$ key,\n"
248         "    $value_type$ defaultValue);\n");
249     WriteFieldDocComment(printer, descriptor_);
250     printer->Print(
251         variables_,
252         "$deprecation$\n"
253         "$value_type$ get$capitalized_name$OrThrow(\n"
254         "    $key_type$ key);\n");
255   }
256 }
257 
258 void ImmutableMapFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const259 GenerateMembers(io::Printer* printer) const {
260   printer->Print(
261       variables_,
262       "private static final class $capitalized_name$DefaultEntryHolder {\n"
263       "  static final com.google.protobuf.MapEntryLite<\n"
264       "      $type_parameters$> defaultEntry =\n"
265       "          com.google.protobuf.MapEntryLite\n"
266       "          .<$type_parameters$>newDefaultInstance(\n"
267       "              $key_wire_type$,\n"
268       "              $key_default_value$,\n"
269       "              $value_wire_type$,\n"
270       "              $value_default_value$);\n"
271       "}\n");
272   printer->Print(
273       variables_,
274       "private com.google.protobuf.MapFieldLite<\n"
275       "    $type_parameters$> $name$_ =\n"
276       "        com.google.protobuf.MapFieldLite.emptyMapField();\n"
277       "private com.google.protobuf.MapFieldLite<$type_parameters$>\n"
278       "internalGet$capitalized_name$() {\n"
279       "  return $name$_;\n"
280       "}\n"
281       "private com.google.protobuf.MapFieldLite<$type_parameters$>\n"
282       "internalGetMutable$capitalized_name$() {\n"
283       "  if (!$name$_.isMutable()) {\n"
284       "    $name$_ = $name$_.mutableCopy();\n"
285       "  }\n"
286       "  return $name$_;\n"
287       "}\n");
288   printer->Print(
289       variables_,
290       "$deprecation$\n"
291       "public int get$capitalized_name$Count() {\n"
292       "  return internalGet$capitalized_name$().size();\n"
293       "}\n");
294   WriteFieldDocComment(printer, descriptor_);
295   printer->Print(
296       variables_,
297       "$deprecation$\n"
298       "public boolean contains$capitalized_name$(\n"
299       "    $key_type$ key) {\n"
300       "  $key_null_check$\n"
301       "  return internalGet$capitalized_name$().containsKey(key);\n"
302       "}\n");
303   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
304     printer->Print(
305         variables_,
306         "private static final\n"
307         "com.google.protobuf.Internal.MapAdapter.Converter<\n"
308         "    java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
309         "        com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
310         "            $value_enum_type$.internalGetValueMap(),\n"
311         "            $unrecognized_value$);\n");
312     printer->Print(
313         variables_,
314         "/**\n"
315         " * Use {@link #get$capitalized_name$Map()} instead.\n"
316         " */\n"
317         "@java.lang.Deprecated\n"
318         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
319         "get$capitalized_name$() {\n"
320         "  return get$capitalized_name$Map();\n"
321         "}\n");
322     WriteFieldDocComment(printer, descriptor_);
323     printer->Print(
324         variables_,
325         "$deprecation$\n"
326         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
327         "get$capitalized_name$Map() {\n"
328         "  return java.util.Collections.unmodifiableMap(\n"
329         "      new com.google.protobuf.Internal.MapAdapter<\n"
330         "        $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
331         "            internalGet$capitalized_name$(),\n"
332         "            $name$ValueConverter));\n"
333         "}\n");
334     WriteFieldDocComment(printer, descriptor_);
335     printer->Print(
336         variables_,
337         "$deprecation$\n"
338         "public $value_enum_type$ get$capitalized_name$OrDefault(\n"
339         "    $key_type$ key,\n"
340         "    $value_enum_type$ defaultValue) {\n"
341         "  $key_null_check$\n"
342         "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
343         "      internalGet$capitalized_name$();\n"
344         "  return map.containsKey(key)\n"
345         "         ? $name$ValueConverter.doForward(map.get(key))\n"
346         "         : defaultValue;\n"
347         "}\n");
348     WriteFieldDocComment(printer, descriptor_);
349     printer->Print(
350         variables_,
351         "$deprecation$\n"
352         "public $value_enum_type$ get$capitalized_name$OrThrow(\n"
353         "    $key_type$ key) {\n"
354         "  $key_null_check$\n"
355         "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
356         "      internalGet$capitalized_name$();\n"
357         "  if (!map.containsKey(key)) {\n"
358         "    throw new java.lang.IllegalArgumentException();\n"
359         "  }\n"
360         "  return $name$ValueConverter.doForward(map.get(key));\n"
361         "}\n");
362     if (SupportUnknownEnumValue(descriptor_->file())) {
363       printer->Print(
364           variables_,
365           "/**\n"
366           " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
367           " */\n"
368           "@java.lang.Deprecated\n"
369           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
370           "get$capitalized_name$Value() {\n"
371           "  return get$capitalized_name$ValueMap();\n"
372           "}\n");
373       WriteFieldDocComment(printer, descriptor_);
374       printer->Print(
375           variables_,
376           "$deprecation$\n"
377           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
378           "get$capitalized_name$ValueMap() {\n"
379           "  return java.util.Collections.unmodifiableMap(\n"
380           "      internalGet$capitalized_name$());\n"
381           "}\n");
382       WriteFieldDocComment(printer, descriptor_);
383       printer->Print(
384           variables_,
385           "$deprecation$\n"
386           "public $value_type$ get$capitalized_name$ValueOrDefault(\n"
387           "    $key_type$ key,\n"
388           "    $value_type$ defaultValue) {\n"
389           "  $key_null_check$\n"
390           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
391           "      internalGet$capitalized_name$();\n"
392           "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
393           "}\n");
394       WriteFieldDocComment(printer, descriptor_);
395       printer->Print(
396           variables_,
397           "$deprecation$\n"
398           "public $value_type$ get$capitalized_name$ValueOrThrow(\n"
399           "    $key_type$ key) {\n"
400           "  $key_null_check$\n"
401           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
402           "      internalGet$capitalized_name$();\n"
403           "  if (!map.containsKey(key)) {\n"
404           "    throw new java.lang.IllegalArgumentException();\n"
405           "  }\n"
406           "  return map.get(key);\n"
407           "}\n");
408     }
409   } else {
410     printer->Print(
411         variables_,
412         "/**\n"
413         " * Use {@link #get$capitalized_name$Map()} instead.\n"
414         " */\n"
415         "@java.lang.Deprecated\n"
416         "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
417         "  return get$capitalized_name$Map();\n"
418         "}\n");
419     WriteFieldDocComment(printer, descriptor_);
420     printer->Print(
421         variables_,
422         "$deprecation$\n"
423         "public java.util.Map<$type_parameters$> get$capitalized_name$Map() {\n"
424         "  return java.util.Collections.unmodifiableMap(\n"
425         "      internalGet$capitalized_name$());\n"
426         "}\n");
427     WriteFieldDocComment(printer, descriptor_);
428     printer->Print(
429         variables_,
430         "$deprecation$\n"
431         "public $value_type$ get$capitalized_name$OrDefault(\n"
432         "    $key_type$ key,\n"
433         "    $value_type$ defaultValue) {\n"
434         "  $key_null_check$\n"
435         "  java.util.Map<$type_parameters$> map =\n"
436         "      internalGet$capitalized_name$();\n"
437         "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
438         "}\n");
439     WriteFieldDocComment(printer, descriptor_);
440     printer->Print(
441         variables_,
442         "$deprecation$\n"
443         "public $value_type$ get$capitalized_name$OrThrow(\n"
444         "    $key_type$ key) {\n"
445         "  $key_null_check$\n"
446         "  java.util.Map<$type_parameters$> 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   }
454 
455   // Generate private setters for the builder to proxy into.
456   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
457     WriteFieldDocComment(printer, descriptor_);
458     printer->Print(
459         variables_,
460         "private java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
461         "getMutable$capitalized_name$Map() {\n"
462         "  return new com.google.protobuf.Internal.MapAdapter<\n"
463         "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
464         "          internalGetMutable$capitalized_name$(),\n"
465         "          $name$ValueConverter);\n"
466         "}\n");
467     if (SupportUnknownEnumValue(descriptor_->file())) {
468       WriteFieldDocComment(printer, descriptor_);
469       printer->Print(
470           variables_,
471           "private java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
472           "getMutable$capitalized_name$ValueMap() {\n"
473           "  return internalGetMutable$capitalized_name$();\n"
474           "}\n");
475     }
476   } else {
477     WriteFieldDocComment(printer, descriptor_);
478     printer->Print(
479         variables_,
480         "private java.util.Map<$type_parameters$>\n"
481         "getMutable$capitalized_name$Map() {\n"
482         "  return internalGetMutable$capitalized_name$();\n"
483         "}\n");
484   }
485 }
486 
487 void ImmutableMapFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const488 GenerateBuilderMembers(io::Printer* printer) const {
489   printer->Print(
490       variables_,
491       "$deprecation$\n"
492       "public int get$capitalized_name$Count() {\n"
493       "  return instance.get$capitalized_name$Map().size();\n"
494       "}\n");
495   WriteFieldDocComment(printer, descriptor_);
496   printer->Print(
497       variables_,
498       "$deprecation$\n"
499       "public boolean contains$capitalized_name$(\n"
500       "    $key_type$ key) {\n"
501       "  $key_null_check$\n"
502       "  return instance.get$capitalized_name$Map().containsKey(key);\n"
503       "}\n");
504   printer->Print(
505       variables_,
506       "$deprecation$\n"
507       "public Builder clear$capitalized_name$() {\n"
508       "  copyOnWrite();\n"
509       "  instance.getMutable$capitalized_name$Map().clear();\n"
510       "  return this;\n"
511       "}\n");
512   WriteFieldDocComment(printer, descriptor_);
513   printer->Print(
514       variables_,
515       "$deprecation$\n"
516       "public Builder remove$capitalized_name$(\n"
517       "    $key_type$ key) {\n"
518       "  $key_null_check$\n"
519       "  copyOnWrite();\n"
520       "  instance.getMutable$capitalized_name$Map().remove(key);\n"
521       "  return this;\n"
522       "}\n");
523   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
524     printer->Print(
525         variables_,
526         "/**\n"
527         " * Use {@link #get$capitalized_name$Map()} instead.\n"
528         " */\n"
529         "@java.lang.Deprecated\n"
530         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
531         "get$capitalized_name$() {\n"
532         "  return get$capitalized_name$Map();\n"
533         "}\n");
534     WriteFieldDocComment(printer, descriptor_);
535     printer->Print(
536         variables_,
537         "$deprecation$\n"
538         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
539         "get$capitalized_name$Map() {\n"
540         "  return java.util.Collections.unmodifiableMap(\n"
541         "      instance.get$capitalized_name$Map());\n"
542         "}\n");
543     WriteFieldDocComment(printer, descriptor_);
544     printer->Print(
545         variables_,
546         "$deprecation$\n"
547         "public $value_enum_type$ get$capitalized_name$OrDefault(\n"
548         "    $key_type$ key,\n"
549         "    $value_enum_type$ defaultValue) {\n"
550         "  $key_null_check$\n"
551         "  java.util.Map<$boxed_key_type$, $value_enum_type$> map =\n"
552         "      instance.get$capitalized_name$Map();\n"
553         "  return map.containsKey(key)\n"
554         "         ? map.get(key)\n"
555         "         : defaultValue;\n"
556         "}\n");
557     WriteFieldDocComment(printer, descriptor_);
558     printer->Print(
559         variables_,
560         "$deprecation$\n"
561         "public $value_enum_type$ get$capitalized_name$OrThrow(\n"
562         "    $key_type$ key) {\n"
563         "  $key_null_check$\n"
564         "  java.util.Map<$boxed_key_type$, $value_enum_type$> map =\n"
565         "      instance.get$capitalized_name$Map();\n"
566         "  if (!map.containsKey(key)) {\n"
567         "    throw new java.lang.IllegalArgumentException();\n"
568         "  }\n"
569         "  return map.get(key);\n"
570         "}\n");
571     WriteFieldDocComment(printer, descriptor_);
572     printer->Print(
573         variables_,
574         "$deprecation$public Builder put$capitalized_name$(\n"
575         "    $key_type$ key,\n"
576         "    $value_enum_type$ value) {\n"
577         "  $key_null_check$\n"
578         "  $value_null_check$\n"
579         "  copyOnWrite();\n"
580         "  instance.getMutable$capitalized_name$Map().put(key, value);\n"
581         "  return this;\n"
582         "}\n");
583     WriteFieldDocComment(printer, descriptor_);
584     printer->Print(
585         variables_,
586         "$deprecation$public Builder putAll$capitalized_name$(\n"
587         "    java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
588         "  copyOnWrite();\n"
589         "  instance.getMutable$capitalized_name$Map().putAll(values);\n"
590         "  return this;\n"
591         "}\n");
592     if (SupportUnknownEnumValue(descriptor_->file())) {
593       printer->Print(
594           variables_,
595           "/**\n"
596           " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
597           " */\n"
598           "@java.lang.Deprecated\n"
599           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
600           "get$capitalized_name$Value() {\n"
601           "  return get$capitalized_name$ValueMap();\n"
602           "}\n");
603       WriteFieldDocComment(printer, descriptor_);
604       printer->Print(
605           variables_,
606           "$deprecation$\n"
607           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
608           "get$capitalized_name$ValueMap() {\n"
609           "  return java.util.Collections.unmodifiableMap(\n"
610           "      instance.get$capitalized_name$ValueMap());\n"
611           "}\n");
612       WriteFieldDocComment(printer, descriptor_);
613       printer->Print(
614           variables_,
615           "$deprecation$\n"
616           "public $value_type$ get$capitalized_name$ValueOrDefault(\n"
617           "    $key_type$ key,\n"
618           "    $value_type$ defaultValue) {\n"
619           "  $key_null_check$\n"
620           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
621           "      instance.get$capitalized_name$ValueMap();\n"
622           "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
623           "}\n");
624       WriteFieldDocComment(printer, descriptor_);
625       printer->Print(
626           variables_,
627           "$deprecation$\n"
628           "public $value_type$ get$capitalized_name$ValueOrThrow(\n"
629           "    $key_type$ key) {\n"
630           "  $key_null_check$\n"
631           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
632           "      instance.get$capitalized_name$ValueMap();\n"
633           "  if (!map.containsKey(key)) {\n"
634           "    throw new java.lang.IllegalArgumentException();\n"
635           "  }\n"
636           "  return map.get(key);\n"
637           "}\n");
638       WriteFieldDocComment(printer, descriptor_);
639       printer->Print(
640           variables_,
641           "$deprecation$public Builder put$capitalized_name$Value(\n"
642           "    $key_type$ key,\n"
643           "    $value_type$ value) {\n"
644           "  $key_null_check$\n"
645           "  if ($value_enum_type$.forNumber(value) == null) {\n"
646           "    throw new java.lang.IllegalArgumentException();\n"
647           "  }\n"
648           "  copyOnWrite();\n"
649           "  instance.getMutable$capitalized_name$ValueMap().put(key, value);\n"
650           "  return this;\n"
651           "}\n");
652       WriteFieldDocComment(printer, descriptor_);
653       printer->Print(
654           variables_,
655           "$deprecation$public Builder putAll$capitalized_name$Value(\n"
656           "    java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
657           "  copyOnWrite();\n"
658           "  instance.getMutable$capitalized_name$ValueMap().putAll(values);\n"
659           "  return this;\n"
660           "}\n");
661     }
662   } else {
663     printer->Print(
664         variables_,
665         "/**\n"
666         " * Use {@link #get$capitalized_name$Map()} instead.\n"
667         " */\n"
668         "@java.lang.Deprecated\n"
669         "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
670         "  return get$capitalized_name$Map();\n"
671         "}\n");
672     WriteFieldDocComment(printer, descriptor_);
673     printer->Print(
674         variables_,
675         "$deprecation$"
676         "public java.util.Map<$type_parameters$> get$capitalized_name$Map() {\n"
677         "  return java.util.Collections.unmodifiableMap(\n"
678         "      instance.get$capitalized_name$Map());\n"
679         "}\n");
680     WriteFieldDocComment(printer, descriptor_);
681     printer->Print(
682         variables_,
683         "$deprecation$\n"
684         "public $value_type$ get$capitalized_name$OrDefault(\n"
685         "    $key_type$ key,\n"
686         "    $value_type$ defaultValue) {\n"
687         "  $key_null_check$\n"
688         "  java.util.Map<$type_parameters$> map =\n"
689         "      instance.get$capitalized_name$Map();\n"
690         "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
691         "}\n");
692     WriteFieldDocComment(printer, descriptor_);
693     printer->Print(
694         variables_,
695         "$deprecation$\n"
696         "public $value_type$ get$capitalized_name$OrThrow(\n"
697         "    $key_type$ key) {\n"
698         "  $key_null_check$\n"
699         "  java.util.Map<$type_parameters$> map =\n"
700         "      instance.get$capitalized_name$Map();\n"
701         "  if (!map.containsKey(key)) {\n"
702         "    throw new java.lang.IllegalArgumentException();\n"
703         "  }\n"
704         "  return map.get(key);\n"
705         "}\n");
706     WriteFieldDocComment(printer, descriptor_);
707     printer->Print(
708         variables_,
709         "$deprecation$"
710         "public Builder put$capitalized_name$(\n"
711         "    $key_type$ key,\n"
712         "    $value_type$ value) {\n"
713         "  $key_null_check$\n"
714         "  $value_null_check$\n"
715         "  copyOnWrite();\n"
716         "  instance.getMutable$capitalized_name$Map().put(key, value);\n"
717         "  return this;\n"
718         "}\n");
719     WriteFieldDocComment(printer, descriptor_);
720     printer->Print(
721         variables_,
722         "$deprecation$"
723         "public Builder putAll$capitalized_name$(\n"
724         "    java.util.Map<$type_parameters$> values) {\n"
725         "  copyOnWrite();\n"
726         "  instance.getMutable$capitalized_name$Map().putAll(values);\n"
727         "  return this;\n"
728         "}\n");
729   }
730 }
731 
732 void ImmutableMapFieldLiteGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const733 GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
734   // Nothing to initialize.
735 }
736 
737 void ImmutableMapFieldLiteGenerator::
GenerateInitializationCode(io::Printer * printer) const738 GenerateInitializationCode(io::Printer* printer) const {
739   // Nothing to initialize.
740 }
741 
742 void ImmutableMapFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const743 GenerateVisitCode(io::Printer* printer) const {
744   printer->Print(
745       variables_,
746       "$name$_ = visitor.visitMap(\n"
747       "    $name$_, other.internalGet$capitalized_name$());\n");
748 }
749 
750 void ImmutableMapFieldLiteGenerator::
GenerateDynamicMethodMakeImmutableCode(io::Printer * printer) const751 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
752   printer->Print(variables_,
753     "$name$_.makeImmutable();\n");
754 }
755 
756 void ImmutableMapFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const757 GenerateParsingCode(io::Printer* printer) const {
758   printer->Print(
759       variables_,
760       "if (!$name$_.isMutable()) {\n"
761       "  $name$_ = $name$_.mutableCopy();\n"
762       "}\n");
763   if (!SupportUnknownEnumValue(descriptor_->file()) &&
764       GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
765     printer->Print(
766         variables_,
767         "com.google.protobuf.ByteString bytes = input.readBytes();\n"
768         "java.util.Map.Entry<$type_parameters$> $name$ =\n"
769         "    $default_entry$.parseEntry(bytes, extensionRegistry);\n");
770     printer->Print(
771         variables_,
772         "if ($value_enum_type$.forNumber($name$.getValue()) == null) {\n"
773         "  super.mergeLengthDelimitedField($number$, bytes);\n"
774         "} else {\n"
775         "  $name$_.put($name$);\n"
776         "}\n");
777   } else {
778     printer->Print(
779         variables_,
780         "$default_entry$.parseInto($name$_, input, extensionRegistry);");
781   }
782 }
783 
784 void ImmutableMapFieldLiteGenerator::
GenerateParsingDoneCode(io::Printer * printer) const785 GenerateParsingDoneCode(io::Printer* printer) const {
786   // Nothing to do here.
787 }
788 
789 void ImmutableMapFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const790 GenerateSerializationCode(io::Printer* printer) const {
791   printer->Print(
792       variables_,
793       "for (java.util.Map.Entry<$type_parameters$> entry\n"
794       "     : internalGet$capitalized_name$().entrySet()) {\n"
795       "  $default_entry$.serializeTo(\n"
796       "      output, $number$, entry.getKey(), entry.getValue());\n"
797       "}\n");
798 }
799 
800 void ImmutableMapFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const801 GenerateSerializedSizeCode(io::Printer* printer) const {
802   printer->Print(
803       variables_,
804       "for (java.util.Map.Entry<$type_parameters$> entry\n"
805       "     : internalGet$capitalized_name$().entrySet()) {\n"
806       "  size += $default_entry$.computeMessageSize(\n"
807       "    $number$, entry.getKey(), entry.getValue());\n"
808       "}\n");
809 }
810 
811 void ImmutableMapFieldLiteGenerator::
GenerateEqualsCode(io::Printer * printer) const812 GenerateEqualsCode(io::Printer* printer) const {
813   printer->Print(
814       variables_,
815       "result = result && internalGet$capitalized_name$().equals(\n"
816       "    other.internalGet$capitalized_name$());\n");
817 }
818 
819 void ImmutableMapFieldLiteGenerator::
GenerateHashCode(io::Printer * printer) const820 GenerateHashCode(io::Printer* printer) const {
821   printer->Print(
822       variables_,
823       "if (!internalGet$capitalized_name$().isEmpty()) {\n"
824       "  hash = (37 * hash) + $constant_name$;\n"
825       "  hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
826       "}\n");
827 }
828 
GetBoxedType() const829 string ImmutableMapFieldLiteGenerator::GetBoxedType() const {
830   return name_resolver_->GetImmutableClassName(descriptor_->message_type());
831 }
832 
833 }  // namespace java
834 }  // namespace compiler
835 }  // namespace protobuf
836 }  // namespace google
837