javamicro_message_field.cc revision ede38fe9b9f93888e6e41afc7abb09525f44da95
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/javamicro/javamicro_message_field.h>
39#include <google/protobuf/compiler/javamicro/javamicro_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 javamicro {
48
49namespace {
50
51// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
52//   repeat code between this and the other field types.
53void SetMessageVariables(const Params& params,
54    const FieldDescriptor* descriptor, map<string, string>* variables) {
55  (*variables)["name"] =
56    UnderscoresToCamelCase(descriptor);
57  (*variables)["capitalized_name"] =
58    UnderscoresToCapitalizedCamelCase(descriptor);
59  (*variables)["number"] = SimpleItoa(descriptor->number());
60  (*variables)["type"] = ClassName(params, descriptor->message_type());
61  (*variables)["group_or_message"] =
62    (descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
63    "Group" : "Message";
64  (*variables)["message_name"] = descriptor->containing_type()->name();
65  //(*variables)["message_type"] = descriptor->message_type()->name();
66}
67
68}  // namespace
69
70// ===================================================================
71
72MessageFieldGenerator::
73MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
74  : FieldGenerator(params), descriptor_(descriptor) {
75  SetMessageVariables(params, descriptor, &variables_);
76}
77
78MessageFieldGenerator::~MessageFieldGenerator() {}
79
80void MessageFieldGenerator::
81GenerateMembers(io::Printer* printer) const {
82  printer->Print(variables_,
83    "private boolean has$capitalized_name$;\n"
84//    "private $type$ $name$_ = null;\n"
85//    "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
86//    "public $type$ get$capitalized_name$() { return $name$_; }\n"
87    "private $type$ $name$_ = null;\n"
88    "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
89    "public $type$ get$capitalized_name$() { return $name$_; }\n"
90    "public $message_name$ set$capitalized_name$($type$ value) {\n"
91    "  if (value == null) {\n"
92    "    throw new NullPointerException();\n"
93    "  }\n"
94    "  has$capitalized_name$ = true;\n"
95    "  $name$_ = value;\n"
96    "  return this;\n"
97    "}\n"
98    "public $message_name$ clear$capitalized_name$() {\n"
99    "  has$capitalized_name$ = false;\n"
100    "  $name$_ = null;\n"
101    "  return this;\n"
102    "}\n");
103}
104
105void MessageFieldGenerator::
106GenerateMergingCode(io::Printer* printer) const {
107  printer->Print(variables_,
108    "if (other.has$capitalized_name$()) {\n"
109    "  merge$capitalized_name$(other.get$capitalized_name$());\n"
110    "}\n");
111}
112
113void MessageFieldGenerator::
114GenerateParsingCode(io::Printer* printer) const {
115  printer->Print(variables_,
116    "$type$ value = new $type$();\n");
117
118  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
119    printer->Print(variables_,
120      "input.readGroup(value, $number$);\n");
121  } else {
122    printer->Print(variables_,
123      "input.readMessage(value);\n");
124  }
125
126  printer->Print(variables_,
127    "set$capitalized_name$(value);\n");
128}
129
130void MessageFieldGenerator::
131GenerateSerializationCode(io::Printer* printer) const {
132  printer->Print(variables_,
133    "if (has$capitalized_name$()) {\n"
134    "  output.write$group_or_message$($number$, get$capitalized_name$());\n"
135    "}\n");
136}
137
138void MessageFieldGenerator::
139GenerateSerializedSizeCode(io::Printer* printer) const {
140  printer->Print(variables_,
141    "if (has$capitalized_name$()) {\n"
142    "  size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
143    "    .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
144    "}\n");
145}
146
147string MessageFieldGenerator::GetBoxedType() const {
148  return ClassName(params_, descriptor_->message_type());
149}
150
151// ===================================================================
152
153RepeatedMessageFieldGenerator::
154RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
155  : FieldGenerator(params), descriptor_(descriptor) {
156  SetMessageVariables(params, descriptor, &variables_);
157}
158
159RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
160
161void RepeatedMessageFieldGenerator::
162GenerateMembers(io::Printer* printer) const {
163  if (params_.java_use_vector()) {
164    printer->Print(variables_,
165      "private java.util.Vector $name$_ = new java.util.Vector();\n"
166      "public java.util.Vector get$capitalized_name$List() {\n"
167      "  return $name$_;\n"
168      "}\n"
169      "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
170      "public $type$ get$capitalized_name$(int index) {\n"
171      "  return ($type$) $name$_.elementAt(index);\n"
172      "}\n"
173      "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
174      "  if (value == null) {\n"
175      "    throw new NullPointerException();\n"
176      "  }\n"
177      "  $name$_.setElementAt(value, index);\n"
178      "  return this;\n"
179      "}\n"
180      "public $message_name$ add$capitalized_name$($type$ value) {\n"
181      "  if (value == null) {\n"
182      "    throw new NullPointerException();\n"
183      "  }\n"
184      "  $name$_.addElement(value);\n"
185      "  return this;\n"
186      "}\n"
187      "public $message_name$ clear$capitalized_name$() {\n"
188      "  $name$_.removeAllElements();\n"
189      "  return this;\n"
190      "}\n");
191  } else {
192    printer->Print(variables_,
193      "private java.util.List<$type$> $name$_ =\n"
194      "  java.util.Collections.emptyList();\n"
195      "public java.util.List<$type$> get$capitalized_name$List() {\n"
196      "  return $name$_;\n"
197      "}\n"
198      "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
199      "public $type$ get$capitalized_name$(int index) {\n"
200      "  return $name$_.get(index);\n"
201      "}\n"
202      "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
203      "  if (value == null) {\n"
204      "    throw new NullPointerException();\n"
205      "  }\n"
206      "  $name$_.set(index, value);\n"
207      "  return this;\n"
208      "}\n"
209      "public $message_name$ add$capitalized_name$($type$ value) {\n"
210      "  if (value == null) {\n"
211      "    throw new NullPointerException();\n"
212      "  }\n"
213      "  if ($name$_.isEmpty()) {\n"
214      "    $name$_ = new java.util.ArrayList<$type$>();\n"
215      "  }\n"
216      "  $name$_.add(value);\n"
217      "  return this;\n"
218      "}\n"
219      "public $message_name$ clear$capitalized_name$() {\n"
220      "  $name$_ = java.util.Collections.emptyList();\n"
221      "  return this;\n"
222      "}\n");
223  }
224}
225
226void RepeatedMessageFieldGenerator::
227GenerateMergingCode(io::Printer* printer) const {
228  if (params_.java_use_vector()) {
229    printer->Print(variables_,
230      "if (other.$name$_.size() != 0) {\n"
231      "  for (int i = 0; i < other.$name$_.size(); i++) {\n"
232      "    result.$name$_.addElement(other.$name$_.elementAt(i));\n"
233      "  }\n"
234      "}\n");
235  } else {
236    printer->Print(variables_,
237      "if (!other.$name$_.isEmpty()) {\n"
238      "  if (result.$name$_.isEmpty()) {\n"
239      "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
240      "  }\n"
241      "  result.$name$_.addAll(other.$name$_);\n"
242      "}\n");
243  }
244}
245
246void RepeatedMessageFieldGenerator::
247GenerateParsingCode(io::Printer* printer) const {
248  printer->Print(variables_,
249    "$type$ value = new $type$();\n");
250
251  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
252    printer->Print(variables_,
253      "input.readGroup(value, $number$);\n");
254  } else {
255    printer->Print(variables_,
256      "input.readMessage(value);\n");
257  }
258
259  printer->Print(variables_,
260    "add$capitalized_name$(value);\n");
261}
262
263void RepeatedMessageFieldGenerator::
264GenerateSerializationCode(io::Printer* printer) const {
265  if (params_.java_use_vector()) {
266    printer->Print(variables_,
267      "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
268      "  output.write$group_or_message$($number$, get$capitalized_name$(i));\n"
269      "}\n");
270  } else {
271    printer->Print(variables_,
272      "for ($type$ element : get$capitalized_name$List()) {\n"
273      "  output.write$group_or_message$($number$, element);\n"
274      "}\n");
275  }
276}
277
278void RepeatedMessageFieldGenerator::
279GenerateSerializedSizeCode(io::Printer* printer) const {
280  if (params_.java_use_vector()) {
281    printer->Print(variables_,
282      "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
283      "  size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
284      "    .compute$group_or_message$Size($number$, get$capitalized_name$(i));\n"
285      "}\n");
286  } else {
287    printer->Print(variables_,
288      "for ($type$ element : get$capitalized_name$List()) {\n"
289      "  size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
290      "    .compute$group_or_message$Size($number$, element);\n"
291      "}\n");
292  }
293}
294
295string RepeatedMessageFieldGenerator::GetBoxedType() const {
296  return ClassName(params_, descriptor_->message_type());
297}
298
299}  // namespace javamicro
300}  // namespace compiler
301}  // namespace protobuf
302}  // namespace google
303