java_message_field.cc revision fbaaef999ba563838ebd00874ed8a1c01fbf286d
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    (descriptor->type() == 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$_ = $type$.getDefaultInstance();\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::
128GenerateMergingCode(io::Printer* printer) const {
129  printer->Print(variables_,
130    "if (other.has$capitalized_name$()) {\n"
131    "  merge$capitalized_name$(other.get$capitalized_name$());\n"
132    "}\n");
133}
134
135void MessageFieldGenerator::
136GenerateBuildingCode(io::Printer* printer) const {
137  // Nothing to do for singular fields.
138}
139
140void MessageFieldGenerator::
141GenerateParsingCode(io::Printer* printer) const {
142  printer->Print(variables_,
143    "$type$.Builder subBuilder = $type$.newBuilder();\n"
144    "if (has$capitalized_name$()) {\n"
145    "  subBuilder.mergeFrom(get$capitalized_name$());\n"
146    "}\n");
147
148  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
149    printer->Print(variables_,
150      "input.readGroup($number$, subBuilder, extensionRegistry);\n");
151  } else {
152    printer->Print(variables_,
153      "input.readMessage(subBuilder, extensionRegistry);\n");
154  }
155
156  printer->Print(variables_,
157    "set$capitalized_name$(subBuilder.buildPartial());\n");
158}
159
160void MessageFieldGenerator::
161GenerateSerializationCode(io::Printer* printer) const {
162  printer->Print(variables_,
163    "if (has$capitalized_name$()) {\n"
164    "  output.write$group_or_message$($number$, get$capitalized_name$());\n"
165    "}\n");
166}
167
168void MessageFieldGenerator::
169GenerateSerializedSizeCode(io::Printer* printer) const {
170  printer->Print(variables_,
171    "if (has$capitalized_name$()) {\n"
172    "  size += com.google.protobuf.CodedOutputStream\n"
173    "    .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
174    "}\n");
175}
176
177string MessageFieldGenerator::GetBoxedType() const {
178  return ClassName(descriptor_->message_type());
179}
180
181// ===================================================================
182
183RepeatedMessageFieldGenerator::
184RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
185  : descriptor_(descriptor) {
186  SetMessageVariables(descriptor, &variables_);
187}
188
189RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
190
191void RepeatedMessageFieldGenerator::
192GenerateMembers(io::Printer* printer) const {
193  printer->Print(variables_,
194    "private java.util.List<$type$> $name$_ =\n"
195    "  java.util.Collections.emptyList();\n"
196    "public java.util.List<$type$> get$capitalized_name$List() {\n"
197    "  return $name$_;\n"   // note:  unmodifiable list
198    "}\n"
199    "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
200    "public $type$ get$capitalized_name$(int index) {\n"
201    "  return $name$_.get(index);\n"
202    "}\n");
203}
204
205void RepeatedMessageFieldGenerator::
206GenerateBuilderMembers(io::Printer* printer) const {
207  printer->Print(variables_,
208    // Note:  We return an unmodifiable list because otherwise the caller
209    //   could hold on to the returned list and modify it after the message
210    //   has been built, thus mutating the message which is supposed to be
211    //   immutable.
212    "public java.util.List<$type$> get$capitalized_name$List() {\n"
213    "  return java.util.Collections.unmodifiableList(result.$name$_);\n"
214    "}\n"
215    "public int get$capitalized_name$Count() {\n"
216    "  return result.get$capitalized_name$Count();\n"
217    "}\n"
218    "public $type$ get$capitalized_name$(int index) {\n"
219    "  return result.get$capitalized_name$(index);\n"
220    "}\n"
221    "public Builder set$capitalized_name$(int index, $type$ value) {\n"
222    "  if (value == null) {\n"
223    "    throw new NullPointerException();\n"
224    "  }\n"
225    "  result.$name$_.set(index, value);\n"
226    "  return this;\n"
227    "}\n"
228    "public Builder set$capitalized_name$(int index, "
229      "$type$.Builder builderForValue) {\n"
230    "  result.$name$_.set(index, builderForValue.build());\n"
231    "  return this;\n"
232    "}\n"
233    "public Builder add$capitalized_name$($type$ value) {\n"
234    "  if (value == null) {\n"
235    "    throw new NullPointerException();\n"
236    "  }\n"
237    "  if (result.$name$_.isEmpty()) {\n"
238    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
239    "  }\n"
240    "  result.$name$_.add(value);\n"
241    "  return this;\n"
242    "}\n"
243    "public Builder add$capitalized_name$($type$.Builder builderForValue) {\n"
244    "  if (result.$name$_.isEmpty()) {\n"
245    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
246    "  }\n"
247    "  result.$name$_.add(builderForValue.build());\n"
248    "  return this;\n"
249    "}\n"
250    "public Builder addAll$capitalized_name$(\n"
251    "    java.lang.Iterable<? extends $type$> values) {\n"
252    "  if (result.$name$_.isEmpty()) {\n"
253    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
254    "  }\n"
255    "  super.addAll(values, result.$name$_);\n"
256    "  return this;\n"
257    "}\n"
258    "public Builder clear$capitalized_name$() {\n"
259    "  result.$name$_ = java.util.Collections.emptyList();\n"
260    "  return this;\n"
261    "}\n");
262}
263
264void RepeatedMessageFieldGenerator::
265GenerateMergingCode(io::Printer* printer) const {
266  printer->Print(variables_,
267    "if (!other.$name$_.isEmpty()) {\n"
268    "  if (result.$name$_.isEmpty()) {\n"
269    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
270    "  }\n"
271    "  result.$name$_.addAll(other.$name$_);\n"
272    "}\n");
273}
274
275void RepeatedMessageFieldGenerator::
276GenerateBuildingCode(io::Printer* printer) const {
277  printer->Print(variables_,
278    "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n"
279    "  result.$name$_ =\n"
280    "    java.util.Collections.unmodifiableList(result.$name$_);\n"
281    "}\n");
282}
283
284void RepeatedMessageFieldGenerator::
285GenerateParsingCode(io::Printer* printer) const {
286  printer->Print(variables_,
287    "$type$.Builder subBuilder = $type$.newBuilder();\n");
288
289  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
290    printer->Print(variables_,
291      "input.readGroup($number$, subBuilder, extensionRegistry);\n");
292  } else {
293    printer->Print(variables_,
294      "input.readMessage(subBuilder, extensionRegistry);\n");
295  }
296
297  printer->Print(variables_,
298    "add$capitalized_name$(subBuilder.buildPartial());\n");
299}
300
301void RepeatedMessageFieldGenerator::
302GenerateSerializationCode(io::Printer* printer) const {
303  printer->Print(variables_,
304    "for ($type$ element : get$capitalized_name$List()) {\n"
305    "  output.write$group_or_message$($number$, element);\n"
306    "}\n");
307}
308
309void RepeatedMessageFieldGenerator::
310GenerateSerializedSizeCode(io::Printer* printer) const {
311  printer->Print(variables_,
312    "for ($type$ element : get$capitalized_name$List()) {\n"
313    "  size += com.google.protobuf.CodedOutputStream\n"
314    "    .compute$group_or_message$Size($number$, element);\n"
315    "}\n");
316}
317
318string RepeatedMessageFieldGenerator::GetBoxedType() const {
319  return ClassName(descriptor_->message_type());
320}
321
322}  // namespace java
323}  // namespace compiler
324}  // namespace protobuf
325}  // namespace google
326