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 <map>
36#include <string>
37
38#include <google/protobuf/compiler/javanano/javanano_message_field.h>
39#include <google/protobuf/compiler/javanano/javanano_helpers.h>
40#include <google/protobuf/io/printer.h>
41#include <google/protobuf/wire_format.h>
42#include <google/protobuf/stubs/strutil.h>
43
44namespace google {
45namespace protobuf {
46namespace compiler {
47namespace javanano {
48
49using internal::WireFormat;
50using internal::WireFormatLite;
51
52namespace {
53
54// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
55//   repeat code between this and the other field types.
56void SetMessageVariables(const Params& params,
57    const FieldDescriptor* descriptor, map<string, string>* variables) {
58  (*variables)["name"] =
59    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
60  (*variables)["capitalized_name"] =
61    RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
62  (*variables)["number"] = SimpleItoa(descriptor->number());
63  (*variables)["type"] = ClassName(params, descriptor->message_type());
64  (*variables)["group_or_message"] =
65    (descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
66    "Group" : "Message";
67  (*variables)["message_name"] = descriptor->containing_type()->name();
68  //(*variables)["message_type"] = descriptor->message_type()->name();
69  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
70}
71
72}  // namespace
73
74// ===================================================================
75
76MessageFieldGenerator::
77MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
78  : FieldGenerator(params), descriptor_(descriptor) {
79  SetMessageVariables(params, descriptor, &variables_);
80}
81
82MessageFieldGenerator::~MessageFieldGenerator() {}
83
84void MessageFieldGenerator::
85GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
86  printer->Print(variables_,
87    "public $type$ $name$;\n");
88}
89
90void MessageFieldGenerator::
91GenerateClearCode(io::Printer* printer) const {
92  printer->Print(variables_,
93    "$name$ = null;\n");
94}
95
96void MessageFieldGenerator::
97GenerateMergingCode(io::Printer* printer) const {
98  printer->Print(variables_,
99    "if (this.$name$ == null) {\n"
100    "  this.$name$ = new $type$();\n"
101    "}\n");
102
103  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
104    printer->Print(variables_,
105      "input.readGroup(this.$name$, $number$);\n");
106  } else {
107    printer->Print(variables_,
108      "input.readMessage(this.$name$);\n");
109  }
110}
111
112void MessageFieldGenerator::
113GenerateSerializationCode(io::Printer* printer) const {
114  printer->Print(variables_,
115    "if (this.$name$ != null) {\n"
116    "  output.write$group_or_message$($number$, this.$name$);\n"
117    "}\n");
118}
119
120void MessageFieldGenerator::
121GenerateSerializedSizeCode(io::Printer* printer) const {
122  printer->Print(variables_,
123    "if (this.$name$ != null) {\n"
124    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
125    "    .compute$group_or_message$Size($number$, this.$name$);\n"
126    "}\n");
127}
128
129void MessageFieldGenerator::
130GenerateFixClonedCode(io::Printer* printer) const {
131  printer->Print(variables_,
132    "if (this.$name$ != null) {\n"
133    "  cloned.$name$ = this.$name$.clone();\n"
134    "}\n");
135}
136
137void MessageFieldGenerator::
138GenerateEqualsCode(io::Printer* printer) const {
139  printer->Print(variables_,
140    "if (this.$name$ == null) { \n"
141    "  if (other.$name$ != null) {\n"
142    "    return false;\n"
143    "  }\n"
144    "} else {\n"
145    "  if (!this.$name$.equals(other.$name$)) {\n"
146    "    return false;\n"
147    "  }\n"
148    "}\n");
149}
150
151void MessageFieldGenerator::
152GenerateHashCodeCode(io::Printer* printer) const {
153  printer->Print(variables_,
154    "result = 31 * result +\n"
155    "    (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
156}
157// ===================================================================
158
159MessageOneofFieldGenerator::MessageOneofFieldGenerator(
160    const FieldDescriptor* descriptor, const Params& params)
161    : FieldGenerator(params), descriptor_(descriptor) {
162    SetMessageVariables(params, descriptor, &variables_);
163    SetCommonOneofVariables(descriptor, &variables_);
164}
165
166MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
167
168void MessageOneofFieldGenerator::
169GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
170  printer->Print(variables_,
171    "public boolean has$capitalized_name$() {\n"
172    "  return $has_oneof_case$;\n"
173    "}\n"
174    "public $type$ get$capitalized_name$() {\n"
175    "  if ($has_oneof_case$) {\n"
176    "    return ($type$) this.$oneof_name$_;\n"
177    "  }\n"
178    "  return null;\n"
179    "}\n"
180    "public $message_name$ set$capitalized_name$($type$ value) {\n"
181    "  if (value == null) { throw new java.lang.NullPointerException(); }\n"
182    "  $set_oneof_case$;\n"
183    "  this.$oneof_name$_ = value;\n"
184    "  return this;\n"
185    "}\n");
186}
187
188void MessageOneofFieldGenerator::
189GenerateClearCode(io::Printer* printer) const {
190  // No clear method for oneof fields.
191}
192
193void MessageOneofFieldGenerator::
194GenerateMergingCode(io::Printer* printer) const {
195  printer->Print(variables_,
196    "if (!($has_oneof_case$)) {\n"
197    "  this.$oneof_name$_ = new $type$();\n"
198    "}\n"
199    "input.readMessage(\n"
200    "    (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
201    "$set_oneof_case$;\n");
202}
203
204void MessageOneofFieldGenerator::
205GenerateSerializationCode(io::Printer* printer) const {
206  printer->Print(variables_,
207    "if ($has_oneof_case$) {\n"
208    "  output.writeMessage($number$,\n"
209    "      (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
210    "}\n");
211}
212
213void MessageOneofFieldGenerator::
214GenerateSerializedSizeCode(io::Printer* printer) const {
215  printer->Print(variables_,
216    "if ($has_oneof_case$) {\n"
217    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
218    "    .computeMessageSize($number$,\n"
219    "        (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
220    "}\n");
221}
222
223void MessageOneofFieldGenerator::
224GenerateFixClonedCode(io::Printer* printer) const {
225  printer->Print(variables_,
226    "if (this.$oneof_name$ != null) {\n"
227    "  cloned.$oneof_name$ = this.$oneof_name$.clone();\n"
228    "}\n");
229}
230
231void MessageOneofFieldGenerator::
232GenerateEqualsCode(io::Printer* printer) const {
233  GenerateOneofFieldEquals(descriptor_, variables_, printer);
234}
235
236void MessageOneofFieldGenerator::
237GenerateHashCodeCode(io::Printer* printer) const {
238  GenerateOneofFieldHashCode(descriptor_, variables_, printer);
239}
240
241// ===================================================================
242
243RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
244    const FieldDescriptor* descriptor, const Params& params)
245    : FieldGenerator(params), descriptor_(descriptor) {
246  SetMessageVariables(params, descriptor, &variables_);
247}
248
249RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
250
251void RepeatedMessageFieldGenerator::
252GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
253  printer->Print(variables_,
254    "public $type$[] $name$;\n");
255}
256
257void RepeatedMessageFieldGenerator::
258GenerateClearCode(io::Printer* printer) const {
259  printer->Print(variables_,
260    "$name$ = $type$.emptyArray();\n");
261}
262
263void RepeatedMessageFieldGenerator::
264GenerateMergingCode(io::Printer* printer) const {
265  // First, figure out the length of the array, then parse.
266  printer->Print(variables_,
267    "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
268    "    .getRepeatedFieldArrayLength(input, $tag$);\n"
269    "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
270    "$type$[] newArray =\n"
271    "    new $type$[i + arrayLength];\n"
272    "if (i != 0) {\n"
273    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
274    "}\n"
275    "for (; i < newArray.length - 1; i++) {\n"
276    "  newArray[i] = new $type$();\n");
277
278  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
279    printer->Print(variables_,
280      "  input.readGroup(newArray[i], $number$);\n");
281  } else {
282    printer->Print(variables_,
283      "  input.readMessage(newArray[i]);\n");
284  }
285
286  printer->Print(variables_,
287    "  input.readTag();\n"
288    "}\n"
289    "// Last one without readTag.\n"
290    "newArray[i] = new $type$();\n");
291
292  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
293    printer->Print(variables_,
294      "input.readGroup(newArray[i], $number$);\n");
295  } else {
296    printer->Print(variables_,
297      "input.readMessage(newArray[i]);\n");
298  }
299
300  printer->Print(variables_,
301    "this.$name$ = newArray;\n");
302}
303
304void RepeatedMessageFieldGenerator::
305GenerateSerializationCode(io::Printer* printer) const {
306  printer->Print(variables_,
307    "if (this.$name$ != null && this.$name$.length > 0) {\n"
308    "  for (int i = 0; i < this.$name$.length; i++) {\n"
309    "    $type$ element = this.$name$[i];\n"
310    "    if (element != null) {\n"
311    "      output.write$group_or_message$($number$, element);\n"
312    "    }\n"
313    "  }\n"
314    "}\n");
315}
316
317void RepeatedMessageFieldGenerator::
318GenerateSerializedSizeCode(io::Printer* printer) const {
319  printer->Print(variables_,
320    "if (this.$name$ != null && this.$name$.length > 0) {\n"
321    "  for (int i = 0; i < this.$name$.length; i++) {\n"
322    "    $type$ element = this.$name$[i];\n"
323    "    if (element != null) {\n"
324    "      size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
325    "        .compute$group_or_message$Size($number$, element);\n"
326    "    }\n"
327    "  }\n"
328    "}\n");
329}
330
331void RepeatedMessageFieldGenerator::
332GenerateFixClonedCode(io::Printer* printer) const {
333  printer->Print(variables_,
334    "if (this.$name$ != null && this.$name$.length > 0) {\n"
335    "  cloned.$name$ = new $type$[this.$name$.length];\n"
336    "  for (int i = 0; i < this.$name$.length; i++) {\n"
337    "    if (this.$name$[i] != null) {\n"
338    "      cloned.$name$[i] = this.$name$[i].clone();\n"
339    "    }\n"
340    "  }\n"
341    "}\n");
342}
343
344void RepeatedMessageFieldGenerator::
345GenerateEqualsCode(io::Printer* printer) const {
346  printer->Print(variables_,
347    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
348    "    this.$name$, other.$name$)) {\n"
349    "  return false;\n"
350    "}\n");
351}
352
353void RepeatedMessageFieldGenerator::
354GenerateHashCodeCode(io::Printer* printer) const {
355  printer->Print(variables_,
356    "result = 31 * result\n"
357    "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
358}
359
360}  // namespace javanano
361}  // namespace compiler
362}  // namespace protobuf
363}  // namespace google
364