• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   (*variables)["key_type"] = TypeName(key, name_resolver, false);
92   (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
93   (*variables)["key_wire_type"] = WireType(key);
94   (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
95   if (GetJavaType(value) == JAVATYPE_ENUM) {
96     // We store enums as Integers internally.
97     (*variables)["value_type"] = "int";
98     (*variables)["boxed_value_type"] = "java.lang.Integer";
99     (*variables)["value_wire_type"] = WireType(value);
100     (*variables)["value_default_value"] =
101         DefaultValue(value, true, name_resolver) + ".getNumber()";
102 
103     (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
104 
105     if (SupportUnknownEnumValue(descriptor->file())) {
106       // Map unknown values to a special UNRECOGNIZED value if supported.
107       (*variables)["unrecognized_value"] =
108           (*variables)["value_enum_type"] + ".UNRECOGNIZED";
109     } else {
110       // Map unknown values to the default value if we don't have UNRECOGNIZED.
111       (*variables)["unrecognized_value"] =
112           DefaultValue(value, true, name_resolver);
113     }
114   } else {
115     (*variables)["value_type"] = TypeName(value, name_resolver, false);
116     (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
117     (*variables)["value_wire_type"] = WireType(value);
118     (*variables)["value_default_value"] =
119         DefaultValue(value, true, name_resolver);
120   }
121   (*variables)["type_parameters"] =
122       (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
123   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
124   // by the proto compiler
125   (*variables)["deprecation"] = descriptor->options().deprecated()
126       ? "@java.lang.Deprecated " : "";
127 
128   (*variables)["default_entry"] = (*variables)["capitalized_name"] +
129       "DefaultEntryHolder.defaultEntry";
130   (*variables)["lite"] = "Lite";
131   (*variables)["descriptor"] = "";
132 }
133 
134 }  // namespace
135 
136 ImmutableMapFieldLiteGenerator::
ImmutableMapFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)137 ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor,
138                                        int messageBitIndex,
139                                        int builderBitIndex,
140                                        Context* context)
141   : descriptor_(descriptor), name_resolver_(context->GetNameResolver())  {
142   SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
143                       context->GetFieldGeneratorInfo(descriptor),
144                       context, &variables_);
145 }
146 
147 ImmutableMapFieldLiteGenerator::
~ImmutableMapFieldLiteGenerator()148 ~ImmutableMapFieldLiteGenerator() {}
149 
GetNumBitsForMessage() const150 int ImmutableMapFieldLiteGenerator::GetNumBitsForMessage() const {
151   return 0;
152 }
153 
GetNumBitsForBuilder() const154 int ImmutableMapFieldLiteGenerator::GetNumBitsForBuilder() const {
155   return 0;
156 }
157 
158 void ImmutableMapFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer * printer) const159 GenerateInterfaceMembers(io::Printer* printer) const {
160   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
161     WriteFieldDocComment(printer, descriptor_);
162     printer->Print(
163         variables_,
164         "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
165         "get$capitalized_name$();\n");
166     if (SupportUnknownEnumValue(descriptor_->file())) {
167       WriteFieldDocComment(printer, descriptor_);
168       printer->Print(
169           variables_,
170           "$deprecation$java.util.Map<$type_parameters$>\n"
171           "get$capitalized_name$Value();\n");
172     }
173   } else {
174     WriteFieldDocComment(printer, descriptor_);
175     printer->Print(
176         variables_,
177         "$deprecation$java.util.Map<$type_parameters$>\n"
178         "get$capitalized_name$();\n");
179   }
180 }
181 
182 void ImmutableMapFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const183 GenerateMembers(io::Printer* printer) const {
184   printer->Print(
185       variables_,
186       "private static final class $capitalized_name$DefaultEntryHolder {\n"
187       "  static final com.google.protobuf.MapEntry$lite$<\n"
188       "      $type_parameters$> defaultEntry =\n"
189       "          com.google.protobuf.MapEntry$lite$\n"
190       "          .<$type_parameters$>newDefaultInstance(\n"
191       "              $descriptor$\n"
192       "              $key_wire_type$,\n"
193       "              $key_default_value$,\n"
194       "              $value_wire_type$,\n"
195       "              $value_default_value$);\n"
196       "}\n");
197   printer->Print(
198       variables_,
199       "private com.google.protobuf.MapField$lite$<\n"
200       "    $type_parameters$> $name$_ =\n"
201       "        com.google.protobuf.MapField$lite$.emptyMapField();\n"
202       "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
203       "internalGet$capitalized_name$() {\n"
204       "  return $name$_;\n"
205       "}\n"
206       "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
207       "internalGetMutable$capitalized_name$() {\n"
208       "  if (!$name$_.isMutable()) {\n"
209       "    $name$_ = $name$_.copy();\n"
210       "  }\n"
211       "  return $name$_;\n"
212       "}\n");
213   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
214     printer->Print(
215         variables_,
216         "private static final\n"
217         "com.google.protobuf.Internal.MapAdapter.Converter<\n"
218         "    java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
219         "        com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
220         "            $value_enum_type$.internalGetValueMap(),\n"
221         "            $unrecognized_value$);\n");
222     if (SupportUnknownEnumValue(descriptor_->file())) {
223       WriteFieldDocComment(printer, descriptor_);
224       printer->Print(
225           variables_,
226           "$deprecation$\n"
227           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
228           "get$capitalized_name$Value() {\n"
229           "  return internalGet$capitalized_name$().getMap();\n"
230           "}\n");
231     }
232     WriteFieldDocComment(printer, descriptor_);
233     printer->Print(
234         variables_,
235         "$deprecation$\n"
236         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
237         "get$capitalized_name$() {\n"
238         "  return new com.google.protobuf.Internal.MapAdapter<\n"
239         "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
240         "          internalGet$capitalized_name$().getMap(),\n"
241         "          $name$ValueConverter);\n"
242         "}\n");
243   } else {
244     WriteFieldDocComment(printer, descriptor_);
245     printer->Print(
246         variables_,
247         "$deprecation$\n"
248         "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
249         "  return internalGet$capitalized_name$().getMap();\n"
250         "}\n");
251   }
252 
253   // Generate private setters for the builder to proxy into.
254   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
255     WriteFieldDocComment(printer, descriptor_);
256     printer->Print(
257         variables_,
258         "private java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
259         "getMutable$capitalized_name$() {\n"
260         "  return new com.google.protobuf.Internal.MapAdapter<\n"
261         "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
262         "          internalGetMutable$capitalized_name$().getMutableMap(),\n"
263         "          $name$ValueConverter);\n"
264         "}\n");
265     if (SupportUnknownEnumValue(descriptor_->file())) {
266       WriteFieldDocComment(printer, descriptor_);
267       printer->Print(
268           variables_,
269           "private java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
270           "getMutable$capitalized_name$Value() {\n"
271           "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
272           "}\n");
273     }
274   } else {
275     WriteFieldDocComment(printer, descriptor_);
276     printer->Print(
277         variables_,
278         "private java.util.Map<$type_parameters$>\n"
279         "getMutable$capitalized_name$() {\n"
280         "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
281         "}\n");
282   }
283 }
284 
285 void ImmutableMapFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const286 GenerateBuilderMembers(io::Printer* printer) const {
287   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
288     WriteFieldDocComment(printer, descriptor_);
289     printer->Print(
290         variables_,
291         "$deprecation$\n"
292         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
293         "get$capitalized_name$() {\n"
294         "  return instance.get$capitalized_name$();\n"
295         "}\n");
296     WriteFieldDocComment(printer, descriptor_);
297     printer->Print(
298         variables_,
299         "$deprecation$\n"
300         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
301         "getMutable$capitalized_name$() {\n"
302         "  copyOnWrite();\n"
303         "  return instance.getMutable$capitalized_name$();\n"
304         "}\n");
305     WriteFieldDocComment(printer, descriptor_);
306     printer->Print(
307         variables_,
308         "$deprecation$public Builder putAll$capitalized_name$(\n"
309         "    java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
310         "  getMutable$capitalized_name$().putAll(values);\n"
311         "  return this;\n"
312         "}\n");
313     if (SupportUnknownEnumValue(descriptor_->file())) {
314       WriteFieldDocComment(printer, descriptor_);
315       printer->Print(
316           variables_,
317           "$deprecation$\n"
318           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
319           "get$capitalized_name$Value() {\n"
320           "  return instance.get$capitalized_name$Value();\n"
321           "}\n");
322       WriteFieldDocComment(printer, descriptor_);
323       printer->Print(
324           variables_,
325           "$deprecation$\n"
326           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
327           "getMutable$capitalized_name$Value() {\n"
328           "  copyOnWrite();\n"
329           "  return instance.getMutable$capitalized_name$Value();\n"
330           "}\n");
331       WriteFieldDocComment(printer, descriptor_);
332       printer->Print(
333           variables_,
334           "$deprecation$public Builder putAll$capitalized_name$Value(\n"
335           "    java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
336           "  getMutable$capitalized_name$Value().putAll(values);\n"
337           "  return this;\n"
338           "}\n");
339     }
340   } else {
341     WriteFieldDocComment(printer, descriptor_);
342     printer->Print(
343         variables_,
344         "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
345         "  return instance.get$capitalized_name$();\n"
346         "}\n");
347     WriteFieldDocComment(printer, descriptor_);
348     printer->Print(
349         variables_,
350         "public java.util.Map<$type_parameters$>\n"
351         "getMutable$capitalized_name$() {\n"
352         "  copyOnWrite();\n"
353         "  return instance.getMutable$capitalized_name$();\n"
354         "}\n");
355     WriteFieldDocComment(printer, descriptor_);
356     printer->Print(
357         variables_,
358         "public Builder putAll$capitalized_name$(\n"
359         "    java.util.Map<$type_parameters$> values) {\n"
360         "  getMutable$capitalized_name$().putAll(values);\n"
361         "  return this;\n"
362         "}\n");
363   }
364 }
365 
366 void ImmutableMapFieldLiteGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const367 GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
368   // Nothing to initialize.
369 }
370 
371 void ImmutableMapFieldLiteGenerator::
GenerateInitializationCode(io::Printer * printer) const372 GenerateInitializationCode(io::Printer* printer) const {
373   // Nothing to initialize.
374 }
375 
376 void ImmutableMapFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const377 GenerateVisitCode(io::Printer* printer) const {
378   printer->Print(
379       variables_,
380       "$name$_ = visitor.visitMap(internalGetMutable$capitalized_name$(),\n"
381       "    other.internalGet$capitalized_name$());\n");
382 }
383 
384 void ImmutableMapFieldLiteGenerator::
GenerateDynamicMethodMakeImmutableCode(io::Printer * printer) const385 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
386   printer->Print(variables_,
387     "$name$_.makeImmutable();\n");
388 }
389 
390 void ImmutableMapFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const391 GenerateParsingCode(io::Printer* printer) const {
392   printer->Print(
393       variables_,
394       "if (!$name$_.isMutable()) {\n"
395       "  $name$_ = $name$_.copy();\n"
396       "}\n");
397   if (!SupportUnknownEnumValue(descriptor_->file()) &&
398       GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
399     printer->Print(
400         variables_,
401         "com.google.protobuf.ByteString bytes = input.readBytes();\n"
402         "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
403         "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
404     printer->Print(
405         variables_,
406         "if ($value_enum_type$.forNumber($name$.getValue()) == null) {\n"
407         "  super.mergeLengthDelimitedField($number$, bytes);\n"
408         "} else {\n"
409         "  $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
410         "}\n");
411   } else {
412     printer->Print(
413         variables_,
414         "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
415         "$name$ = input.readMessage(\n"
416         "    $default_entry$.getParserForType(), extensionRegistry);\n"
417         "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
418   }
419 }
420 
421 void ImmutableMapFieldLiteGenerator::
GenerateParsingDoneCode(io::Printer * printer) const422 GenerateParsingDoneCode(io::Printer* printer) const {
423   // Nothing to do here.
424 }
425 
426 void ImmutableMapFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const427 GenerateSerializationCode(io::Printer* printer) const {
428   printer->Print(
429       variables_,
430       "for (java.util.Map.Entry<$type_parameters$> entry\n"
431       "     : internalGet$capitalized_name$().getMap().entrySet()) {\n"
432       "  com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
433       "  $name$ = $default_entry$.newBuilderForType()\n"
434       "      .setKey(entry.getKey())\n"
435       "      .setValue(entry.getValue())\n"
436       "      .build();\n"
437       "  output.writeMessage($number$, $name$);\n"
438       "}\n");
439 }
440 
441 void ImmutableMapFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const442 GenerateSerializedSizeCode(io::Printer* printer) const {
443   printer->Print(
444       variables_,
445       "for (java.util.Map.Entry<$type_parameters$> entry\n"
446       "     : internalGet$capitalized_name$().getMap().entrySet()) {\n"
447       "  com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
448       "  $name$ = $default_entry$.newBuilderForType()\n"
449       "      .setKey(entry.getKey())\n"
450       "      .setValue(entry.getValue())\n"
451       "      .build();\n"
452       "  size += com.google.protobuf.CodedOutputStream\n"
453       "      .computeMessageSize($number$, $name$);\n"
454       "}\n");
455 }
456 
457 void ImmutableMapFieldLiteGenerator::
GenerateEqualsCode(io::Printer * printer) const458 GenerateEqualsCode(io::Printer* printer) const {
459   printer->Print(
460       variables_,
461       "result = result && internalGet$capitalized_name$().equals(\n"
462       "    other.internalGet$capitalized_name$());\n");
463 }
464 
465 void ImmutableMapFieldLiteGenerator::
GenerateHashCode(io::Printer * printer) const466 GenerateHashCode(io::Printer* printer) const {
467   printer->Print(
468       variables_,
469       "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
470       "  hash = (37 * hash) + $constant_name$;\n"
471       "  hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
472       "}\n");
473 }
474 
GetBoxedType() const475 string ImmutableMapFieldLiteGenerator::GetBoxedType() const {
476   return name_resolver_->GetImmutableClassName(descriptor_->message_type());
477 }
478 
479 }  // namespace java
480 }  // namespace compiler
481 }  // namespace protobuf
482 }  // namespace google
483