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