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