Line data Source code
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 :
46 0 : const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
47 0 : GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
48 0 : const Descriptor* message = descriptor->message_type();
49 0 : GOOGLE_CHECK(message->options().map_entry());
50 0 : return message->FindFieldByName("key");
51 : }
52 :
53 0 : const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
54 0 : GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
55 0 : const Descriptor* message = descriptor->message_type();
56 0 : GOOGLE_CHECK(message->options().map_entry());
57 0 : return message->FindFieldByName("value");
58 : }
59 :
60 0 : string TypeName(const FieldDescriptor* field,
61 : ClassNameResolver* name_resolver,
62 : bool boxed) {
63 0 : if (GetJavaType(field) == JAVATYPE_MESSAGE) {
64 0 : return name_resolver->GetImmutableClassName(field->message_type());
65 0 : } else if (GetJavaType(field) == JAVATYPE_ENUM) {
66 0 : return name_resolver->GetImmutableClassName(field->enum_type());
67 : } else {
68 0 : return boxed ? BoxedPrimitiveTypeName(GetJavaType(field))
69 0 : : PrimitiveTypeName(GetJavaType(field));
70 : }
71 : }
72 :
73 0 : string WireType(const FieldDescriptor* field) {
74 : return "com.google.protobuf.WireFormat.FieldType." +
75 0 : string(FieldTypeName(field->type()));
76 : }
77 :
78 0 : void SetMessageVariables(const FieldDescriptor* descriptor,
79 : int messageBitIndex,
80 : int builderBitIndex,
81 : const FieldGeneratorInfo* info,
82 : ClassNameResolver* name_resolver,
83 : map<string, string>* variables) {
84 0 : SetCommonFieldVariables(descriptor, info, variables);
85 :
86 0 : (*variables)["type"] =
87 : name_resolver->GetImmutableClassName(descriptor->message_type());
88 0 : const FieldDescriptor* key = KeyField(descriptor);
89 0 : const FieldDescriptor* value = ValueField(descriptor);
90 0 : (*variables)["key_type"] = TypeName(key, name_resolver, false);
91 0 : (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
92 0 : (*variables)["key_wire_type"] = WireType(key);
93 0 : (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
94 0 : if (GetJavaType(value) == JAVATYPE_ENUM) {
95 : // We store enums as Integers internally.
96 0 : (*variables)["value_type"] = "int";
97 0 : (*variables)["boxed_value_type"] = "java.lang.Integer";
98 0 : (*variables)["value_wire_type"] = WireType(value);
99 0 : (*variables)["value_default_value"] =
100 0 : DefaultValue(value, true, name_resolver) + ".getNumber()";
101 :
102 0 : (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
103 :
104 0 : if (SupportUnknownEnumValue(descriptor->file())) {
105 : // Map unknown values to a special UNRECOGNIZED value if supported.
106 0 : (*variables)["unrecognized_value"] =
107 0 : (*variables)["value_enum_type"] + ".UNRECOGNIZED";
108 : } else {
109 : // Map unknown values to the default value if we don't have UNRECOGNIZED.
110 0 : (*variables)["unrecognized_value"] =
111 : DefaultValue(value, true, name_resolver);
112 : }
113 : } else {
114 0 : (*variables)["value_type"] = TypeName(value, name_resolver, false);
115 0 : (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
116 0 : (*variables)["value_wire_type"] = WireType(value);
117 0 : (*variables)["value_default_value"] =
118 : DefaultValue(value, true, name_resolver);
119 : }
120 0 : (*variables)["type_parameters"] =
121 0 : (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
122 : // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
123 : // by the proto compiler
124 0 : (*variables)["deprecation"] = descriptor->options().deprecated()
125 : ? "@java.lang.Deprecated " : "";
126 0 : (*variables)["on_changed"] =
127 0 : HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
128 :
129 : // For repeated fields, one bit is used for whether the array is immutable
130 : // in the parsing constructor.
131 0 : (*variables)["get_mutable_bit_parser"] =
132 : GenerateGetBitMutableLocal(builderBitIndex);
133 0 : (*variables)["set_mutable_bit_parser"] =
134 : GenerateSetBitMutableLocal(builderBitIndex);
135 :
136 0 : (*variables)["default_entry"] = (*variables)["capitalized_name"] +
137 : "DefaultEntryHolder.defaultEntry";
138 0 : if (HasDescriptorMethods(descriptor->file())) {
139 0 : (*variables)["lite"] = "";
140 0 : (*variables)["map_field_parameter"] = (*variables)["default_entry"];
141 0 : (*variables)["descriptor"] =
142 0 : name_resolver->GetImmutableClassName(descriptor->file()) +
143 0 : ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
144 : "_descriptor, ";
145 : } else {
146 0 : (*variables)["lite"] = "Lite";
147 0 : (*variables)["map_field_parameter"] = "";
148 0 : (*variables)["descriptor"] = "";
149 : }
150 0 : }
151 :
152 : } // namespace
153 :
154 0 : ImmutableMapFieldGenerator::
155 : ImmutableMapFieldGenerator(const FieldDescriptor* descriptor,
156 : int messageBitIndex,
157 : int builderBitIndex,
158 : Context* context)
159 0 : : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
160 : SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
161 : context->GetFieldGeneratorInfo(descriptor),
162 0 : name_resolver_, &variables_);
163 0 : }
164 :
165 0 : ImmutableMapFieldGenerator::
166 0 : ~ImmutableMapFieldGenerator() {}
167 :
168 0 : int ImmutableMapFieldGenerator::GetNumBitsForMessage() const {
169 0 : return 0;
170 : }
171 :
172 0 : int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const {
173 0 : return 1;
174 : }
175 :
176 0 : void ImmutableMapFieldGenerator::
177 : GenerateInterfaceMembers(io::Printer* printer) const {
178 0 : if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
179 0 : WriteFieldDocComment(printer, descriptor_);
180 : printer->Print(
181 : variables_,
182 : "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
183 0 : "get$capitalized_name$();\n");
184 0 : if (SupportUnknownEnumValue(descriptor_->file())) {
185 0 : WriteFieldDocComment(printer, descriptor_);
186 : printer->Print(
187 : variables_,
188 : "$deprecation$java.util.Map<$type_parameters$>\n"
189 0 : "get$capitalized_name$Value();\n");
190 : }
191 : } else {
192 0 : WriteFieldDocComment(printer, descriptor_);
193 : printer->Print(
194 : variables_,
195 : "$deprecation$java.util.Map<$type_parameters$>\n"
196 0 : "get$capitalized_name$();\n");
197 : }
198 0 : }
199 :
200 0 : void ImmutableMapFieldGenerator::
201 : GenerateMembers(io::Printer* printer) const {
202 : printer->Print(
203 : variables_,
204 : "private static final class $capitalized_name$DefaultEntryHolder {\n"
205 : " static final com.google.protobuf.MapEntry$lite$<\n"
206 : " $type_parameters$> defaultEntry =\n"
207 : " com.google.protobuf.MapEntry$lite$\n"
208 : " .<$type_parameters$>newDefaultInstance(\n"
209 : " $descriptor$\n"
210 : " $key_wire_type$,\n"
211 : " $key_default_value$,\n"
212 : " $value_wire_type$,\n"
213 : " $value_default_value$);\n"
214 0 : "}\n");
215 : printer->Print(
216 : variables_,
217 : "private com.google.protobuf.MapField$lite$<\n"
218 : " $type_parameters$> $name$_;\n"
219 : "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
220 : "internalGet$capitalized_name$() {\n"
221 : " if ($name$_ == null) {\n"
222 : " return com.google.protobuf.MapField$lite$.emptyMapField(\n"
223 : " $map_field_parameter$);\n"
224 : " }\n"
225 : " return $name$_;\n"
226 0 : "}\n");
227 0 : if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
228 : printer->Print(
229 : variables_,
230 : "private static final\n"
231 : "com.google.protobuf.Internal.MapAdapter.Converter<\n"
232 : " java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
233 : " com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
234 : " $value_enum_type$.internalGetValueMap(),\n"
235 0 : " $unrecognized_value$);\n");
236 0 : if (SupportUnknownEnumValue(descriptor_->file())) {
237 0 : WriteFieldDocComment(printer, descriptor_);
238 : printer->Print(
239 : variables_,
240 : "$deprecation$\n"
241 : "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
242 : "get$capitalized_name$Value() {\n"
243 : " return internalGet$capitalized_name$().getMap();\n"
244 0 : "}\n");
245 : }
246 0 : WriteFieldDocComment(printer, descriptor_);
247 : printer->Print(
248 : variables_,
249 : "$deprecation$\n"
250 : "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
251 : "get$capitalized_name$() {\n"
252 : " return new com.google.protobuf.Internal.MapAdapter<\n"
253 : " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
254 : " internalGet$capitalized_name$().getMap(),\n"
255 : " $name$ValueConverter);\n"
256 0 : "}\n");
257 : } else {
258 0 : WriteFieldDocComment(printer, descriptor_);
259 : printer->Print(
260 : variables_,
261 : "$deprecation$\n"
262 : "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
263 : " return internalGet$capitalized_name$().getMap();\n"
264 0 : "}\n");
265 : }
266 0 : }
267 :
268 0 : void ImmutableMapFieldGenerator::
269 : GenerateBuilderMembers(io::Printer* printer) const {
270 : printer->Print(
271 : variables_,
272 : "private com.google.protobuf.MapField$lite$<\n"
273 : " $type_parameters$> $name$_;\n"
274 : "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
275 : "internalGet$capitalized_name$() {\n"
276 : " if ($name$_ == null) {\n"
277 : " return com.google.protobuf.MapField$lite$.emptyMapField(\n"
278 : " $map_field_parameter$);\n"
279 : " }\n"
280 : " return $name$_;\n"
281 : "}\n"
282 : "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
283 : "internalGetMutable$capitalized_name$() {\n"
284 : " $on_changed$;\n"
285 : " if ($name$_ == null) {\n"
286 : " $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n"
287 : " $map_field_parameter$);\n"
288 : " }\n"
289 : " if (!$name$_.isMutable()) {\n"
290 : " $name$_ = $name$_.copy();\n"
291 : " }\n"
292 : " return $name$_;\n"
293 0 : "}\n");
294 0 : if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
295 0 : WriteFieldDocComment(printer, descriptor_);
296 : printer->Print(
297 : variables_,
298 : "$deprecation$\n"
299 : "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
300 : "get$capitalized_name$() {\n"
301 : " return new com.google.protobuf.Internal.MapAdapter<\n"
302 : " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
303 : " internalGet$capitalized_name$().getMap(),\n"
304 : " $name$ValueConverter);\n"
305 0 : "}\n");
306 0 : WriteFieldDocComment(printer, descriptor_);
307 : printer->Print(
308 : variables_,
309 : "$deprecation$\n"
310 : "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
311 : "getMutable$capitalized_name$() {\n"
312 : " return new com.google.protobuf.Internal.MapAdapter<\n"
313 : " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
314 : " internalGetMutable$capitalized_name$().getMutableMap(),\n"
315 : " $name$ValueConverter);\n"
316 0 : "}\n");
317 0 : WriteFieldDocComment(printer, descriptor_);
318 : printer->Print(
319 : variables_,
320 : "$deprecation$public Builder putAll$capitalized_name$(\n"
321 : " java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
322 : " getMutable$capitalized_name$().putAll(values);\n"
323 : " return this;\n"
324 0 : "}\n");
325 0 : if (SupportUnknownEnumValue(descriptor_->file())) {
326 0 : WriteFieldDocComment(printer, descriptor_);
327 : printer->Print(
328 : variables_,
329 : "$deprecation$\n"
330 : "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
331 : "get$capitalized_name$Value() {\n"
332 : " return internalGet$capitalized_name$().getMap();\n"
333 0 : "}\n");
334 0 : WriteFieldDocComment(printer, descriptor_);
335 : printer->Print(
336 : variables_,
337 : "$deprecation$\n"
338 : "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
339 : "getMutable$capitalized_name$Value() {\n"
340 : " return internalGetMutable$capitalized_name$().getMutableMap();\n"
341 0 : "}\n");
342 0 : WriteFieldDocComment(printer, descriptor_);
343 : printer->Print(
344 : variables_,
345 : "$deprecation$public Builder putAll$capitalized_name$Value(\n"
346 : " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
347 : " getMutable$capitalized_name$Value().putAll(values);\n"
348 : " return this;\n"
349 0 : "}\n");
350 : }
351 : } else {
352 0 : WriteFieldDocComment(printer, descriptor_);
353 : printer->Print(
354 : variables_,
355 : "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
356 : " return internalGet$capitalized_name$().getMap();\n"
357 0 : "}\n");
358 0 : WriteFieldDocComment(printer, descriptor_);
359 : printer->Print(
360 : variables_,
361 : "public java.util.Map<$type_parameters$>\n"
362 : "getMutable$capitalized_name$() {\n"
363 : " return internalGetMutable$capitalized_name$().getMutableMap();\n"
364 0 : "}\n");
365 0 : WriteFieldDocComment(printer, descriptor_);
366 : printer->Print(
367 : variables_,
368 : "$deprecation$public Builder putAll$capitalized_name$(\n"
369 : " java.util.Map<$type_parameters$> values) {\n"
370 : " getMutable$capitalized_name$().putAll(values);\n"
371 : " return this;\n"
372 0 : "}\n");
373 : }
374 0 : }
375 :
376 0 : void ImmutableMapFieldGenerator::
377 : GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
378 : // Nothing to initialize.
379 0 : }
380 :
381 0 : void ImmutableMapFieldGenerator::
382 : GenerateInitializationCode(io::Printer* printer) const {
383 : // Nothing to initialize.
384 0 : }
385 :
386 0 : void ImmutableMapFieldGenerator::
387 : GenerateBuilderClearCode(io::Printer* printer) const {
388 : printer->Print(
389 : variables_,
390 0 : "internalGetMutable$capitalized_name$().clear();\n");
391 0 : }
392 :
393 0 : void ImmutableMapFieldGenerator::
394 : GenerateMergingCode(io::Printer* printer) const {
395 : printer->Print(
396 : variables_,
397 : "internalGetMutable$capitalized_name$().mergeFrom(\n"
398 0 : " other.internalGet$capitalized_name$());\n");
399 0 : }
400 :
401 0 : void ImmutableMapFieldGenerator::
402 : GenerateBuildingCode(io::Printer* printer) const {
403 : printer->Print(
404 : variables_,
405 : "result.$name$_ = internalGet$capitalized_name$();\n"
406 0 : "result.$name$_.makeImmutable();\n");
407 0 : }
408 :
409 0 : void ImmutableMapFieldGenerator::
410 : GenerateParsingCode(io::Printer* printer) const {
411 : printer->Print(
412 : variables_,
413 : "if (!$get_mutable_bit_parser$) {\n"
414 : " $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n"
415 : " $map_field_parameter$);\n"
416 : " $set_mutable_bit_parser$;\n"
417 0 : "}\n");
418 0 : if (!SupportUnknownEnumValue(descriptor_->file()) &&
419 0 : GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
420 : printer->Print(
421 : variables_,
422 : "com.google.protobuf.ByteString bytes = input.readBytes();\n"
423 : "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
424 0 : "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
425 : printer->Print(
426 : variables_,
427 : "if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
428 : " unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
429 : "} else {\n"
430 : " $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
431 0 : "}\n");
432 : } else {
433 : printer->Print(
434 : variables_,
435 : "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
436 : "$name$ = input.readMessage(\n"
437 : " $default_entry$.getParserForType(), extensionRegistry);\n"
438 0 : "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
439 : }
440 0 : }
441 :
442 0 : void ImmutableMapFieldGenerator::
443 : GenerateParsingDoneCode(io::Printer* printer) const {
444 : // Nothing to do here.
445 0 : }
446 :
447 0 : void ImmutableMapFieldGenerator::
448 : GenerateSerializationCode(io::Printer* printer) const {
449 : printer->Print(
450 : variables_,
451 : "for (java.util.Map.Entry<$type_parameters$> entry\n"
452 : " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
453 : " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
454 : " $name$ = $default_entry$.newBuilderForType()\n"
455 : " .setKey(entry.getKey())\n"
456 : " .setValue(entry.getValue())\n"
457 : " .build();\n"
458 : " output.writeMessage($number$, $name$);\n"
459 0 : "}\n");
460 0 : }
461 :
462 0 : void ImmutableMapFieldGenerator::
463 : GenerateSerializedSizeCode(io::Printer* printer) const {
464 : printer->Print(
465 : variables_,
466 : "for (java.util.Map.Entry<$type_parameters$> entry\n"
467 : " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
468 : " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
469 : " $name$ = $default_entry$.newBuilderForType()\n"
470 : " .setKey(entry.getKey())\n"
471 : " .setValue(entry.getValue())\n"
472 : " .build();\n"
473 : " size += com.google.protobuf.CodedOutputStream\n"
474 : " .computeMessageSize($number$, $name$);\n"
475 0 : "}\n");
476 0 : }
477 :
478 0 : void ImmutableMapFieldGenerator::
479 : GenerateEqualsCode(io::Printer* printer) const {
480 : printer->Print(
481 : variables_,
482 : "result = result && internalGet$capitalized_name$().equals(\n"
483 0 : " other.internalGet$capitalized_name$());\n");
484 0 : }
485 :
486 0 : void ImmutableMapFieldGenerator::
487 : GenerateHashCode(io::Printer* printer) const {
488 : printer->Print(
489 : variables_,
490 : "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
491 : " hash = (37 * hash) + $constant_name$;\n"
492 : " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
493 0 : "}\n");
494 0 : }
495 :
496 0 : string ImmutableMapFieldGenerator::GetBoxedType() const {
497 0 : return name_resolver_->GetImmutableClassName(descriptor_->message_type());
498 : }
499 :
500 : } // namespace java
501 : } // namespace compiler
502 : } // namespace protobuf
503 : } // namespace google
|