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