blob: 47ee84cfdb0d8ee5b2a42d6aab1a75bc92e21545 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
temporal40ee5512008-07-10 02:12:20 +00003// http://code.google.com/p/protobuf/
4//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
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/java/java_message.h>
38#include <google/protobuf/compiler/java/java_enum.h>
39#include <google/protobuf/compiler/java/java_extension.h>
40#include <google/protobuf/compiler/java/java_helpers.h>
41#include <google/protobuf/stubs/strutil.h>
42#include <google/protobuf/io/printer.h>
43#include <google/protobuf/io/coded_stream.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000044#include <google/protobuf/wire_format.h>
temporal40ee5512008-07-10 02:12:20 +000045#include <google/protobuf/descriptor.pb.h>
46
47namespace google {
48namespace protobuf {
49namespace compiler {
50namespace java {
51
52using internal::WireFormat;
kenton@google.com80b1d622009-07-29 01:13:20 +000053using internal::WireFormatLite;
temporal40ee5512008-07-10 02:12:20 +000054
55namespace {
56
57void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
58 // Print the field's proto-syntax definition as a comment. We don't want to
59 // print group bodies so we cut off after the first line.
60 string def = field->DebugString();
61 printer->Print("// $def$\n",
62 "def", def.substr(0, def.find_first_of('\n')));
63}
64
65struct FieldOrderingByNumber {
66 inline bool operator()(const FieldDescriptor* a,
67 const FieldDescriptor* b) const {
68 return a->number() < b->number();
69 }
70};
71
72struct ExtensionRangeOrdering {
73 bool operator()(const Descriptor::ExtensionRange* a,
74 const Descriptor::ExtensionRange* b) const {
75 return a->start < b->start;
76 }
77};
78
79// Sort the fields of the given Descriptor by number into a new[]'d array
80// and return it.
81const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
82 const FieldDescriptor** fields =
83 new const FieldDescriptor*[descriptor->field_count()];
84 for (int i = 0; i < descriptor->field_count(); i++) {
85 fields[i] = descriptor->field(i);
86 }
87 sort(fields, fields + descriptor->field_count(),
88 FieldOrderingByNumber());
89 return fields;
90}
91
92// Get an identifier that uniquely identifies this type within the file.
93// This is used to declare static variables related to this type at the
94// outermost file scope.
95string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
96 return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
97}
98
99// Returns true if the message type has any required fields. If it doesn't,
100// we can optimize out calls to its isInitialized() method.
101//
102// already_seen is used to avoid checking the same type multiple times
103// (and also to protect against recursion).
104static bool HasRequiredFields(
105 const Descriptor* type,
106 hash_set<const Descriptor*>* already_seen) {
107 if (already_seen->count(type) > 0) {
108 // The type is already in cache. This means that either:
109 // a. The type has no required fields.
110 // b. We are in the midst of checking if the type has required fields,
111 // somewhere up the stack. In this case, we know that if the type
112 // has any required fields, they'll be found when we return to it,
113 // and the whole call to HasRequiredFields() will return true.
114 // Therefore, we don't have to check if this type has required fields
115 // here.
116 return false;
117 }
118 already_seen->insert(type);
119
120 // If the type has extensions, an extension with message type could contain
121 // required fields, so we have to be conservative and assume such an
122 // extension exists.
123 if (type->extension_range_count() > 0) return true;
124
125 for (int i = 0; i < type->field_count(); i++) {
126 const FieldDescriptor* field = type->field(i);
127 if (field->is_required()) {
128 return true;
129 }
kenton@google.comfccb1462009-12-18 02:11:36 +0000130 if (GetJavaType(field) == JAVATYPE_MESSAGE) {
temporal40ee5512008-07-10 02:12:20 +0000131 if (HasRequiredFields(field->message_type(), already_seen)) {
132 return true;
133 }
134 }
135 }
136
137 return false;
138}
139
140static bool HasRequiredFields(const Descriptor* type) {
141 hash_set<const Descriptor*> already_seen;
142 return HasRequiredFields(type, &already_seen);
143}
144
145} // namespace
146
147// ===================================================================
148
149MessageGenerator::MessageGenerator(const Descriptor* descriptor)
150 : descriptor_(descriptor),
151 field_generators_(descriptor) {
152}
153
154MessageGenerator::~MessageGenerator() {}
155
156void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000157 if (HasDescriptorMethods(descriptor_)) {
158 // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
159 // used in the construction of descriptors, we have a tricky bootstrapping
160 // problem. To help control static initialization order, we make sure all
161 // descriptors and other static data that depends on them are members of
162 // the outermost class in the file. This way, they will be initialized in
163 // a deterministic order.
temporal40ee5512008-07-10 02:12:20 +0000164
kenton@google.com80b1d622009-07-29 01:13:20 +0000165 map<string, string> vars;
166 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
167 vars["index"] = SimpleItoa(descriptor_->index());
168 vars["classname"] = ClassName(descriptor_);
169 if (descriptor_->containing_type() != NULL) {
170 vars["parent"] = UniqueFileScopeIdentifier(
171 descriptor_->containing_type());
172 }
173 if (descriptor_->file()->options().java_multiple_files()) {
174 // We can only make these package-private since the classes that use them
175 // are in separate files.
176 vars["private"] = "";
177 } else {
178 vars["private"] = "private ";
179 }
180
181 // The descriptor for this type.
182 printer->Print(vars,
183 "$private$static com.google.protobuf.Descriptors.Descriptor\n"
184 " internal_$identifier$_descriptor;\n");
185
186 // And the FieldAccessorTable.
187 printer->Print(vars,
188 "$private$static\n"
189 " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
190 " internal_$identifier$_fieldAccessorTable;\n");
temporal40ee5512008-07-10 02:12:20 +0000191 }
kenton@google.com24bf56f2008-09-24 20:31:01 +0000192
193 // Generate static members for all nested types.
194 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
195 // TODO(kenton): Reuse MessageGenerator objects?
196 MessageGenerator(descriptor_->nested_type(i))
197 .GenerateStaticVariables(printer);
198 }
199}
200
201void MessageGenerator::GenerateStaticVariableInitializers(
202 io::Printer* printer) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000203 if (HasDescriptorMethods(descriptor_)) {
204 map<string, string> vars;
205 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
206 vars["index"] = SimpleItoa(descriptor_->index());
207 vars["classname"] = ClassName(descriptor_);
208 if (descriptor_->containing_type() != NULL) {
209 vars["parent"] = UniqueFileScopeIdentifier(
210 descriptor_->containing_type());
211 }
kenton@google.com24bf56f2008-09-24 20:31:01 +0000212
kenton@google.com80b1d622009-07-29 01:13:20 +0000213 // The descriptor for this type.
214 if (descriptor_->containing_type() == NULL) {
215 printer->Print(vars,
216 "internal_$identifier$_descriptor =\n"
217 " getDescriptor().getMessageTypes().get($index$);\n");
218 } else {
219 printer->Print(vars,
220 "internal_$identifier$_descriptor =\n"
221 " internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
222 }
kenton@google.com24bf56f2008-09-24 20:31:01 +0000223
kenton@google.com80b1d622009-07-29 01:13:20 +0000224 // And the FieldAccessorTable.
225 printer->Print(vars,
226 "internal_$identifier$_fieldAccessorTable = new\n"
227 " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
228 " internal_$identifier$_descriptor,\n"
229 " new java.lang.String[] { ");
230 for (int i = 0; i < descriptor_->field_count(); i++) {
231 printer->Print(
232 "\"$field_name$\", ",
233 "field_name",
234 UnderscoresToCapitalizedCamelCase(descriptor_->field(i)));
235 }
236 printer->Print("},\n"
237 " $classname$.class,\n"
238 " $classname$.Builder.class);\n",
239 "classname", ClassName(descriptor_));
temporal40ee5512008-07-10 02:12:20 +0000240 }
temporal40ee5512008-07-10 02:12:20 +0000241
kenton@google.com24bf56f2008-09-24 20:31:01 +0000242 // Generate static member initializers for all nested types.
temporal40ee5512008-07-10 02:12:20 +0000243 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
244 // TODO(kenton): Reuse MessageGenerator objects?
245 MessageGenerator(descriptor_->nested_type(i))
kenton@google.com24bf56f2008-09-24 20:31:01 +0000246 .GenerateStaticVariableInitializers(printer);
247 }
temporal40ee5512008-07-10 02:12:20 +0000248}
249
liujisi@google.com33165fe2010-11-02 13:14:58 +0000250// ===================================================================
251
252void MessageGenerator::GenerateInterface(io::Printer* printer) {
253
254 if (descriptor_->extension_range_count() > 0) {
255 if (HasDescriptorMethods(descriptor_)) {
256 printer->Print(
257 "public interface $classname$OrBuilder extends\n"
258 " com.google.protobuf.GeneratedMessage.\n"
259 " ExtendableMessageOrBuilder<$classname$> {\n",
260 "classname", descriptor_->name());
261 } else {
262 printer->Print(
263 "public interface $classname$OrBuilder extends \n"
264 " com.google.protobuf.GeneratedMessageLite.\n"
265 " ExtendableMessageOrBuilder<$classname$> {\n",
266 "classname", descriptor_->name());
267 }
268 } else {
269 if (HasDescriptorMethods(descriptor_)) {
270 printer->Print(
271 "public interface $classname$OrBuilder\n"
272 " extends com.google.protobuf.MessageOrBuilder {\n",
273 "classname", descriptor_->name());
274 } else {
275 printer->Print(
276 "public interface $classname$OrBuilder\n"
277 " extends com.google.protobuf.MessageLiteOrBuilder {\n",
278 "classname", descriptor_->name());
279 }
280 }
281
282 printer->Indent();
283 for (int i = 0; i < descriptor_->field_count(); i++) {
284 printer->Print("\n");
285 PrintFieldComment(printer, descriptor_->field(i));
286 field_generators_.get(descriptor_->field(i))
287 .GenerateInterfaceMembers(printer);
288 }
289 printer->Outdent();
290
291 printer->Print("}\n");
292}
293
294// ===================================================================
295
temporal40ee5512008-07-10 02:12:20 +0000296void MessageGenerator::Generate(io::Printer* printer) {
297 bool is_own_file =
298 descriptor_->containing_type() == NULL &&
299 descriptor_->file()->options().java_multiple_files();
300
301 if (descriptor_->extension_range_count() > 0) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000302 if (HasDescriptorMethods(descriptor_)) {
303 printer->Print(
304 "public $static$ final class $classname$ extends\n"
305 " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000306 " $classname$> implements $classname$OrBuilder {\n",
kenton@google.com80b1d622009-07-29 01:13:20 +0000307 "static", is_own_file ? "" : "static",
308 "classname", descriptor_->name());
309 } else {
310 printer->Print(
311 "public $static$ final class $classname$ extends\n"
312 " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000313 " $classname$> implements $classname$OrBuilder {\n",
kenton@google.com80b1d622009-07-29 01:13:20 +0000314 "static", is_own_file ? "" : "static",
315 "classname", descriptor_->name());
316 }
temporal40ee5512008-07-10 02:12:20 +0000317 } else {
kenton@google.com80b1d622009-07-29 01:13:20 +0000318 if (HasDescriptorMethods(descriptor_)) {
319 printer->Print(
320 "public $static$ final class $classname$ extends\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000321 " com.google.protobuf.GeneratedMessage\n"
322 " implements $classname$OrBuilder {\n",
kenton@google.com80b1d622009-07-29 01:13:20 +0000323 "static", is_own_file ? "" : "static",
324 "classname", descriptor_->name());
325 } else {
326 printer->Print(
327 "public $static$ final class $classname$ extends\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000328 " com.google.protobuf.GeneratedMessageLite\n"
329 " implements $classname$OrBuilder {\n",
kenton@google.com80b1d622009-07-29 01:13:20 +0000330 "static", is_own_file ? "" : "static",
331 "classname", descriptor_->name());
332 }
temporal40ee5512008-07-10 02:12:20 +0000333 }
334 printer->Indent();
335 printer->Print(
336 "// Use $classname$.newBuilder() to construct.\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000337 "private $classname$(Builder builder) {\n"
338 " super(builder);\n"
kenton@google.comfccb1462009-12-18 02:11:36 +0000339 "}\n"
340 // Used when constructing the default instance, which cannot be initialized
341 // immediately because it may cyclically refer to other default instances.
342 "private $classname$(boolean noInit) {}\n"
temporal40ee5512008-07-10 02:12:20 +0000343 "\n"
kenton@google.comfccb1462009-12-18 02:11:36 +0000344 "private static final $classname$ defaultInstance;\n"
temporal40ee5512008-07-10 02:12:20 +0000345 "public static $classname$ getDefaultInstance() {\n"
346 " return defaultInstance;\n"
347 "}\n"
348 "\n"
349 "public $classname$ getDefaultInstanceForType() {\n"
350 " return defaultInstance;\n"
351 "}\n"
352 "\n",
353 "classname", descriptor_->name());
kenton@google.com80b1d622009-07-29 01:13:20 +0000354
liujisi@google.com33165fe2010-11-02 13:14:58 +0000355 GenerateDescriptorMethods(printer);
temporal40ee5512008-07-10 02:12:20 +0000356
liujisi@google.com33165fe2010-11-02 13:14:58 +0000357 // Nested types
temporal40ee5512008-07-10 02:12:20 +0000358 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
359 EnumGenerator(descriptor_->enum_type(i)).Generate(printer);
360 }
361
362 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000363 MessageGenerator messageGenerator(descriptor_->nested_type(i));
364 messageGenerator.GenerateInterface(printer);
365 messageGenerator.Generate(printer);
temporal40ee5512008-07-10 02:12:20 +0000366 }
367
liujisi@google.com33165fe2010-11-02 13:14:58 +0000368 // Integers for bit fields.
369 int totalBits = 0;
370 for (int i = 0; i < descriptor_->field_count(); i++) {
371 totalBits += field_generators_.get(descriptor_->field(i))
372 .GetNumBitsForMessage();
373 }
374 int totalInts = (totalBits + 31) / 32;
375 for (int i = 0; i < totalInts; i++) {
376 printer->Print("private int $bit_field_name$;\n",
377 "bit_field_name", GetBitFieldName(i));
temporal40ee5512008-07-10 02:12:20 +0000378 }
379
380 // Fields
381 for (int i = 0; i < descriptor_->field_count(); i++) {
382 PrintFieldComment(printer, descriptor_->field(i));
kenton@google.comcfa2d8a2009-04-18 00:02:12 +0000383 printer->Print("public static final int $constant_name$ = $number$;\n",
384 "constant_name", FieldConstantName(descriptor_->field(i)),
385 "number", SimpleItoa(descriptor_->field(i)->number()));
temporal40ee5512008-07-10 02:12:20 +0000386 field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
387 printer->Print("\n");
388 }
389
kenton@google.comfccb1462009-12-18 02:11:36 +0000390 // Called by the constructor, except in the case of the default instance,
391 // in which case this is called by static init code later on.
392 printer->Print("private void initFields() {\n");
393 printer->Indent();
394 for (int i = 0; i < descriptor_->field_count(); i++) {
395 field_generators_.get(descriptor_->field(i))
396 .GenerateInitializationCode(printer);
397 }
398 printer->Outdent();
399 printer->Print("}\n");
400
kenton@google.com80b1d622009-07-29 01:13:20 +0000401 if (HasGeneratedMethods(descriptor_)) {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000402 GenerateIsInitialized(printer, MEMOIZE);
temporal40ee5512008-07-10 02:12:20 +0000403 GenerateMessageSerializationMethods(printer);
404 }
405
liujisi@google.com33165fe2010-11-02 13:14:58 +0000406 if (HasEqualsAndHashCode(descriptor_)) {
407 GenerateEqualsAndHashCode(printer);
408 }
409
temporal40ee5512008-07-10 02:12:20 +0000410 GenerateParseFromMethods(printer);
411 GenerateBuilder(printer);
kenton@google.com24bf56f2008-09-24 20:31:01 +0000412
liujisi@google.com33165fe2010-11-02 13:14:58 +0000413 // Carefully initialize the default instance in such a way that it doesn't
414 // conflict with other initialization.
kenton@google.com24bf56f2008-09-24 20:31:01 +0000415 printer->Print(
416 "\n"
417 "static {\n"
kenton@google.comfccb1462009-12-18 02:11:36 +0000418 " defaultInstance = new $classname$(true);\n"
kenton@google.comfccb1462009-12-18 02:11:36 +0000419 " defaultInstance.initFields();\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000420 "}\n"
kenton@google.comfccb1462009-12-18 02:11:36 +0000421 "\n"
422 "// @@protoc_insertion_point(class_scope:$full_name$)\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000423 "classname", descriptor_->name(),
kenton@google.comfccb1462009-12-18 02:11:36 +0000424 "full_name", descriptor_->full_name());
kenton@google.com24bf56f2008-09-24 20:31:01 +0000425
liujisi@google.com33165fe2010-11-02 13:14:58 +0000426 // Extensions must be declared after the defaultInstance is initialized
427 // because the defaultInstance is used by the extension to lazily retrieve
428 // the outer class's FileDescriptor.
429 for (int i = 0; i < descriptor_->extension_count(); i++) {
430 ExtensionGenerator(descriptor_->extension(i)).Generate(printer);
431 }
432
kenton@google.com24bf56f2008-09-24 20:31:01 +0000433 printer->Outdent();
434 printer->Print("}\n\n");
temporal40ee5512008-07-10 02:12:20 +0000435}
436
liujisi@google.com33165fe2010-11-02 13:14:58 +0000437
temporal40ee5512008-07-10 02:12:20 +0000438// ===================================================================
439
440void MessageGenerator::
441GenerateMessageSerializationMethods(io::Printer* printer) {
442 scoped_array<const FieldDescriptor*> sorted_fields(
443 SortFieldsByNumber(descriptor_));
444
445 vector<const Descriptor::ExtensionRange*> sorted_extensions;
446 for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
447 sorted_extensions.push_back(descriptor_->extension_range(i));
448 }
449 sort(sorted_extensions.begin(), sorted_extensions.end(),
450 ExtensionRangeOrdering());
451
452 printer->Print(
453 "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
454 " throws java.io.IOException {\n");
455 printer->Indent();
jasonh+personal@google.com99512332009-12-01 18:05:21 +0000456 // writeTo(CodedOutputStream output) might be invoked without
457 // getSerializedSize() ever being called, but we need the memoized
458 // sizes in case this message has packed fields. Rather than emit checks for
459 // each packed field, just call getSerializedSize() up front for all messages.
460 // In most cases, getSerializedSize() will have already been called anyway by
461 // one of the wrapper writeTo() methods, making this call cheap.
462 printer->Print(
463 "getSerializedSize();\n");
temporal40ee5512008-07-10 02:12:20 +0000464
465 if (descriptor_->extension_range_count() > 0) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000466 if (descriptor_->options().message_set_wire_format()) {
467 printer->Print(
kenton@google.comab6950d2010-01-28 01:09:11 +0000468 "com.google.protobuf.GeneratedMessage$lite$\n"
469 " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000470 " newMessageSetExtensionWriter();\n",
kenton@google.comab6950d2010-01-28 01:09:11 +0000471 "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite",
472 "classname", ClassName(descriptor_));
kenton@google.com80b1d622009-07-29 01:13:20 +0000473 } else {
474 printer->Print(
kenton@google.comab6950d2010-01-28 01:09:11 +0000475 "com.google.protobuf.GeneratedMessage$lite$\n"
476 " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n"
477 " newExtensionWriter();\n",
478 "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite",
479 "classname", ClassName(descriptor_));
kenton@google.com80b1d622009-07-29 01:13:20 +0000480 }
temporal40ee5512008-07-10 02:12:20 +0000481 }
482
483 // Merge the fields and the extension ranges, both sorted by field number.
484 for (int i = 0, j = 0;
485 i < descriptor_->field_count() || j < sorted_extensions.size();
486 ) {
487 if (i == descriptor_->field_count()) {
488 GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
489 } else if (j == sorted_extensions.size()) {
490 GenerateSerializeOneField(printer, sorted_fields[i++]);
491 } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
492 GenerateSerializeOneField(printer, sorted_fields[i++]);
493 } else {
494 GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
495 }
496 }
497
kenton@google.com80b1d622009-07-29 01:13:20 +0000498 if (HasUnknownFields(descriptor_)) {
499 if (descriptor_->options().message_set_wire_format()) {
500 printer->Print(
501 "getUnknownFields().writeAsMessageSetTo(output);\n");
502 } else {
503 printer->Print(
504 "getUnknownFields().writeTo(output);\n");
505 }
temporal40ee5512008-07-10 02:12:20 +0000506 }
507
508 printer->Outdent();
509 printer->Print(
510 "}\n"
511 "\n"
512 "private int memoizedSerializedSize = -1;\n"
513 "public int getSerializedSize() {\n"
514 " int size = memoizedSerializedSize;\n"
515 " if (size != -1) return size;\n"
516 "\n"
517 " size = 0;\n");
518 printer->Indent();
519
520 for (int i = 0; i < descriptor_->field_count(); i++) {
521 field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
522 }
523
524 if (descriptor_->extension_range_count() > 0) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000525 if (descriptor_->options().message_set_wire_format()) {
526 printer->Print(
527 "size += extensionsSerializedSizeAsMessageSet();\n");
528 } else {
529 printer->Print(
530 "size += extensionsSerializedSize();\n");
531 }
temporal40ee5512008-07-10 02:12:20 +0000532 }
533
kenton@google.com80b1d622009-07-29 01:13:20 +0000534 if (HasUnknownFields(descriptor_)) {
535 if (descriptor_->options().message_set_wire_format()) {
536 printer->Print(
537 "size += getUnknownFields().getSerializedSizeAsMessageSet();\n");
538 } else {
539 printer->Print(
540 "size += getUnknownFields().getSerializedSize();\n");
541 }
temporal40ee5512008-07-10 02:12:20 +0000542 }
543
544 printer->Outdent();
545 printer->Print(
546 " memoizedSerializedSize = size;\n"
547 " return size;\n"
548 "}\n"
549 "\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000550
551 printer->Print(
552 "@java.lang.Override\n"
553 "protected Object writeReplace() throws java.io.ObjectStreamException {\n"
554 " return super.writeReplace();\n"
555 "}\n"
556 "\n");
temporal40ee5512008-07-10 02:12:20 +0000557}
558
559void MessageGenerator::
560GenerateParseFromMethods(io::Printer* printer) {
561 // Note: These are separate from GenerateMessageSerializationMethods()
562 // because they need to be generated even for messages that are optimized
563 // for code size.
564 printer->Print(
565 "public static $classname$ parseFrom(\n"
566 " com.google.protobuf.ByteString data)\n"
567 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
568 " return newBuilder().mergeFrom(data).buildParsed();\n"
569 "}\n"
570 "public static $classname$ parseFrom(\n"
571 " com.google.protobuf.ByteString data,\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000572 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
temporal40ee5512008-07-10 02:12:20 +0000573 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
574 " return newBuilder().mergeFrom(data, extensionRegistry)\n"
575 " .buildParsed();\n"
576 "}\n"
577 "public static $classname$ parseFrom(byte[] data)\n"
578 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
579 " return newBuilder().mergeFrom(data).buildParsed();\n"
580 "}\n"
581 "public static $classname$ parseFrom(\n"
582 " byte[] data,\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000583 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
temporal40ee5512008-07-10 02:12:20 +0000584 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
585 " return newBuilder().mergeFrom(data, extensionRegistry)\n"
586 " .buildParsed();\n"
587 "}\n"
588 "public static $classname$ parseFrom(java.io.InputStream input)\n"
589 " throws java.io.IOException {\n"
590 " return newBuilder().mergeFrom(input).buildParsed();\n"
591 "}\n"
592 "public static $classname$ parseFrom(\n"
593 " java.io.InputStream input,\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000594 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
temporal40ee5512008-07-10 02:12:20 +0000595 " throws java.io.IOException {\n"
596 " return newBuilder().mergeFrom(input, extensionRegistry)\n"
597 " .buildParsed();\n"
598 "}\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000599 "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
600 " throws java.io.IOException {\n"
kenton@google.comfccb1462009-12-18 02:11:36 +0000601 " Builder builder = newBuilder();\n"
602 " if (builder.mergeDelimitedFrom(input)) {\n"
603 " return builder.buildParsed();\n"
604 " } else {\n"
605 " return null;\n"
606 " }\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000607 "}\n"
608 "public static $classname$ parseDelimitedFrom(\n"
609 " java.io.InputStream input,\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000610 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000611 " throws java.io.IOException {\n"
kenton@google.comfccb1462009-12-18 02:11:36 +0000612 " Builder builder = newBuilder();\n"
613 " if (builder.mergeDelimitedFrom(input, extensionRegistry)) {\n"
614 " return builder.buildParsed();\n"
615 " } else {\n"
616 " return null;\n"
617 " }\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000618 "}\n"
temporal40ee5512008-07-10 02:12:20 +0000619 "public static $classname$ parseFrom(\n"
620 " com.google.protobuf.CodedInputStream input)\n"
621 " throws java.io.IOException {\n"
622 " return newBuilder().mergeFrom(input).buildParsed();\n"
623 "}\n"
624 "public static $classname$ parseFrom(\n"
625 " com.google.protobuf.CodedInputStream input,\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000626 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
temporal40ee5512008-07-10 02:12:20 +0000627 " throws java.io.IOException {\n"
628 " return newBuilder().mergeFrom(input, extensionRegistry)\n"
629 " .buildParsed();\n"
630 "}\n"
631 "\n",
632 "classname", ClassName(descriptor_));
633}
634
635void MessageGenerator::GenerateSerializeOneField(
636 io::Printer* printer, const FieldDescriptor* field) {
637 field_generators_.get(field).GenerateSerializationCode(printer);
638}
639
640void MessageGenerator::GenerateSerializeOneExtensionRange(
641 io::Printer* printer, const Descriptor::ExtensionRange* range) {
642 printer->Print(
643 "extensionWriter.writeUntil($end$, output);\n",
644 "end", SimpleItoa(range->end));
645}
646
647// ===================================================================
648
649void MessageGenerator::GenerateBuilder(io::Printer* printer) {
650 printer->Print(
kenton@google.com80b1d622009-07-29 01:13:20 +0000651 "public static Builder newBuilder() { return Builder.create(); }\n"
652 "public Builder newBuilderForType() { return newBuilder(); }\n"
temporal40ee5512008-07-10 02:12:20 +0000653 "public static Builder newBuilder($classname$ prototype) {\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000654 " return newBuilder().mergeFrom(prototype);\n"
temporal40ee5512008-07-10 02:12:20 +0000655 "}\n"
kenton@google.com2d6daa72009-01-22 01:27:00 +0000656 "public Builder toBuilder() { return newBuilder(this); }\n"
temporal40ee5512008-07-10 02:12:20 +0000657 "\n",
658 "classname", ClassName(descriptor_));
659
liujisi@google.com33165fe2010-11-02 13:14:58 +0000660 if (HasNestedBuilders(descriptor_)) {
661 printer->Print(
662 "@java.lang.Override\n"
663 "protected Builder newBuilderForType(\n"
664 " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
665 " Builder builder = new Builder(parent);\n"
666 " return builder;\n"
667 "}\n");
668 }
669
temporal40ee5512008-07-10 02:12:20 +0000670 if (descriptor_->extension_range_count() > 0) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000671 if (HasDescriptorMethods(descriptor_)) {
672 printer->Print(
673 "public static final class Builder extends\n"
674 " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000675 " $classname$, Builder> implements $classname$OrBuilder {\n",
kenton@google.com80b1d622009-07-29 01:13:20 +0000676 "classname", ClassName(descriptor_));
677 } else {
678 printer->Print(
679 "public static final class Builder extends\n"
680 " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000681 " $classname$, Builder> implements $classname$OrBuilder {\n",
kenton@google.com80b1d622009-07-29 01:13:20 +0000682 "classname", ClassName(descriptor_));
683 }
temporal40ee5512008-07-10 02:12:20 +0000684 } else {
kenton@google.com80b1d622009-07-29 01:13:20 +0000685 if (HasDescriptorMethods(descriptor_)) {
686 printer->Print(
687 "public static final class Builder extends\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000688 " com.google.protobuf.GeneratedMessage.Builder<Builder>\n"
689 " implements $classname$OrBuilder {\n",
kenton@google.com80b1d622009-07-29 01:13:20 +0000690 "classname", ClassName(descriptor_));
691 } else {
692 printer->Print(
693 "public static final class Builder extends\n"
694 " com.google.protobuf.GeneratedMessageLite.Builder<\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000695 " $classname$, Builder>\n"
696 " implements $classname$OrBuilder {\n",
kenton@google.com80b1d622009-07-29 01:13:20 +0000697 "classname", ClassName(descriptor_));
698 }
temporal40ee5512008-07-10 02:12:20 +0000699 }
700 printer->Indent();
701
liujisi@google.com33165fe2010-11-02 13:14:58 +0000702 GenerateDescriptorMethods(printer);
temporal40ee5512008-07-10 02:12:20 +0000703 GenerateCommonBuilderMethods(printer);
704
kenton@google.com80b1d622009-07-29 01:13:20 +0000705 if (HasGeneratedMethods(descriptor_)) {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000706 GenerateIsInitialized(printer, DONT_MEMOIZE);
temporal40ee5512008-07-10 02:12:20 +0000707 GenerateBuilderParsingMethods(printer);
708 }
709
liujisi@google.com33165fe2010-11-02 13:14:58 +0000710 // Integers for bit fields.
711 int totalBits = 0;
712 for (int i = 0; i < descriptor_->field_count(); i++) {
713 totalBits += field_generators_.get(descriptor_->field(i))
714 .GetNumBitsForBuilder();
715 }
716 int totalInts = (totalBits + 31) / 32;
717 for (int i = 0; i < totalInts; i++) {
718 printer->Print("private int $bit_field_name$;\n",
719 "bit_field_name", GetBitFieldName(i));
720 }
721
temporal40ee5512008-07-10 02:12:20 +0000722 for (int i = 0; i < descriptor_->field_count(); i++) {
723 printer->Print("\n");
724 PrintFieldComment(printer, descriptor_->field(i));
725 field_generators_.get(descriptor_->field(i))
726 .GenerateBuilderMembers(printer);
727 }
728
temporal8ee14742009-12-20 00:09:50 +0000729 printer->Print(
730 "\n"
731 "// @@protoc_insertion_point(builder_scope:$full_name$)\n",
732 "full_name", descriptor_->full_name());
733
temporal40ee5512008-07-10 02:12:20 +0000734 printer->Outdent();
735 printer->Print("}\n");
temporal40ee5512008-07-10 02:12:20 +0000736}
737
liujisi@google.com33165fe2010-11-02 13:14:58 +0000738void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) {
739 if (HasDescriptorMethods(descriptor_)) {
740 printer->Print(
741 "public static final com.google.protobuf.Descriptors.Descriptor\n"
742 " getDescriptor() {\n"
743 " return $fileclass$.internal_$identifier$_descriptor;\n"
744 "}\n"
745 "\n"
746 "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
747 " internalGetFieldAccessorTable() {\n"
748 " return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
749 "}\n"
750 "\n",
751 "fileclass", ClassName(descriptor_->file()),
752 "identifier", UniqueFileScopeIdentifier(descriptor_));
753 }
754}
755
temporal40ee5512008-07-10 02:12:20 +0000756// ===================================================================
757
758void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
759 printer->Print(
760 "// Construct using $classname$.newBuilder()\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000761 "private Builder() {\n"
762 " maybeForceBuilderInitialization();\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000763 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000764 "\n",
765 "classname", ClassName(descriptor_));
766
767 if (HasDescriptorMethods(descriptor_)) {
768 printer->Print(
769 "private Builder(BuilderParent parent) {\n"
770 " super(parent);\n"
771 " maybeForceBuilderInitialization();\n"
772 "}\n",
773 "classname", ClassName(descriptor_));
774 }
775
776
777 if (HasNestedBuilders(descriptor_)) {
778 printer->Print(
779 "private void maybeForceBuilderInitialization() {\n"
780 " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
781
782 printer->Indent();
783 printer->Indent();
784 for (int i = 0; i < descriptor_->field_count(); i++) {
785 field_generators_.get(descriptor_->field(i))
786 .GenerateFieldBuilderInitializationCode(printer);
787 }
788 printer->Outdent();
789 printer->Outdent();
790
791 printer->Print(
792 " }\n"
793 "}\n");
794 } else {
795 printer->Print(
796 "private void maybeForceBuilderInitialization() {\n"
797 "}\n");
798 }
799
800 printer->Print(
801 "private static Builder create() {\n"
802 " return new Builder();\n"
temporal40ee5512008-07-10 02:12:20 +0000803 "}\n"
804 "\n"
805 "public Builder clear() {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000806 " super.clear();\n",
807 "classname", ClassName(descriptor_));
808
809 printer->Indent();
810
811 for (int i = 0; i < descriptor_->field_count(); i++) {
812 field_generators_.get(descriptor_->field(i))
813 .GenerateBuilderClearCode(printer);
814 }
815
816 printer->Outdent();
817
818 printer->Print(
temporal40ee5512008-07-10 02:12:20 +0000819 " return this;\n"
820 "}\n"
821 "\n"
822 "public Builder clone() {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000823 " return create().mergeFrom(buildPartial());\n"
temporal40ee5512008-07-10 02:12:20 +0000824 "}\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000825 "\n",
826 "classname", ClassName(descriptor_));
827 if (HasDescriptorMethods(descriptor_)) {
828 printer->Print(
kenton@google.com80b1d622009-07-29 01:13:20 +0000829 "public com.google.protobuf.Descriptors.Descriptor\n"
830 " getDescriptorForType() {\n"
831 " return $classname$.getDescriptor();\n"
832 "}\n"
833 "\n",
834 "classname", ClassName(descriptor_));
835 }
836 printer->Print(
temporal40ee5512008-07-10 02:12:20 +0000837 "public $classname$ getDefaultInstanceForType() {\n"
838 " return $classname$.getDefaultInstance();\n"
839 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000840 "\n",
temporal40ee5512008-07-10 02:12:20 +0000841 "classname", ClassName(descriptor_));
842
843 // -----------------------------------------------------------------
844
845 printer->Print(
846 "public $classname$ build() {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000847 " $classname$ result = buildPartial();\n"
848 " if (!result.isInitialized()) {\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000849 " throw newUninitializedMessageException(result);\n"
temporal40ee5512008-07-10 02:12:20 +0000850 " }\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000851 " return result;\n"
temporal40ee5512008-07-10 02:12:20 +0000852 "}\n"
853 "\n"
854 "private $classname$ buildParsed()\n"
855 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000856 " $classname$ result = buildPartial();\n"
857 " if (!result.isInitialized()) {\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000858 " throw newUninitializedMessageException(\n"
temporal40ee5512008-07-10 02:12:20 +0000859 " result).asInvalidProtocolBufferException();\n"
860 " }\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000861 " return result;\n"
temporal40ee5512008-07-10 02:12:20 +0000862 "}\n"
863 "\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000864 "public $classname$ buildPartial() {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000865 " $classname$ result = new $classname$(this);\n",
temporal40ee5512008-07-10 02:12:20 +0000866 "classname", ClassName(descriptor_));
liujisi@google.com33165fe2010-11-02 13:14:58 +0000867
temporal40ee5512008-07-10 02:12:20 +0000868 printer->Indent();
869
liujisi@google.com33165fe2010-11-02 13:14:58 +0000870 // Local vars for from and to bit fields to avoid accessing the builder and
871 // message over and over for these fields. Seems to provide a slight
872 // perforamance improvement in micro benchmark and this is also what proto1
873 // code does.
874 int totalBuilderBits = 0;
875 int totalMessageBits = 0;
876 for (int i = 0; i < descriptor_->field_count(); i++) {
877 const FieldGenerator& field = field_generators_.get(descriptor_->field(i));
878 totalBuilderBits += field.GetNumBitsForBuilder();
879 totalMessageBits += field.GetNumBitsForMessage();
880 }
881 int totalBuilderInts = (totalBuilderBits + 31) / 32;
882 int totalMessageInts = (totalMessageBits + 31) / 32;
883 for (int i = 0; i < totalBuilderInts; i++) {
884 printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n",
885 "bit_field_name", GetBitFieldName(i));
886 }
887 for (int i = 0; i < totalMessageInts; i++) {
888 printer->Print("int to_$bit_field_name$ = 0;\n",
889 "bit_field_name", GetBitFieldName(i));
890 }
891
892 // Output generation code for each field.
temporal40ee5512008-07-10 02:12:20 +0000893 for (int i = 0; i < descriptor_->field_count(); i++) {
894 field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
895 }
896
liujisi@google.com33165fe2010-11-02 13:14:58 +0000897 // Copy the bit field results to the generated message
898 for (int i = 0; i < totalMessageInts; i++) {
899 printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n",
900 "bit_field_name", GetBitFieldName(i));
901 }
902
temporal40ee5512008-07-10 02:12:20 +0000903 printer->Outdent();
liujisi@google.com33165fe2010-11-02 13:14:58 +0000904
905 if (HasDescriptorMethods(descriptor_)) {
906 printer->Print(
907 " onBuilt();\n");
908 }
909
temporal40ee5512008-07-10 02:12:20 +0000910 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +0000911 " return result;\n"
temporal40ee5512008-07-10 02:12:20 +0000912 "}\n"
913 "\n",
914 "classname", ClassName(descriptor_));
915
916 // -----------------------------------------------------------------
917
kenton@google.com80b1d622009-07-29 01:13:20 +0000918 if (HasGeneratedMethods(descriptor_)) {
919 // MergeFrom(Message other) requires the ability to distinguish the other
920 // messages type by its descriptor.
921 if (HasDescriptorMethods(descriptor_)) {
922 printer->Print(
kenton@google.com80b1d622009-07-29 01:13:20 +0000923 "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
924 " if (other instanceof $classname$) {\n"
925 " return mergeFrom(($classname$)other);\n"
926 " } else {\n"
927 " super.mergeFrom(other);\n"
928 " return this;\n"
929 " }\n"
930 "}\n"
931 "\n",
932 "classname", ClassName(descriptor_));
933 }
934
temporal40ee5512008-07-10 02:12:20 +0000935 printer->Print(
temporal40ee5512008-07-10 02:12:20 +0000936 "public Builder mergeFrom($classname$ other) {\n"
937 // Optimization: If other is the default instance, we know none of its
938 // fields are set so we can skip the merge.
939 " if (other == $classname$.getDefaultInstance()) return this;\n",
940 "classname", ClassName(descriptor_));
941 printer->Indent();
942
943 for (int i = 0; i < descriptor_->field_count(); i++) {
944 field_generators_.get(descriptor_->field(i)).GenerateMergingCode(printer);
945 }
946
947 printer->Outdent();
kenton@google.com2d6daa72009-01-22 01:27:00 +0000948
949 // if message type has extensions
950 if (descriptor_->extension_range_count() > 0) {
951 printer->Print(
952 " this.mergeExtensionFields(other);\n");
953 }
954
kenton@google.com80b1d622009-07-29 01:13:20 +0000955 if (HasUnknownFields(descriptor_)) {
956 printer->Print(
957 " this.mergeUnknownFields(other.getUnknownFields());\n");
958 }
959
temporal40ee5512008-07-10 02:12:20 +0000960 printer->Print(
temporal40ee5512008-07-10 02:12:20 +0000961 " return this;\n"
962 "}\n"
963 "\n");
964 }
965}
966
967// ===================================================================
968
969void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
970 scoped_array<const FieldDescriptor*> sorted_fields(
971 SortFieldsByNumber(descriptor_));
972
973 printer->Print(
974 "public Builder mergeFrom(\n"
temporal40ee5512008-07-10 02:12:20 +0000975 " com.google.protobuf.CodedInputStream input,\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000976 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
temporal40ee5512008-07-10 02:12:20 +0000977 " throws java.io.IOException {\n");
978 printer->Indent();
979
kenton@google.com80b1d622009-07-29 01:13:20 +0000980 if (HasUnknownFields(descriptor_)) {
981 printer->Print(
982 "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
983 " com.google.protobuf.UnknownFieldSet.newBuilder(\n"
984 " this.getUnknownFields());\n");
985 }
986
temporal40ee5512008-07-10 02:12:20 +0000987 printer->Print(
temporal40ee5512008-07-10 02:12:20 +0000988 "while (true) {\n");
989 printer->Indent();
990
991 printer->Print(
992 "int tag = input.readTag();\n"
993 "switch (tag) {\n");
994 printer->Indent();
995
kenton@google.com80b1d622009-07-29 01:13:20 +0000996 if (HasUnknownFields(descriptor_)) {
997 printer->Print(
998 "case 0:\n" // zero signals EOF / limit reached
999 " this.setUnknownFields(unknownFields.build());\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001000 " $on_changed$\n"
kenton@google.com80b1d622009-07-29 01:13:20 +00001001 " return this;\n"
1002 "default: {\n"
1003 " if (!parseUnknownField(input, unknownFields,\n"
1004 " extensionRegistry, tag)) {\n"
1005 " this.setUnknownFields(unknownFields.build());\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001006 " $on_changed$\n"
kenton@google.com80b1d622009-07-29 01:13:20 +00001007 " return this;\n" // it's an endgroup tag
1008 " }\n"
1009 " break;\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001010 "}\n",
1011 "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : "");
kenton@google.com80b1d622009-07-29 01:13:20 +00001012 } else {
1013 printer->Print(
1014 "case 0:\n" // zero signals EOF / limit reached
liujisi@google.com33165fe2010-11-02 13:14:58 +00001015 " $on_changed$\n"
kenton@google.com80b1d622009-07-29 01:13:20 +00001016 " return this;\n"
1017 "default: {\n"
1018 " if (!parseUnknownField(input, extensionRegistry, tag)) {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001019 " $on_changed$\n"
kenton@google.com80b1d622009-07-29 01:13:20 +00001020 " return this;\n" // it's an endgroup tag
1021 " }\n"
1022 " break;\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001023 "}\n",
1024 "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : "");
kenton@google.com80b1d622009-07-29 01:13:20 +00001025 }
temporal40ee5512008-07-10 02:12:20 +00001026
1027 for (int i = 0; i < descriptor_->field_count(); i++) {
1028 const FieldDescriptor* field = sorted_fields[i];
kenton@google.com80b1d622009-07-29 01:13:20 +00001029 uint32 tag = WireFormatLite::MakeTag(field->number(),
kenton@google.comfccb1462009-12-18 02:11:36 +00001030 WireFormat::WireTypeForFieldType(field->type()));
temporal40ee5512008-07-10 02:12:20 +00001031
1032 printer->Print(
1033 "case $tag$: {\n",
1034 "tag", SimpleItoa(tag));
1035 printer->Indent();
1036
1037 field_generators_.get(field).GenerateParsingCode(printer);
1038
1039 printer->Outdent();
1040 printer->Print(
1041 " break;\n"
1042 "}\n");
kenton@google.comfccb1462009-12-18 02:11:36 +00001043
1044 if (field->is_packable()) {
1045 // To make packed = true wire compatible, we generate parsing code from a
1046 // packed version of this field regardless of field->options().packed().
1047 uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
1048 WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
1049 printer->Print(
1050 "case $tag$: {\n",
1051 "tag", SimpleItoa(packed_tag));
1052 printer->Indent();
1053
1054 field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
1055
1056 printer->Outdent();
1057 printer->Print(
1058 " break;\n"
1059 "}\n");
1060 }
temporal40ee5512008-07-10 02:12:20 +00001061 }
1062
1063 printer->Outdent();
1064 printer->Outdent();
1065 printer->Outdent();
1066 printer->Print(
1067 " }\n" // switch (tag)
1068 " }\n" // while (true)
1069 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001070
temporal40ee5512008-07-10 02:12:20 +00001071 "\n");
1072}
1073
1074// ===================================================================
1075
liujisi@google.com33165fe2010-11-02 13:14:58 +00001076void MessageGenerator::GenerateIsInitialized(
1077 io::Printer* printer, UseMemoization useMemoization) {
1078 bool memoization = useMemoization == MEMOIZE;
1079 if (memoization) {
1080 // Memoizes whether the protocol buffer is fully initialized (has all
1081 // required fields). -1 means not yet computed. 0 means false and 1 means
1082 // true.
1083 printer->Print(
1084 "private byte memoizedIsInitialized = -1;\n");
1085 }
temporal40ee5512008-07-10 02:12:20 +00001086 printer->Print(
temporal40ee5512008-07-10 02:12:20 +00001087 "public final boolean isInitialized() {\n");
1088 printer->Indent();
1089
liujisi@google.com33165fe2010-11-02 13:14:58 +00001090 if (memoization) {
1091 printer->Print(
1092 "byte isInitialized = memoizedIsInitialized;\n"
1093 "if (isInitialized != -1) return isInitialized == 1;\n"
1094 "\n");
1095 }
1096
temporal40ee5512008-07-10 02:12:20 +00001097 // Check that all required fields in this message are set.
1098 // TODO(kenton): We can optimize this when we switch to putting all the
1099 // "has" fields into a single bitfield.
1100 for (int i = 0; i < descriptor_->field_count(); i++) {
1101 const FieldDescriptor* field = descriptor_->field(i);
1102
1103 if (field->is_required()) {
1104 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +00001105 "if (!has$name$()) {\n"
1106 " $memoize$\n"
1107 " return false;\n"
1108 "}\n",
1109 "name", UnderscoresToCapitalizedCamelCase(field),
1110 "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
temporal40ee5512008-07-10 02:12:20 +00001111 }
1112 }
1113
1114 // Now check that all embedded messages are initialized.
1115 for (int i = 0; i < descriptor_->field_count(); i++) {
1116 const FieldDescriptor* field = descriptor_->field(i);
kenton@google.comfccb1462009-12-18 02:11:36 +00001117 if (GetJavaType(field) == JAVATYPE_MESSAGE &&
temporal40ee5512008-07-10 02:12:20 +00001118 HasRequiredFields(field->message_type())) {
1119 switch (field->label()) {
1120 case FieldDescriptor::LABEL_REQUIRED:
1121 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +00001122 "if (!get$name$().isInitialized()) {\n"
1123 " $memoize$\n"
1124 " return false;\n"
1125 "}\n",
temporal40ee5512008-07-10 02:12:20 +00001126 "type", ClassName(field->message_type()),
liujisi@google.com33165fe2010-11-02 13:14:58 +00001127 "name", UnderscoresToCapitalizedCamelCase(field),
1128 "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
temporal40ee5512008-07-10 02:12:20 +00001129 break;
1130 case FieldDescriptor::LABEL_OPTIONAL:
1131 printer->Print(
1132 "if (has$name$()) {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001133 " if (!get$name$().isInitialized()) {\n"
1134 " $memoize$\n"
1135 " return false;\n"
1136 " }\n"
temporal40ee5512008-07-10 02:12:20 +00001137 "}\n",
1138 "type", ClassName(field->message_type()),
liujisi@google.com33165fe2010-11-02 13:14:58 +00001139 "name", UnderscoresToCapitalizedCamelCase(field),
1140 "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
temporal40ee5512008-07-10 02:12:20 +00001141 break;
1142 case FieldDescriptor::LABEL_REPEATED:
1143 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +00001144 "for (int i = 0; i < get$name$Count(); i++) {\n"
1145 " if (!get$name$(i).isInitialized()) {\n"
1146 " $memoize$\n"
1147 " return false;\n"
1148 " }\n"
temporal40ee5512008-07-10 02:12:20 +00001149 "}\n",
1150 "type", ClassName(field->message_type()),
liujisi@google.com33165fe2010-11-02 13:14:58 +00001151 "name", UnderscoresToCapitalizedCamelCase(field),
1152 "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
temporal40ee5512008-07-10 02:12:20 +00001153 break;
1154 }
1155 }
1156 }
1157
1158 if (descriptor_->extension_range_count() > 0) {
1159 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +00001160 "if (!extensionsAreInitialized()) {\n"
1161 " $memoize$\n"
1162 " return false;\n"
1163 "}\n",
1164 "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
temporal40ee5512008-07-10 02:12:20 +00001165 }
1166
1167 printer->Outdent();
liujisi@google.com33165fe2010-11-02 13:14:58 +00001168
1169 if (memoization) {
1170 printer->Print(
1171 " memoizedIsInitialized = 1;\n");
1172 }
1173
temporal40ee5512008-07-10 02:12:20 +00001174 printer->Print(
1175 " return true;\n"
1176 "}\n"
1177 "\n");
1178}
1179
kenton@google.com24bf56f2008-09-24 20:31:01 +00001180// ===================================================================
1181
liujisi@google.com33165fe2010-11-02 13:14:58 +00001182void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) {
1183 printer->Print(
1184 "@java.lang.Override\n"
1185 "public boolean equals(final Object obj) {\n");
1186 printer->Indent();
1187 printer->Print(
1188 "if (obj == this) {\n"
1189 " return true;\n"
1190 "}\n"
1191 "if (!(obj instanceof $classname$)) {\n"
1192 " return super.equals(obj);\n"
1193 "}\n"
1194 "$classname$ other = ($classname$) obj;\n"
1195 "\n",
1196 "classname", ClassName(descriptor_));
1197
1198 printer->Print("boolean result = true;\n");
1199 for (int i = 0; i < descriptor_->field_count(); i++) {
1200 const FieldDescriptor* field = descriptor_->field(i);
1201 if (!field->is_repeated()) {
1202 printer->Print(
1203 "result = result && (has$name$() == other.has$name$());\n"
1204 "if (has$name$()) {\n",
1205 "name", UnderscoresToCapitalizedCamelCase(field));
1206 printer->Indent();
1207 }
1208 field_generators_.get(field).GenerateEqualsCode(printer);
1209 if (!field->is_repeated()) {
1210 printer->Outdent();
1211 printer->Print(
1212 "}\n");
1213 }
1214 }
1215 if (HasDescriptorMethods(descriptor_)) {
1216 printer->Print(
1217 "result = result &&\n"
1218 " getUnknownFields().equals(other.getUnknownFields());\n");
1219 if (descriptor_->extension_range_count() > 0) {
1220 printer->Print(
1221 "result = result &&\n"
1222 " getExtensionFields().equals(other.getExtensionFields());\n");
1223 }
1224 }
1225 printer->Print(
1226 "return result;\n");
1227 printer->Outdent();
1228 printer->Print(
1229 "}\n"
1230 "\n");
1231
1232 printer->Print(
1233 "@java.lang.Override\n"
1234 "public int hashCode() {\n");
1235 printer->Indent();
1236 printer->Print(
1237 "int hash = 41;\n"
1238 "hash = (19 * hash) + getDescriptorForType().hashCode();\n");
1239 for (int i = 0; i < descriptor_->field_count(); i++) {
1240 const FieldDescriptor* field = descriptor_->field(i);
1241 if (!field->is_repeated()) {
1242 printer->Print(
1243 "if (has$name$()) {\n",
1244 "name", UnderscoresToCapitalizedCamelCase(field));
1245 printer->Indent();
1246 }
1247 field_generators_.get(field).GenerateHashCode(printer);
1248 if (!field->is_repeated()) {
1249 printer->Outdent();
1250 printer->Print("}\n");
1251 }
1252 }
1253 if (HasDescriptorMethods(descriptor_)) {
1254 if (descriptor_->extension_range_count() > 0) {
1255 printer->Print(
1256 "hash = hashFields(hash, getExtensionFields());\n");
1257 }
1258 }
1259 printer->Print(
1260 "hash = (29 * hash) + getUnknownFields().hashCode();\n"
1261 "return hash;\n");
1262 printer->Outdent();
1263 printer->Print(
1264 "}\n"
1265 "\n");
1266}
1267
1268// ===================================================================
1269
kenton@google.com24bf56f2008-09-24 20:31:01 +00001270void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) {
1271 for (int i = 0; i < descriptor_->extension_count(); i++) {
1272 ExtensionGenerator(descriptor_->extension(i))
1273 .GenerateRegistrationCode(printer);
1274 }
1275
1276 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1277 MessageGenerator(descriptor_->nested_type(i))
1278 .GenerateExtensionRegistrationCode(printer);
1279 }
1280}
1281
temporal40ee5512008-07-10 02:12:20 +00001282} // namespace java
1283} // namespace compiler
1284} // namespace protobuf
1285} // namespace google