java_message_field.cc revision d0332953cda33fb4f8e24ebff9c49159b69c43d6
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/java/java_message_field.h>
39#include <google/protobuf/compiler/java/java_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 java {
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 FieldDescriptor* descriptor,
54                         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(descriptor->message_type());
61  (*variables)["group_or_message"] =
62    (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
63    "Group" : "Message";
64}
65
66}  // namespace
67
68// ===================================================================
69
70MessageFieldGenerator::
71MessageFieldGenerator(const FieldDescriptor* descriptor)
72  : descriptor_(descriptor) {
73  SetMessageVariables(descriptor, &variables_);
74}
75
76MessageFieldGenerator::~MessageFieldGenerator() {}
77
78void MessageFieldGenerator::
79GenerateMembers(io::Printer* printer) const {
80  printer->Print(variables_,
81    "private boolean has$capitalized_name$;\n"
82    "private $type$ $name$_;\n"
83    "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
84    "public $type$ get$capitalized_name$() { return $name$_; }\n");
85}
86
87void MessageFieldGenerator::
88GenerateBuilderMembers(io::Printer* printer) const {
89  printer->Print(variables_,
90    "public boolean has$capitalized_name$() {\n"
91    "  return result.has$capitalized_name$();\n"
92    "}\n"
93    "public $type$ get$capitalized_name$() {\n"
94    "  return result.get$capitalized_name$();\n"
95    "}\n"
96    "public Builder set$capitalized_name$($type$ value) {\n"
97    "  if (value == null) {\n"
98    "    throw new NullPointerException();\n"
99    "  }\n"
100    "  result.has$capitalized_name$ = true;\n"
101    "  result.$name$_ = value;\n"
102    "  return this;\n"
103    "}\n"
104    "public Builder set$capitalized_name$($type$.Builder builderForValue) {\n"
105    "  result.has$capitalized_name$ = true;\n"
106    "  result.$name$_ = builderForValue.build();\n"
107    "  return this;\n"
108    "}\n"
109    "public Builder merge$capitalized_name$($type$ value) {\n"
110    "  if (result.has$capitalized_name$() &&\n"
111    "      result.$name$_ != $type$.getDefaultInstance()) {\n"
112    "    result.$name$_ =\n"
113    "      $type$.newBuilder(result.$name$_).mergeFrom(value).buildPartial();\n"
114    "  } else {\n"
115    "    result.$name$_ = value;\n"
116    "  }\n"
117    "  result.has$capitalized_name$ = true;\n"
118    "  return this;\n"
119    "}\n"
120    "public Builder clear$capitalized_name$() {\n"
121    "  result.has$capitalized_name$ = false;\n"
122    "  result.$name$_ = $type$.getDefaultInstance();\n"
123    "  return this;\n"
124    "}\n");
125}
126
127void MessageFieldGenerator::
128GenerateInitializationCode(io::Printer* printer) const {
129  printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n");
130}
131
132void MessageFieldGenerator::
133GenerateMergingCode(io::Printer* printer) const {
134  printer->Print(variables_,
135    "if (other.has$capitalized_name$()) {\n"
136    "  merge$capitalized_name$(other.get$capitalized_name$());\n"
137    "}\n");
138}
139
140void MessageFieldGenerator::
141GenerateBuildingCode(io::Printer* printer) const {
142  // Nothing to do for singular fields.
143}
144
145void MessageFieldGenerator::
146GenerateParsingCode(io::Printer* printer) const {
147  printer->Print(variables_,
148    "$type$.Builder subBuilder = $type$.newBuilder();\n"
149    "if (has$capitalized_name$()) {\n"
150    "  subBuilder.mergeFrom(get$capitalized_name$());\n"
151    "}\n");
152
153  if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
154    printer->Print(variables_,
155      "input.readGroup($number$, subBuilder, extensionRegistry);\n");
156  } else {
157    printer->Print(variables_,
158      "input.readMessage(subBuilder, extensionRegistry);\n");
159  }
160
161  printer->Print(variables_,
162    "set$capitalized_name$(subBuilder.buildPartial());\n");
163}
164
165void MessageFieldGenerator::
166GenerateSerializationCode(io::Printer* printer) const {
167  printer->Print(variables_,
168    "if (has$capitalized_name$()) {\n"
169    "  output.write$group_or_message$($number$, get$capitalized_name$());\n"
170    "}\n");
171}
172
173void MessageFieldGenerator::
174GenerateSerializedSizeCode(io::Printer* printer) const {
175  printer->Print(variables_,
176    "if (has$capitalized_name$()) {\n"
177    "  size += com.google.protobuf.CodedOutputStream\n"
178    "    .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
179    "}\n");
180}
181
182string MessageFieldGenerator::GetBoxedType() const {
183  return ClassName(descriptor_->message_type());
184}
185
186// ===================================================================
187
188RepeatedMessageFieldGenerator::
189RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
190  : descriptor_(descriptor) {
191  SetMessageVariables(descriptor, &variables_);
192}
193
194RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
195
196void RepeatedMessageFieldGenerator::
197GenerateMembers(io::Printer* printer) const {
198  printer->Print(variables_,
199    "private java.util.List<$type$> $name$_ =\n"
200    "  java.util.Collections.emptyList();\n"
201    "public java.util.List<$type$> get$capitalized_name$List() {\n"
202    "  return $name$_;\n"   // note:  unmodifiable list
203    "}\n"
204    "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
205    "public $type$ get$capitalized_name$(int index) {\n"
206    "  return $name$_.get(index);\n"
207    "}\n");
208}
209
210void RepeatedMessageFieldGenerator::
211GenerateBuilderMembers(io::Printer* printer) const {
212  printer->Print(variables_,
213    // Note:  We return an unmodifiable list because otherwise the caller
214    //   could hold on to the returned list and modify it after the message
215    //   has been built, thus mutating the message which is supposed to be
216    //   immutable.
217    "public java.util.List<$type$> get$capitalized_name$List() {\n"
218    "  return java.util.Collections.unmodifiableList(result.$name$_);\n"
219    "}\n"
220    "public int get$capitalized_name$Count() {\n"
221    "  return result.get$capitalized_name$Count();\n"
222    "}\n"
223    "public $type$ get$capitalized_name$(int index) {\n"
224    "  return result.get$capitalized_name$(index);\n"
225    "}\n"
226    "public Builder set$capitalized_name$(int index, $type$ value) {\n"
227    "  if (value == null) {\n"
228    "    throw new NullPointerException();\n"
229    "  }\n"
230    "  result.$name$_.set(index, value);\n"
231    "  return this;\n"
232    "}\n"
233    "public Builder set$capitalized_name$(int index, "
234      "$type$.Builder builderForValue) {\n"
235    "  result.$name$_.set(index, builderForValue.build());\n"
236    "  return this;\n"
237    "}\n"
238    "public Builder add$capitalized_name$($type$ value) {\n"
239    "  if (value == null) {\n"
240    "    throw new NullPointerException();\n"
241    "  }\n"
242    "  if (result.$name$_.isEmpty()) {\n"
243    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
244    "  }\n"
245    "  result.$name$_.add(value);\n"
246    "  return this;\n"
247    "}\n"
248    "public Builder add$capitalized_name$($type$.Builder builderForValue) {\n"
249    "  if (result.$name$_.isEmpty()) {\n"
250    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
251    "  }\n"
252    "  result.$name$_.add(builderForValue.build());\n"
253    "  return this;\n"
254    "}\n"
255    "public Builder addAll$capitalized_name$(\n"
256    "    java.lang.Iterable<? extends $type$> values) {\n"
257    "  if (result.$name$_.isEmpty()) {\n"
258    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
259    "  }\n"
260    "  super.addAll(values, result.$name$_);\n"
261    "  return this;\n"
262    "}\n"
263    "public Builder clear$capitalized_name$() {\n"
264    "  result.$name$_ = java.util.Collections.emptyList();\n"
265    "  return this;\n"
266    "}\n");
267}
268
269void RepeatedMessageFieldGenerator::
270GenerateInitializationCode(io::Printer* printer) const {
271  // Initialized inline.
272}
273
274void RepeatedMessageFieldGenerator::
275GenerateMergingCode(io::Printer* printer) const {
276  printer->Print(variables_,
277    "if (!other.$name$_.isEmpty()) {\n"
278    "  if (result.$name$_.isEmpty()) {\n"
279    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
280    "  }\n"
281    "  result.$name$_.addAll(other.$name$_);\n"
282    "}\n");
283}
284
285void RepeatedMessageFieldGenerator::
286GenerateBuildingCode(io::Printer* printer) const {
287  printer->Print(variables_,
288    "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n"
289    "  result.$name$_ =\n"
290    "    java.util.Collections.unmodifiableList(result.$name$_);\n"
291    "}\n");
292}
293
294void RepeatedMessageFieldGenerator::
295GenerateParsingCode(io::Printer* printer) const {
296  printer->Print(variables_,
297    "$type$.Builder subBuilder = $type$.newBuilder();\n");
298
299  if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
300    printer->Print(variables_,
301      "input.readGroup($number$, subBuilder, extensionRegistry);\n");
302  } else {
303    printer->Print(variables_,
304      "input.readMessage(subBuilder, extensionRegistry);\n");
305  }
306
307  printer->Print(variables_,
308    "add$capitalized_name$(subBuilder.buildPartial());\n");
309}
310
311void RepeatedMessageFieldGenerator::
312GenerateSerializationCode(io::Printer* printer) const {
313  printer->Print(variables_,
314    "for ($type$ element : get$capitalized_name$List()) {\n"
315    "  output.write$group_or_message$($number$, element);\n"
316    "}\n");
317}
318
319void RepeatedMessageFieldGenerator::
320GenerateSerializedSizeCode(io::Printer* printer) const {
321  printer->Print(variables_,
322    "for ($type$ element : get$capitalized_name$List()) {\n"
323    "  size += com.google.protobuf.CodedOutputStream\n"
324    "    .compute$group_or_message$Size($number$, element);\n"
325    "}\n");
326}
327
328string RepeatedMessageFieldGenerator::GetBoxedType() const {
329  return ClassName(descriptor_->message_type());
330}
331
332}  // namespace java
333}  // namespace compiler
334}  // namespace protobuf
335}  // namespace google
336