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
44 namespace google {
45 namespace protobuf {
46 namespace compiler {
47 namespace java {
48
49 namespace {
50
51 // TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
52 // repeat code between this and the other field types.
SetMessageVariables(const FieldDescriptor * descriptor,map<string,string> * variables)53 void 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
70 MessageFieldGenerator::
MessageFieldGenerator(const FieldDescriptor * descriptor)71 MessageFieldGenerator(const FieldDescriptor* descriptor)
72 : descriptor_(descriptor) {
73 SetMessageVariables(descriptor, &variables_);
74 }
75
~MessageFieldGenerator()76 MessageFieldGenerator::~MessageFieldGenerator() {}
77
78 void MessageFieldGenerator::
GenerateMembers(io::Printer * printer) const79 GenerateMembers(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
87 void MessageFieldGenerator::
GenerateBuilderMembers(io::Printer * printer) const88 GenerateBuilderMembers(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
127 void MessageFieldGenerator::
GenerateInitializationCode(io::Printer * printer) const128 GenerateInitializationCode(io::Printer* printer) const {
129 printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n");
130 }
131
132 void MessageFieldGenerator::
GenerateMergingCode(io::Printer * printer) const133 GenerateMergingCode(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
140 void MessageFieldGenerator::
GenerateBuildingCode(io::Printer * printer) const141 GenerateBuildingCode(io::Printer* printer) const {
142 // Nothing to do for singular fields.
143 }
144
145 void MessageFieldGenerator::
GenerateParsingCode(io::Printer * printer) const146 GenerateParsingCode(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
165 void MessageFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const166 GenerateSerializationCode(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
173 void MessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const174 GenerateSerializedSizeCode(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
GetBoxedType() const182 string MessageFieldGenerator::GetBoxedType() const {
183 return ClassName(descriptor_->message_type());
184 }
185
186 // ===================================================================
187
188 RepeatedMessageFieldGenerator::
RepeatedMessageFieldGenerator(const FieldDescriptor * descriptor)189 RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
190 : descriptor_(descriptor) {
191 SetMessageVariables(descriptor, &variables_);
192 }
193
~RepeatedMessageFieldGenerator()194 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
195
196 void RepeatedMessageFieldGenerator::
GenerateMembers(io::Printer * printer) const197 GenerateMembers(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
210 void RepeatedMessageFieldGenerator::
GenerateBuilderMembers(io::Printer * printer) const211 GenerateBuilderMembers(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
269 void RepeatedMessageFieldGenerator::
GenerateInitializationCode(io::Printer * printer) const270 GenerateInitializationCode(io::Printer* printer) const {
271 // Initialized inline.
272 }
273
274 void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer * printer) const275 GenerateMergingCode(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
285 void RepeatedMessageFieldGenerator::
GenerateBuildingCode(io::Printer * printer) const286 GenerateBuildingCode(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
294 void RepeatedMessageFieldGenerator::
GenerateParsingCode(io::Printer * printer) const295 GenerateParsingCode(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
311 void RepeatedMessageFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const312 GenerateSerializationCode(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
319 void RepeatedMessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const320 GenerateSerializedSizeCode(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
GetBoxedType() const328 string RepeatedMessageFieldGenerator::GetBoxedType() const {
329 return ClassName(descriptor_->message_type());
330 }
331
332 } // namespace java
333 } // namespace compiler
334 } // namespace protobuf
335 } // namespace google
336