javamicro_message_field.cc revision e2d542951c059563a3b7f74c257dac4f222d9dc5
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Protocol Buffers - Google's data interchange format
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2008 Google Inc.  All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/protobuf/
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: kenton@google.com (Kenton Varda)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Based on original Protocol Buffers design by
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Sanjay Ghemawat, Jeff Dean, and others.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/javamicro/javamicro_message_field.h>
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/printer.h>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/wire_format.h>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/strutil.h>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace google {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protobuf {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace compiler {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace javamicro {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   repeat code between this and the other field types.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetMessageVariables(const Params& params,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* descriptor, map<string, string>* variables) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*variables)["name"] =
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnderscoresToCamelCase(descriptor);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*variables)["capitalized_name"] =
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnderscoresToCapitalizedCamelCase(descriptor);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*variables)["number"] = SimpleItoa(descriptor->number());
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*variables)["type"] = ClassName(params, descriptor->message_type());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*variables)["group_or_message"] =
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Group" : "Message";
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*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