javanano_message_field.cc revision b15a1b379f896e371ca3375bdf51dd4a9a0268af
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) 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
129string MessageFieldGenerator::GetBoxedType() const {
130  return ClassName(params_, descriptor_->message_type());
131}
132
133// ===================================================================
134
135AccessorMessageFieldGenerator::
136AccessorMessageFieldGenerator(
137    const FieldDescriptor* descriptor, const Params& params)
138  : FieldGenerator(params), descriptor_(descriptor) {
139  SetMessageVariables(params, descriptor, &variables_);
140}
141
142AccessorMessageFieldGenerator::~AccessorMessageFieldGenerator() {}
143
144void AccessorMessageFieldGenerator::
145GenerateMembers(io::Printer* printer) const {
146  printer->Print(variables_,
147    "private $type$ $name$_;\n"
148    "public $type$ get$capitalized_name$() {\n"
149    "  return $name$_;\n"
150    "}\n"
151    "public $message_name$ set$capitalized_name$($type$ value) {\n"
152    "  if (value == null) {\n"
153    "    throw new java.lang.NullPointerException();\n"
154    "  }\n"
155    "  $name$_ = value;\n"
156    "  return this;\n"
157    "}\n"
158    "public boolean has$capitalized_name$() {\n"
159    "  return $name$_ != null;\n"
160    "}\n"
161    "public $message_name$ clear$capitalized_name$() {\n"
162    "  $name$_ = null;\n"
163    "  return this;"
164    "}\n");
165}
166
167void AccessorMessageFieldGenerator::
168GenerateClearCode(io::Printer* printer) const {
169  printer->Print(variables_,
170    "$name$_ = null;\n");
171}
172
173void AccessorMessageFieldGenerator::
174GenerateMergingCode(io::Printer* printer) const {
175  printer->Print(variables_,
176    "if ($name$_ == null) {\n"
177    "  $name$_ = new $type$();\n"
178    "}\n");
179
180  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
181    printer->Print(variables_,
182      "input.readGroup($name$_, $number$);\n");
183  } else {
184    printer->Print(variables_,
185      "input.readMessage($name$_);\n");
186  }
187}
188
189void AccessorMessageFieldGenerator::
190GenerateSerializationCode(io::Printer* printer) const {
191  printer->Print(variables_,
192    "if ($name$_ != null) {\n"
193    "  output.write$group_or_message$($number$, $name$_);\n"
194    "}\n");
195}
196
197void AccessorMessageFieldGenerator::
198GenerateSerializedSizeCode(io::Printer* printer) const {
199  printer->Print(variables_,
200    "if ($name$_ != null) {\n"
201    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
202    "    .compute$group_or_message$Size($number$, $name$_);\n"
203    "}\n");
204}
205
206string AccessorMessageFieldGenerator::GetBoxedType() const {
207  return ClassName(params_, descriptor_->message_type());
208}
209
210// ===================================================================
211
212RepeatedMessageFieldGenerator::
213RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
214  : FieldGenerator(params), descriptor_(descriptor) {
215  SetMessageVariables(params, descriptor, &variables_);
216}
217
218RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
219
220void RepeatedMessageFieldGenerator::
221GenerateMembers(io::Printer* printer) const {
222  printer->Print(variables_,
223    "public $type$[] $name$;\n");
224}
225
226void RepeatedMessageFieldGenerator::
227GenerateClearCode(io::Printer* printer) const {
228  printer->Print(variables_,
229    "$name$ = $type$.EMPTY_ARRAY;\n");
230}
231
232void RepeatedMessageFieldGenerator::
233GenerateMergingCode(io::Printer* printer) const {
234  // First, figure out the length of the array, then parse.
235  printer->Print(variables_,
236    "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
237    "    .getRepeatedFieldArrayLength(input, $tag$);\n"
238    "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
239    "$type$[] newArray =\n"
240    "    new $type$[i + arrayLength];\n"
241    "if (i != 0) {\n"
242    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
243    "}\n"
244    "for (; i < newArray.length - 1; i++) {\n"
245    "  newArray[i] = new $type$();\n");
246
247  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
248    printer->Print(variables_,
249      "  input.readGroup(newArray[i], $number$);\n");
250  } else {
251    printer->Print(variables_,
252      "  input.readMessage(newArray[i]);\n");
253  }
254
255  printer->Print(variables_,
256    "  input.readTag();\n"
257    "}\n"
258    "// Last one without readTag.\n"
259    "newArray[i] = new $type$();\n");
260
261  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
262    printer->Print(variables_,
263      "input.readGroup(newArray[i], $number$);\n");
264  } else {
265    printer->Print(variables_,
266      "input.readMessage(newArray[i]);\n");
267  }
268
269  printer->Print(variables_,
270    "this.$name$ = newArray;\n");
271}
272
273void RepeatedMessageFieldGenerator::
274GenerateSerializationCode(io::Printer* printer) const {
275  printer->Print(variables_,
276    "if (this.$name$ != null) {\n"
277    "  for ($type$ element : this.$name$) {\n"
278    "    output.write$group_or_message$($number$, element);\n"
279    "  }\n"
280    "}\n");
281}
282
283void RepeatedMessageFieldGenerator::
284GenerateSerializedSizeCode(io::Printer* printer) const {
285  printer->Print(variables_,
286    "if (this.$name$ != null) {\n"
287    "  for ($type$ element : this.$name$) {\n"
288    "    size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
289    "      .compute$group_or_message$Size($number$, element);\n"
290    "  }\n"
291    "}\n");
292}
293
294string RepeatedMessageFieldGenerator::GetBoxedType() const {
295  return ClassName(params_, descriptor_->message_type());
296}
297
298}  // namespace javanano
299}  // namespace compiler
300}  // namespace protobuf
301}  // namespace google
302