Line data Source code
1 : // Protocol Buffers - Google's data interchange format
2 : // Copyright 2008 Google Inc. All rights reserved.
3 : // http://code.google.com/p/protobuf/
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 : // Author: kenton@google.com (Kenton Varda)
32 : // Based on original Protocol Buffers design by
33 : // Sanjay Ghemawat, Jeff Dean, and others.
34 :
35 : #include <algorithm>
36 : #include <google/protobuf/stubs/hash.h>
37 : #include <google/protobuf/compiler/javanano/javanano_message.h>
38 : #include <google/protobuf/compiler/javanano/javanano_enum.h>
39 : #include <google/protobuf/compiler/javanano/javanano_extension.h>
40 : #include <google/protobuf/compiler/javanano/javanano_helpers.h>
41 : #include <google/protobuf/stubs/strutil.h>
42 : #include <google/protobuf/io/printer.h>
43 : #include <google/protobuf/io/coded_stream.h>
44 : #include <google/protobuf/wire_format.h>
45 : #include <google/protobuf/descriptor.pb.h>
46 :
47 : namespace google {
48 : namespace protobuf {
49 : namespace compiler {
50 : namespace javanano {
51 :
52 : using internal::WireFormat;
53 : using internal::WireFormatLite;
54 :
55 : namespace {
56 :
57 : struct FieldOrderingByNumber {
58 0 : inline bool operator()(const FieldDescriptor* a,
59 0 : const FieldDescriptor* b) const {
60 0 : return a->number() < b->number();
61 : }
62 : };
63 :
64 : // Sort the fields of the given Descriptor by number into a new[]'d array
65 : // and return it.
66 0 : const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
67 : const FieldDescriptor** fields =
68 0 : new const FieldDescriptor*[descriptor->field_count()];
69 0 : for (int i = 0; i < descriptor->field_count(); i++) {
70 0 : fields[i] = descriptor->field(i);
71 : }
72 0 : sort(fields, fields + descriptor->field_count(),
73 0 : FieldOrderingByNumber());
74 0 : return fields;
75 : }
76 :
77 : } // namespace
78 :
79 : // ===================================================================
80 :
81 0 : MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
82 : : params_(params),
83 : descriptor_(descriptor),
84 0 : field_generators_(descriptor, params) {
85 0 : }
86 :
87 0 : MessageGenerator::~MessageGenerator() {}
88 :
89 0 : void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
90 : // Generate static members for all nested types.
91 0 : for (int i = 0; i < descriptor_->nested_type_count(); i++) {
92 : // TODO(kenton): Reuse MessageGenerator objects?
93 0 : if (IsMapEntry(descriptor_->nested_type(i))) continue;
94 : MessageGenerator(descriptor_->nested_type(i), params_)
95 0 : .GenerateStaticVariables(printer);
96 : }
97 0 : }
98 :
99 0 : void MessageGenerator::GenerateStaticVariableInitializers(
100 : io::Printer* printer) {
101 : // Generate static member initializers for all nested types.
102 0 : for (int i = 0; i < descriptor_->nested_type_count(); i++) {
103 : // TODO(kenton): Reuse MessageGenerator objects?
104 0 : if (IsMapEntry(descriptor_->nested_type(i))) continue;
105 : MessageGenerator(descriptor_->nested_type(i), params_)
106 0 : .GenerateStaticVariableInitializers(printer);
107 : }
108 0 : }
109 :
110 0 : void MessageGenerator::Generate(io::Printer* printer) {
111 0 : if (!params_.store_unknown_fields() &&
112 0 : (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
113 0 : GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the "
114 0 : "'store_unknown_fields' generator option is 'true'\n";
115 : }
116 :
117 0 : const string& file_name = descriptor_->file()->name();
118 : bool is_own_file =
119 0 : params_.java_multiple_files(file_name)
120 0 : && descriptor_->containing_type() == NULL;
121 :
122 0 : if (is_own_file) {
123 : // Note: constants (from enums and fields requiring stored defaults, emitted in the loop below)
124 : // may have the same names as constants in the nested classes. This causes Java warnings, but
125 : // is not fatal, so we suppress those warnings here in the top-most class declaration.
126 : printer->Print(
127 : "\n"
128 : "@SuppressWarnings(\"hiding\")\n"
129 : "public final class $classname$ extends\n",
130 0 : "classname", descriptor_->name());
131 : } else {
132 : printer->Print(
133 : "\n"
134 : "public static final class $classname$ extends\n",
135 0 : "classname", descriptor_->name());
136 : }
137 0 : if (params_.store_unknown_fields() && params_.parcelable_messages()) {
138 : printer->Print(
139 : " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>",
140 0 : "classname", descriptor_->name());
141 0 : } else if (params_.store_unknown_fields()) {
142 : printer->Print(
143 : " com.google.protobuf.nano.ExtendableMessageNano<$classname$>",
144 0 : "classname", descriptor_->name());
145 0 : } else if (params_.parcelable_messages()) {
146 : printer->Print(
147 0 : " com.google.protobuf.nano.android.ParcelableMessageNano");
148 : } else {
149 : printer->Print(
150 0 : " com.google.protobuf.nano.MessageNano");
151 : }
152 0 : if (params_.generate_clone()) {
153 0 : printer->Print(" implements java.lang.Cloneable {\n");
154 : } else {
155 0 : printer->Print(" {\n");
156 : }
157 0 : printer->Indent();
158 :
159 0 : if (params_.parcelable_messages()) {
160 : printer->Print(
161 : "\n"
162 : "// Used by Parcelable\n"
163 : "@SuppressWarnings({\"unused\"})\n"
164 : "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n"
165 : " new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n"
166 : " $classname$>($classname$.class);\n",
167 0 : "classname", descriptor_->name());
168 : }
169 :
170 : // Nested types and extensions
171 0 : for (int i = 0; i < descriptor_->extension_count(); i++) {
172 0 : ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
173 : }
174 :
175 0 : for (int i = 0; i < descriptor_->enum_type_count(); i++) {
176 0 : EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
177 : }
178 :
179 0 : for (int i = 0; i < descriptor_->nested_type_count(); i++) {
180 0 : if (IsMapEntry(descriptor_->nested_type(i))) continue;
181 0 : MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
182 : }
183 :
184 : // oneof
185 : map<string, string> vars;
186 0 : vars["message_name"] = descriptor_->name();
187 0 : for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
188 0 : const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
189 0 : vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc);
190 0 : vars["oneof_capitalized_name"] =
191 : UnderscoresToCapitalizedCamelCase(oneof_desc);
192 0 : vars["oneof_index"] = SimpleItoa(oneof_desc->index());
193 : // Oneof Constants
194 0 : for (int j = 0; j < oneof_desc->field_count(); j++) {
195 0 : const FieldDescriptor* field = oneof_desc->field(j);
196 0 : vars["number"] = SimpleItoa(field->number());
197 0 : vars["cap_field_name"] = ToUpper(field->name());
198 : printer->Print(vars,
199 0 : "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n");
200 : }
201 : // oneofCase_ and oneof_
202 : printer->Print(vars,
203 : "private int $oneof_name$Case_ = 0;\n"
204 0 : "private java.lang.Object $oneof_name$_;\n");
205 : printer->Print(vars,
206 : "public int get$oneof_capitalized_name$Case() {\n"
207 : " return this.$oneof_name$Case_;\n"
208 0 : "}\n");
209 : // Oneof clear
210 : printer->Print(vars,
211 : "public $message_name$ clear$oneof_capitalized_name$() {\n"
212 : " this.$oneof_name$Case_ = 0;\n"
213 : " this.$oneof_name$_ = null;\n"
214 : " return this;\n"
215 0 : "}\n");
216 : }
217 :
218 : // Lazy initialization of otherwise static final fields can help prevent the
219 : // class initializer from being generated. We want to prevent it because it
220 : // stops ProGuard from inlining any methods in this class into call sites and
221 : // therefore reducing the method count. However, extensions are best kept as
222 : // public static final fields with initializers, so with their existence we
223 : // won't bother with lazy initialization.
224 0 : bool lazy_init = descriptor_->extension_count() == 0;
225 :
226 : // Empty array
227 0 : if (lazy_init) {
228 : printer->Print(
229 : "\n"
230 : "private static volatile $classname$[] _emptyArray;\n"
231 : "public static $classname$[] emptyArray() {\n"
232 : " // Lazily initializes the empty array\n"
233 : " if (_emptyArray == null) {\n"
234 : " synchronized (\n"
235 : " com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
236 : " if (_emptyArray == null) {\n"
237 : " _emptyArray = new $classname$[0];\n"
238 : " }\n"
239 : " }\n"
240 : " }\n"
241 : " return _emptyArray;\n"
242 : "}\n",
243 0 : "classname", descriptor_->name());
244 : } else {
245 : printer->Print(
246 : "\n"
247 : "private static final $classname$[] EMPTY_ARRAY = {};\n"
248 : "public static $classname$[] emptyArray() {\n"
249 : " return EMPTY_ARRAY;\n"
250 : "}\n",
251 0 : "classname", descriptor_->name());
252 : }
253 :
254 : // Integers for bit fields
255 0 : int totalInts = (field_generators_.total_bits() + 31) / 32;
256 0 : if (totalInts > 0) {
257 0 : printer->Print("\n");
258 0 : for (int i = 0; i < totalInts; i++) {
259 : printer->Print("private int $bit_field_name$;\n",
260 0 : "bit_field_name", GetBitFieldName(i));
261 : }
262 : }
263 :
264 : // Fields and maybe their default values
265 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
266 0 : printer->Print("\n");
267 0 : PrintFieldComment(printer, descriptor_->field(i));
268 0 : field_generators_.get(descriptor_->field(i)).GenerateMembers(
269 0 : printer, lazy_init);
270 : }
271 :
272 : // Constructor, with lazy init code if needed
273 0 : if (lazy_init && field_generators_.saved_defaults_needed()) {
274 : printer->Print(
275 : "\n"
276 : "private static volatile boolean _classInitialized;\n"
277 : "\n"
278 : "public $classname$() {\n"
279 : " // Lazily initializes the field defaults\n"
280 : " if (!_classInitialized) {\n"
281 : " synchronized (\n"
282 : " com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
283 : " if (!_classInitialized) {\n",
284 0 : "classname", descriptor_->name());
285 0 : printer->Indent();
286 0 : printer->Indent();
287 0 : printer->Indent();
288 0 : printer->Indent();
289 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
290 0 : field_generators_.get(descriptor_->field(i))
291 0 : .GenerateInitSavedDefaultCode(printer);
292 : }
293 0 : printer->Outdent();
294 0 : printer->Outdent();
295 0 : printer->Outdent();
296 0 : printer->Outdent();
297 : printer->Print(
298 : " _classInitialized = true;\n"
299 : " }\n"
300 : " }\n"
301 0 : " }\n");
302 0 : if (params_.generate_clear()) {
303 0 : printer->Print(" clear();\n");
304 : }
305 0 : printer->Print("}\n");
306 : } else {
307 : printer->Print(
308 : "\n"
309 : "public $classname$() {\n",
310 0 : "classname", descriptor_->name());
311 0 : if (params_.generate_clear()) {
312 0 : printer->Print(" clear();\n");
313 : } else {
314 0 : printer->Indent();
315 0 : GenerateFieldInitializers(printer);
316 0 : printer->Outdent();
317 : }
318 0 : printer->Print("}\n");
319 : }
320 :
321 : // Other methods in this class
322 :
323 0 : GenerateClear(printer);
324 :
325 0 : if (params_.generate_clone()) {
326 0 : GenerateClone(printer);
327 : }
328 :
329 0 : if (params_.generate_equals()) {
330 0 : GenerateEquals(printer);
331 0 : GenerateHashCode(printer);
332 : }
333 :
334 0 : GenerateMessageSerializationMethods(printer);
335 0 : GenerateMergeFromMethods(printer);
336 0 : GenerateParseFromMethods(printer);
337 :
338 0 : printer->Outdent();
339 0 : printer->Print("}\n");
340 0 : }
341 :
342 : // ===================================================================
343 :
344 0 : void MessageGenerator::
345 : GenerateMessageSerializationMethods(io::Printer* printer) {
346 : // Rely on the parent implementations of writeTo() and getSerializedSize()
347 : // if there are no fields to serialize in this message.
348 0 : if (descriptor_->field_count() == 0) {
349 0 : return;
350 : }
351 :
352 : scoped_array<const FieldDescriptor*> sorted_fields(
353 0 : SortFieldsByNumber(descriptor_));
354 :
355 : printer->Print(
356 : "\n"
357 : "@Override\n"
358 : "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n"
359 0 : " throws java.io.IOException {\n");
360 0 : printer->Indent();
361 :
362 : // Output the fields in sorted order
363 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
364 0 : GenerateSerializeOneField(printer, sorted_fields[i]);
365 : }
366 :
367 : // The parent implementation will write any unknown fields if necessary.
368 : printer->Print(
369 0 : "super.writeTo(output);\n");
370 :
371 0 : printer->Outdent();
372 0 : printer->Print("}\n");
373 :
374 : // The parent implementation will get the serialized size for unknown
375 : // fields if necessary.
376 : printer->Print(
377 : "\n"
378 : "@Override\n"
379 : "protected int computeSerializedSize() {\n"
380 0 : " int size = super.computeSerializedSize();\n");
381 0 : printer->Indent();
382 :
383 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
384 0 : field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
385 : }
386 :
387 0 : printer->Outdent();
388 : printer->Print(
389 : " return size;\n"
390 0 : "}\n");
391 : }
392 :
393 0 : void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
394 : scoped_array<const FieldDescriptor*> sorted_fields(
395 0 : SortFieldsByNumber(descriptor_));
396 :
397 : printer->Print(
398 : "\n"
399 : "@Override\n"
400 : "public $classname$ mergeFrom(\n"
401 : " com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
402 : " throws java.io.IOException {\n",
403 0 : "classname", descriptor_->name());
404 :
405 0 : printer->Indent();
406 0 : if (HasMapField(descriptor_)) {
407 : printer->Print(
408 : "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n"
409 0 : " com.google.protobuf.nano.MapFactories.getMapFactory();\n");
410 : }
411 :
412 : printer->Print(
413 0 : "while (true) {\n");
414 0 : printer->Indent();
415 :
416 : printer->Print(
417 : "int tag = input.readTag();\n"
418 0 : "switch (tag) {\n");
419 0 : printer->Indent();
420 :
421 : printer->Print(
422 : "case 0:\n" // zero signals EOF / limit reached
423 : " return this;\n"
424 0 : "default: {\n");
425 :
426 0 : printer->Indent();
427 0 : if (params_.store_unknown_fields()) {
428 : printer->Print(
429 : "if (!storeUnknownField(input, tag)) {\n"
430 : " return this;\n"
431 0 : "}\n");
432 : } else {
433 : printer->Print(
434 : "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
435 : " return this;\n" // it's an endgroup tag
436 0 : "}\n");
437 : }
438 0 : printer->Print("break;\n");
439 0 : printer->Outdent();
440 0 : printer->Print("}\n");
441 :
442 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
443 0 : const FieldDescriptor* field = sorted_fields[i];
444 : uint32 tag = WireFormatLite::MakeTag(field->number(),
445 0 : WireFormat::WireTypeForFieldType(field->type()));
446 :
447 : printer->Print(
448 : "case $tag$: {\n",
449 0 : "tag", SimpleItoa(tag));
450 0 : printer->Indent();
451 :
452 0 : field_generators_.get(field).GenerateMergingCode(printer);
453 :
454 0 : printer->Outdent();
455 : printer->Print(
456 : " break;\n"
457 0 : "}\n");
458 :
459 0 : if (field->is_packable()) {
460 : // To make packed = true wire compatible, we generate parsing code from a
461 : // packed version of this field regardless of field->options().packed().
462 : uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
463 0 : WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
464 : printer->Print(
465 : "case $tag$: {\n",
466 0 : "tag", SimpleItoa(packed_tag));
467 0 : printer->Indent();
468 :
469 0 : field_generators_.get(field).GenerateMergingCodeFromPacked(printer);
470 :
471 0 : printer->Outdent();
472 : printer->Print(
473 : " break;\n"
474 0 : "}\n");
475 : }
476 : }
477 :
478 0 : printer->Outdent();
479 0 : printer->Outdent();
480 0 : printer->Outdent();
481 : printer->Print(
482 : " }\n" // switch (tag)
483 : " }\n" // while (true)
484 0 : "}\n");
485 0 : }
486 :
487 0 : void MessageGenerator::
488 : GenerateParseFromMethods(io::Printer* printer) {
489 : // Note: These are separate from GenerateMessageSerializationMethods()
490 : // because they need to be generated even for messages that are optimized
491 : // for code size.
492 : printer->Print(
493 : "\n"
494 : "public static $classname$ parseFrom(byte[] data)\n"
495 : " throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
496 : " return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
497 : "}\n"
498 : "\n"
499 : "public static $classname$ parseFrom(\n"
500 : " com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
501 : " throws java.io.IOException {\n"
502 : " return new $classname$().mergeFrom(input);\n"
503 : "}\n",
504 0 : "classname", descriptor_->name());
505 0 : }
506 :
507 0 : void MessageGenerator::GenerateSerializeOneField(
508 : io::Printer* printer, const FieldDescriptor* field) {
509 0 : field_generators_.get(field).GenerateSerializationCode(printer);
510 0 : }
511 :
512 0 : void MessageGenerator::GenerateClear(io::Printer* printer) {
513 0 : if (!params_.generate_clear()) {
514 0 : return;
515 : }
516 : printer->Print(
517 : "\n"
518 : "public $classname$ clear() {\n",
519 0 : "classname", descriptor_->name());
520 0 : printer->Indent();
521 :
522 0 : GenerateFieldInitializers(printer);
523 :
524 0 : printer->Outdent();
525 : printer->Print(
526 : " return this;\n"
527 0 : "}\n");
528 : }
529 :
530 0 : void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) {
531 : // Clear bit fields.
532 0 : int totalInts = (field_generators_.total_bits() + 31) / 32;
533 0 : for (int i = 0; i < totalInts; i++) {
534 : printer->Print("$bit_field_name$ = 0;\n",
535 0 : "bit_field_name", GetBitFieldName(i));
536 : }
537 :
538 : // Call clear for all of the fields.
539 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
540 0 : const FieldDescriptor* field = descriptor_->field(i);
541 0 : field_generators_.get(field).GenerateClearCode(printer);
542 : }
543 :
544 : // Clear oneofs.
545 0 : for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
546 : printer->Print(
547 : "clear$oneof_capitalized_name$();\n",
548 : "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase(
549 0 : descriptor_->oneof_decl(i)));
550 : }
551 :
552 : // Clear unknown fields.
553 0 : if (params_.store_unknown_fields()) {
554 0 : printer->Print("unknownFieldData = null;\n");
555 : }
556 0 : printer->Print("cachedSize = -1;\n");
557 0 : }
558 :
559 0 : void MessageGenerator::GenerateClone(io::Printer* printer) {
560 : printer->Print(
561 : "@Override\n"
562 : "public $classname$ clone() {\n",
563 0 : "classname", descriptor_->name());
564 0 : printer->Indent();
565 :
566 : printer->Print(
567 : "$classname$ cloned;\n"
568 : "try {\n"
569 : " cloned = ($classname$) super.clone();\n"
570 : "} catch (java.lang.CloneNotSupportedException e) {\n"
571 : " throw new java.lang.AssertionError(e);\n"
572 : "}\n",
573 0 : "classname", descriptor_->name());
574 :
575 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
576 0 : field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer);
577 : }
578 :
579 0 : printer->Outdent();
580 : printer->Print(
581 : " return cloned;\n"
582 : "}\n"
583 0 : "\n");
584 0 : }
585 :
586 0 : void MessageGenerator::GenerateEquals(io::Printer* printer) {
587 : // Don't override if there are no fields. We could generate an
588 : // equals method that compares types, but often empty messages
589 : // are used as namespaces.
590 0 : if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
591 0 : return;
592 : }
593 :
594 : printer->Print(
595 : "\n"
596 : "@Override\n"
597 0 : "public boolean equals(Object o) {\n");
598 0 : printer->Indent();
599 : printer->Print(
600 : "if (o == this) {\n"
601 : " return true;\n"
602 : "}\n"
603 : "if (!(o instanceof $classname$)) {\n"
604 : " return false;\n"
605 : "}\n"
606 : "$classname$ other = ($classname$) o;\n",
607 0 : "classname", descriptor_->name());
608 :
609 : // Checking oneof case before checking each oneof field.
610 0 : for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
611 0 : const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
612 : printer->Print(
613 : "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n"
614 : " return false;\n"
615 : "}\n",
616 0 : "oneof_name", UnderscoresToCamelCase(oneof_desc));
617 : }
618 :
619 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
620 0 : const FieldDescriptor* field = descriptor_->field(i);
621 0 : field_generators_.get(field).GenerateEqualsCode(printer);
622 : }
623 :
624 0 : if (params_.store_unknown_fields()) {
625 : printer->Print(
626 : "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n"
627 : " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n"
628 : "} else {\n"
629 : " return unknownFieldData.equals(other.unknownFieldData);\n"
630 0 : "}");
631 : } else {
632 : printer->Print(
633 0 : "return true;\n");
634 : }
635 :
636 0 : printer->Outdent();
637 0 : printer->Print("}\n");
638 : }
639 :
640 0 : void MessageGenerator::GenerateHashCode(io::Printer* printer) {
641 0 : if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
642 0 : return;
643 : }
644 :
645 : printer->Print(
646 : "\n"
647 : "@Override\n"
648 0 : "public int hashCode() {\n");
649 0 : printer->Indent();
650 :
651 0 : printer->Print("int result = 17;\n");
652 0 : printer->Print("result = 31 * result + getClass().getName().hashCode();\n");
653 0 : for (int i = 0; i < descriptor_->field_count(); i++) {
654 0 : const FieldDescriptor* field = descriptor_->field(i);
655 0 : field_generators_.get(field).GenerateHashCodeCode(printer);
656 : }
657 :
658 0 : if (params_.store_unknown_fields()) {
659 : printer->Print(
660 : "result = 31 * result + \n"
661 : " (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n"
662 0 : " unknownFieldData.hashCode());\n");
663 : }
664 :
665 0 : printer->Print("return result;\n");
666 :
667 0 : printer->Outdent();
668 0 : printer->Print("}\n");
669 : }
670 :
671 : // ===================================================================
672 :
673 : } // namespace javanano
674 : } // namespace compiler
675 : } // namespace protobuf
676 : } // namespace google
|