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/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 ClassNameResolver* name_resolver = context->GetNameResolver();
86
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 if (valueJavaType == JAVATYPE_ENUM) {
103 // We store enums as Integers internally.
104 (*variables)["value_type"] = "int";
105 (*variables)["boxed_value_type"] = "java.lang.Integer";
106 (*variables)["value_wire_type"] = WireType(value);
107 (*variables)["value_default_value"] =
108 DefaultValue(value, true, name_resolver) + ".getNumber()";
109
110 (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
111
112 if (SupportUnknownEnumValue(descriptor->file())) {
113 // Map unknown values to a special UNRECOGNIZED value if supported.
114 (*variables)["unrecognized_value"] =
115 (*variables)["value_enum_type"] + ".UNRECOGNIZED";
116 } else {
117 // Map unknown values to the default value if we don't have UNRECOGNIZED.
118 (*variables)["unrecognized_value"] =
119 DefaultValue(value, true, name_resolver);
120 }
121 } else {
122 (*variables)["value_type"] = TypeName(value, name_resolver, false);
123 (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
124 (*variables)["value_wire_type"] = WireType(value);
125 (*variables)["value_default_value"] =
126 DefaultValue(value, true, name_resolver);
127 }
128 (*variables)["type_parameters"] =
129 (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
130 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
131 // by the proto compiler
132 (*variables)["deprecation"] = descriptor->options().deprecated()
133 ? "@java.lang.Deprecated " : "";
134 (*variables)["on_changed"] = "onChanged();";
135
136 // For repeated fields, one bit is used for whether the array is immutable
137 // in the parsing constructor.
138 (*variables)["get_mutable_bit_parser"] =
139 GenerateGetBitMutableLocal(builderBitIndex);
140 (*variables)["set_mutable_bit_parser"] =
141 GenerateSetBitMutableLocal(builderBitIndex);
142
143 (*variables)["default_entry"] = (*variables)["capitalized_name"] +
144 "DefaultEntryHolder.defaultEntry";
145 (*variables)["map_field_parameter"] = (*variables)["default_entry"];
146 (*variables)["descriptor"] =
147 name_resolver->GetImmutableClassName(descriptor->file()) +
148 ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
149 "_descriptor, ";
150 }
151
152 } // namespace
153
154 ImmutableMapFieldGenerator::
ImmutableMapFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)155 ImmutableMapFieldGenerator(const FieldDescriptor* descriptor,
156 int messageBitIndex,
157 int builderBitIndex,
158 Context* context)
159 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
160 SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
161 context->GetFieldGeneratorInfo(descriptor),
162 context, &variables_);
163 }
164
165 ImmutableMapFieldGenerator::
~ImmutableMapFieldGenerator()166 ~ImmutableMapFieldGenerator() {}
167
GetNumBitsForMessage() const168 int ImmutableMapFieldGenerator::GetNumBitsForMessage() const {
169 return 0;
170 }
171
GetNumBitsForBuilder() const172 int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const {
173 return 1;
174 }
175
176 void ImmutableMapFieldGenerator::
GenerateInterfaceMembers(io::Printer * printer) const177 GenerateInterfaceMembers(io::Printer* printer) const {
178 WriteFieldDocComment(printer, descriptor_);
179 printer->Print(
180 variables_,
181 "$deprecation$int get$capitalized_name$Count();\n");
182 WriteFieldDocComment(printer, descriptor_);
183 printer->Print(
184 variables_,
185 "$deprecation$boolean contains$capitalized_name$(\n"
186 " $key_type$ key);\n");
187 if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
188 printer->Print(
189 variables_,
190 "/**\n"
191 " * Use {@link #get$capitalized_name$Map()} instead.\n"
192 " */\n"
193 "@java.lang.Deprecated\n"
194 "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
195 "get$capitalized_name$();\n");
196 WriteFieldDocComment(printer, descriptor_);
197 printer->Print(
198 variables_,
199 "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
200 "get$capitalized_name$Map();\n");
201 WriteFieldDocComment(printer, descriptor_);
202 printer->Print(
203 variables_,
204 "$deprecation$$value_enum_type$ get$capitalized_name$OrDefault(\n"
205 " $key_type$ key,\n"
206 " $value_enum_type$ defaultValue);\n");
207 WriteFieldDocComment(printer, descriptor_);
208 printer->Print(
209 variables_,
210 "$deprecation$$value_enum_type$ get$capitalized_name$OrThrow(\n"
211 " $key_type$ key);\n");
212 if (SupportUnknownEnumValue(descriptor_->file())) {
213 printer->Print(
214 variables_,
215 "/**\n"
216 " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
217 " */\n"
218 "@java.lang.Deprecated\n"
219 "java.util.Map<$type_parameters$>\n"
220 "get$capitalized_name$Value();\n");
221 WriteFieldDocComment(printer, descriptor_);
222 printer->Print(
223 variables_,
224 "$deprecation$java.util.Map<$type_parameters$>\n"
225 "get$capitalized_name$ValueMap();\n");
226 WriteFieldDocComment(printer, descriptor_);
227 printer->Print(
228 variables_,
229 "$deprecation$\n"
230 "$value_type$ get$capitalized_name$ValueOrDefault(\n"
231 " $key_type$ key,\n"
232 " $value_type$ defaultValue);\n");
233 WriteFieldDocComment(printer, descriptor_);
234 printer->Print(
235 variables_,
236 "$deprecation$\n"
237 "$value_type$ get$capitalized_name$ValueOrThrow(\n"
238 " $key_type$ key);\n");
239 }
240 } else {
241 printer->Print(
242 variables_,
243 "/**\n"
244 " * Use {@link #get$capitalized_name$Map()} instead.\n"
245 " */\n"
246 "@java.lang.Deprecated\n"
247 "java.util.Map<$type_parameters$>\n"
248 "get$capitalized_name$();\n");
249 WriteFieldDocComment(printer, descriptor_);
250 printer->Print(
251 variables_,
252 "$deprecation$java.util.Map<$type_parameters$>\n"
253 "get$capitalized_name$Map();\n");
254 WriteFieldDocComment(printer, descriptor_);
255 printer->Print(
256 variables_,
257 "$deprecation$\n"
258 "$value_type$ get$capitalized_name$OrDefault(\n"
259 " $key_type$ key,\n"
260 " $value_type$ defaultValue);\n");
261 WriteFieldDocComment(printer, descriptor_);
262 printer->Print(
263 variables_,
264 "$deprecation$\n"
265 "$value_type$ get$capitalized_name$OrThrow(\n"
266 " $key_type$ key);\n");
267 }
268 }
269
270 void ImmutableMapFieldGenerator::
GenerateMembers(io::Printer * printer) const271 GenerateMembers(io::Printer* printer) const {
272 printer->Print(
273 variables_,
274 "private static final class $capitalized_name$DefaultEntryHolder {\n"
275 " static final com.google.protobuf.MapEntry<\n"
276 " $type_parameters$> defaultEntry =\n"
277 " com.google.protobuf.MapEntry\n"
278 " .<$type_parameters$>newDefaultInstance(\n"
279 " $descriptor$\n"
280 " $key_wire_type$,\n"
281 " $key_default_value$,\n"
282 " $value_wire_type$,\n"
283 " $value_default_value$);\n"
284 "}\n");
285 printer->Print(
286 variables_,
287 "private com.google.protobuf.MapField<\n"
288 " $type_parameters$> $name$_;\n"
289 "private com.google.protobuf.MapField<$type_parameters$>\n"
290 "internalGet$capitalized_name$() {\n"
291 " if ($name$_ == null) {\n"
292 " return com.google.protobuf.MapField.emptyMapField(\n"
293 " $map_field_parameter$);\n"
294 " }\n"
295 " return $name$_;\n"
296 "}\n");
297 if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
298 printer->Print(
299 variables_,
300 "private static final\n"
301 "com.google.protobuf.Internal.MapAdapter.Converter<\n"
302 " java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
303 " com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
304 " $value_enum_type$.internalGetValueMap(),\n"
305 " $unrecognized_value$);\n");
306 }
307 GenerateMapGetters(printer);
308 }
309
310 void ImmutableMapFieldGenerator::
GenerateBuilderMembers(io::Printer * printer) const311 GenerateBuilderMembers(io::Printer* printer) const {
312 printer->Print(
313 variables_,
314 "private com.google.protobuf.MapField<\n"
315 " $type_parameters$> $name$_;\n"
316 "private com.google.protobuf.MapField<$type_parameters$>\n"
317 "internalGet$capitalized_name$() {\n"
318 " if ($name$_ == null) {\n"
319 " return com.google.protobuf.MapField.emptyMapField(\n"
320 " $map_field_parameter$);\n"
321 " }\n"
322 " return $name$_;\n"
323 "}\n"
324 "private com.google.protobuf.MapField<$type_parameters$>\n"
325 "internalGetMutable$capitalized_name$() {\n"
326 " $on_changed$;\n"
327 " if ($name$_ == null) {\n"
328 " $name$_ = com.google.protobuf.MapField.newMapField(\n"
329 " $map_field_parameter$);\n"
330 " }\n"
331 " if (!$name$_.isMutable()) {\n"
332 " $name$_ = $name$_.copy();\n"
333 " }\n"
334 " return $name$_;\n"
335 "}\n");
336 GenerateMapGetters(printer);
337 printer->Print(
338 variables_,
339 "$deprecation$\n"
340 "public Builder clear$capitalized_name$() {\n"
341 " getMutable$capitalized_name$().clear();\n"
342 " return this;\n"
343 "}\n");
344 WriteFieldDocComment(printer, descriptor_);
345 printer->Print(
346 variables_,
347 "$deprecation$\n"
348 "public Builder remove$capitalized_name$(\n"
349 " $key_type$ key) {\n"
350 " $key_null_check$\n"
351 " getMutable$capitalized_name$().remove(key);\n"
352 " return this;\n"
353 "}\n");
354 if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
355 printer->Print(
356 variables_,
357 "/**\n"
358 " * Use alternate mutation accessors instead.\n"
359 " */\n"
360 "@java.lang.Deprecated\n"
361 "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
362 "getMutable$capitalized_name$() {\n"
363 " return new com.google.protobuf.Internal.MapAdapter<\n"
364 " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
365 " internalGetMutable$capitalized_name$().getMutableMap(),\n"
366 " $name$ValueConverter);\n"
367 "}\n");
368 WriteFieldDocComment(printer, descriptor_);
369 printer->Print(
370 variables_,
371 "$deprecation$public Builder put$capitalized_name$(\n"
372 " $key_type$ key,\n"
373 " $value_enum_type$ value) {\n"
374 " $key_null_check$\n"
375 " $value_null_check$\n"
376 " getMutable$capitalized_name$().put(key, value);\n"
377 " return this;\n"
378 "}\n");
379 WriteFieldDocComment(printer, descriptor_);
380 printer->Print(
381 variables_,
382 // TODO(arielb): null check map keys/values here and everywhere else
383 // related to putAll
384 "$deprecation$public Builder putAll$capitalized_name$(\n"
385 " java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
386 " getMutable$capitalized_name$().putAll(values);\n"
387 " return this;\n"
388 "}\n");
389 if (SupportUnknownEnumValue(descriptor_->file())) {
390 printer->Print(
391 variables_,
392 "/**\n"
393 " * Use alternate mutation accessors instead.\n"
394 " */\n"
395 "@java.lang.Deprecated\n"
396 "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
397 "getMutable$capitalized_name$Value() {\n"
398 " return internalGetMutable$capitalized_name$().getMutableMap();\n"
399 "}\n");
400 WriteFieldDocComment(printer, descriptor_);
401 printer->Print(
402 variables_,
403 "$deprecation$public Builder put$capitalized_name$Value(\n"
404 " $key_type$ key,\n"
405 " $value_type$ value) {\n"
406 " $key_null_check$\n"
407 " if ($value_enum_type$.forNumber(value) == null) {\n"
408 " throw new java.lang.IllegalArgumentException();\n"
409 " }\n"
410 " getMutable$capitalized_name$Value().put(key, value);\n"
411 " return this;\n"
412 "}\n");
413 WriteFieldDocComment(printer, descriptor_);
414 printer->Print(
415 variables_,
416 "$deprecation$public Builder putAll$capitalized_name$Value(\n"
417 " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
418 " getMutable$capitalized_name$Value().putAll(values);\n"
419 " return this;\n"
420 "}\n");
421 }
422 } else {
423 printer->Print(
424 variables_,
425 "/**\n"
426 " * Use alternate mutation accessors instead.\n"
427 " */\n"
428 "@java.lang.Deprecated\n"
429 "public java.util.Map<$type_parameters$>\n"
430 "getMutable$capitalized_name$() {\n"
431 " return internalGetMutable$capitalized_name$().getMutableMap();\n"
432 "}\n");
433 WriteFieldDocComment(printer, descriptor_);
434 printer->Print(
435 variables_,
436 "$deprecation$"
437 "public Builder put$capitalized_name$(\n"
438 " $key_type$ key,\n"
439 " $value_type$ value) {\n"
440 " $key_null_check$\n"
441 " $value_null_check$\n"
442 " getMutable$capitalized_name$().put(key, value);\n"
443 " return this;\n"
444 "}\n");
445 WriteFieldDocComment(printer, descriptor_);
446 printer->Print(
447 variables_,
448 "$deprecation$\n"
449 "public Builder putAll$capitalized_name$(\n"
450 " java.util.Map<$type_parameters$> values) {\n"
451 " getMutable$capitalized_name$().putAll(values);\n"
452 " return this;\n"
453 "}\n");
454 }
455 }
456
457 void ImmutableMapFieldGenerator::
GenerateMapGetters(io::Printer * printer) const458 GenerateMapGetters(io::Printer* printer) const {
459 printer->Print(
460 variables_,
461 "$deprecation$\n"
462 "public int get$capitalized_name$Count() {\n"
463 " return internalGet$capitalized_name$().getMap().size();\n"
464 "}\n");
465 WriteFieldDocComment(printer, descriptor_);
466 printer->Print(
467 variables_,
468 "$deprecation$\n"
469 "public boolean contains$capitalized_name$(\n"
470 " $key_type$ key) {\n"
471 " $key_null_check$\n"
472 " return internalGet$capitalized_name$().getMap().containsKey(key);\n"
473 "}\n");
474 if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
475 printer->Print(
476 variables_,
477 "/**\n"
478 " * Use {@link #get$capitalized_name$Map()} instead.\n"
479 " */\n"
480 "@java.lang.Deprecated\n"
481 "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
482 "get$capitalized_name$() {\n"
483 " return get$capitalized_name$Map();\n"
484 "}\n");
485 WriteFieldDocComment(printer, descriptor_);
486 printer->Print(
487 variables_,
488 "$deprecation$\n"
489 "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
490 "get$capitalized_name$Map() {\n"
491 " return new com.google.protobuf.Internal.MapAdapter<\n"
492 " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
493 " internalGet$capitalized_name$().getMap(),\n"
494 " $name$ValueConverter);\n"
495 "}\n");
496 WriteFieldDocComment(printer, descriptor_);
497 printer->Print(
498 variables_,
499 "$deprecation$\n"
500 "public $value_enum_type$ get$capitalized_name$OrDefault(\n"
501 " $key_type$ key,\n"
502 " $value_enum_type$ defaultValue) {\n"
503 " $key_null_check$\n"
504 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
505 " internalGet$capitalized_name$().getMap();\n"
506 " return map.containsKey(key)\n"
507 " ? $name$ValueConverter.doForward(map.get(key))\n"
508 " : defaultValue;\n"
509 "}\n");
510 WriteFieldDocComment(printer, descriptor_);
511 printer->Print(
512 variables_,
513 "$deprecation$\n"
514 "public $value_enum_type$ get$capitalized_name$OrThrow(\n"
515 " $key_type$ key) {\n"
516 " $key_null_check$\n"
517 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
518 " internalGet$capitalized_name$().getMap();\n"
519 " if (!map.containsKey(key)) {\n"
520 " throw new java.lang.IllegalArgumentException();\n"
521 " }\n"
522 " return $name$ValueConverter.doForward(map.get(key));\n"
523 "}\n");
524 if (SupportUnknownEnumValue(descriptor_->file())) {
525 printer->Print(
526 variables_,
527 "/**\n"
528 " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
529 " */\n"
530 "@java.lang.Deprecated\n"
531 "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
532 "get$capitalized_name$Value() {\n"
533 " return get$capitalized_name$ValueMap();\n"
534 "}\n");
535 WriteFieldDocComment(printer, descriptor_);
536 printer->Print(
537 variables_,
538 "$deprecation$\n"
539 "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
540 "get$capitalized_name$ValueMap() {\n"
541 " return internalGet$capitalized_name$().getMap();\n"
542 "}\n");
543 WriteFieldDocComment(printer, descriptor_);
544 printer->Print(
545 variables_,
546 "$deprecation$\n"
547 "public $value_type$ get$capitalized_name$ValueOrDefault(\n"
548 " $key_type$ key,\n"
549 " $value_type$ 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) ? map.get(key) : defaultValue;\n"
554 "}\n");
555 WriteFieldDocComment(printer, descriptor_);
556 printer->Print(
557 variables_,
558 "$deprecation$\n"
559 "public $value_type$ get$capitalized_name$ValueOrThrow(\n"
560 " $key_type$ key) {\n"
561 " $key_null_check$\n"
562 " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
563 " internalGet$capitalized_name$().getMap();\n"
564 " if (!map.containsKey(key)) {\n"
565 " throw new java.lang.IllegalArgumentException();\n"
566 " }\n"
567 " return map.get(key);\n"
568 "}\n");
569 }
570 } else {
571 printer->Print(
572 variables_,
573 "/**\n"
574 " * Use {@link #get$capitalized_name$Map()} instead.\n"
575 " */\n"
576 "@java.lang.Deprecated\n"
577 "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
578 " return get$capitalized_name$Map();\n"
579 "}\n");
580 WriteFieldDocComment(printer, descriptor_);
581 printer->Print(
582 variables_,
583 "$deprecation$\n"
584 "public java.util.Map<$type_parameters$> get$capitalized_name$Map() {\n"
585 " return internalGet$capitalized_name$().getMap();\n"
586 "}\n");
587 WriteFieldDocComment(printer, descriptor_);
588 printer->Print(
589 variables_,
590 "$deprecation$\n"
591 "public $value_type$ get$capitalized_name$OrDefault(\n"
592 " $key_type$ key,\n"
593 " $value_type$ defaultValue) {\n"
594 " $key_null_check$\n"
595 " java.util.Map<$type_parameters$> map =\n"
596 " internalGet$capitalized_name$().getMap();\n"
597 " return map.containsKey(key) ? map.get(key) : defaultValue;\n"
598 "}\n");
599 WriteFieldDocComment(printer, descriptor_);
600 printer->Print(
601 variables_,
602 "$deprecation$\n"
603 "public $value_type$ get$capitalized_name$OrThrow(\n"
604 " $key_type$ key) {\n"
605 " $key_null_check$\n"
606 " java.util.Map<$type_parameters$> map =\n"
607 " internalGet$capitalized_name$().getMap();\n"
608 " if (!map.containsKey(key)) {\n"
609 " throw new java.lang.IllegalArgumentException();\n"
610 " }\n"
611 " return map.get(key);\n"
612 "}\n");
613 }
614 }
615
616 void ImmutableMapFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const617 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
618 // Nothing to initialize.
619 }
620
621 void ImmutableMapFieldGenerator::
GenerateInitializationCode(io::Printer * printer) const622 GenerateInitializationCode(io::Printer* printer) const {
623 // Nothing to initialize.
624 }
625
626 void ImmutableMapFieldGenerator::
GenerateBuilderClearCode(io::Printer * printer) const627 GenerateBuilderClearCode(io::Printer* printer) const {
628 printer->Print(
629 variables_,
630 "internalGetMutable$capitalized_name$().clear();\n");
631 }
632
633 void ImmutableMapFieldGenerator::
GenerateMergingCode(io::Printer * printer) const634 GenerateMergingCode(io::Printer* printer) const {
635 printer->Print(
636 variables_,
637 "internalGetMutable$capitalized_name$().mergeFrom(\n"
638 " other.internalGet$capitalized_name$());\n");
639 }
640
641 void ImmutableMapFieldGenerator::
GenerateBuildingCode(io::Printer * printer) const642 GenerateBuildingCode(io::Printer* printer) const {
643 printer->Print(
644 variables_,
645 "result.$name$_ = internalGet$capitalized_name$();\n"
646 "result.$name$_.makeImmutable();\n");
647 }
648
649 void ImmutableMapFieldGenerator::
GenerateParsingCode(io::Printer * printer) const650 GenerateParsingCode(io::Printer* printer) const {
651 printer->Print(
652 variables_,
653 "if (!$get_mutable_bit_parser$) {\n"
654 " $name$_ = com.google.protobuf.MapField.newMapField(\n"
655 " $map_field_parameter$);\n"
656 " $set_mutable_bit_parser$;\n"
657 "}\n");
658 if (!SupportUnknownEnumValue(descriptor_->file()) &&
659 GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
660 printer->Print(
661 variables_,
662 "com.google.protobuf.ByteString bytes = input.readBytes();\n"
663 "com.google.protobuf.MapEntry<$type_parameters$>\n"
664 "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
665 printer->Print(
666 variables_,
667 "if ($value_enum_type$.forNumber($name$.getValue()) == null) {\n"
668 " unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
669 "} else {\n"
670 " $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
671 "}\n");
672 } else {
673 printer->Print(
674 variables_,
675 "com.google.protobuf.MapEntry<$type_parameters$>\n"
676 "$name$ = input.readMessage(\n"
677 " $default_entry$.getParserForType(), extensionRegistry);\n"
678 "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
679 }
680 }
681
682 void ImmutableMapFieldGenerator::
GenerateParsingDoneCode(io::Printer * printer) const683 GenerateParsingDoneCode(io::Printer* printer) const {
684 // Nothing to do here.
685 }
686
687 void ImmutableMapFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const688 GenerateSerializationCode(io::Printer* printer) const {
689 printer->Print(
690 variables_,
691 "for (java.util.Map.Entry<$type_parameters$> entry\n"
692 " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
693 " com.google.protobuf.MapEntry<$type_parameters$>\n"
694 " $name$ = $default_entry$.newBuilderForType()\n"
695 " .setKey(entry.getKey())\n"
696 " .setValue(entry.getValue())\n"
697 " .build();\n"
698 " output.writeMessage($number$, $name$);\n"
699 "}\n");
700 }
701
702 void ImmutableMapFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const703 GenerateSerializedSizeCode(io::Printer* printer) const {
704 printer->Print(
705 variables_,
706 "for (java.util.Map.Entry<$type_parameters$> entry\n"
707 " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
708 " com.google.protobuf.MapEntry<$type_parameters$>\n"
709 " $name$ = $default_entry$.newBuilderForType()\n"
710 " .setKey(entry.getKey())\n"
711 " .setValue(entry.getValue())\n"
712 " .build();\n"
713 " size += com.google.protobuf.CodedOutputStream\n"
714 " .computeMessageSize($number$, $name$);\n"
715 "}\n");
716 }
717
718 void ImmutableMapFieldGenerator::
GenerateEqualsCode(io::Printer * printer) const719 GenerateEqualsCode(io::Printer* printer) const {
720 printer->Print(
721 variables_,
722 "result = result && internalGet$capitalized_name$().equals(\n"
723 " other.internalGet$capitalized_name$());\n");
724 }
725
726 void ImmutableMapFieldGenerator::
GenerateHashCode(io::Printer * printer) const727 GenerateHashCode(io::Printer* printer) const {
728 printer->Print(
729 variables_,
730 "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
731 " hash = (37 * hash) + $constant_name$;\n"
732 " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
733 "}\n");
734 }
735
GetBoxedType() const736 string ImmutableMapFieldGenerator::GetBoxedType() const {
737 return name_resolver_->GetImmutableClassName(descriptor_->message_type());
738 }
739
740 } // namespace java
741 } // namespace compiler
742 } // namespace protobuf
743 } // namespace google
744