• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
44 namespace google {
45 namespace protobuf {
46 namespace compiler {
47 namespace javamicro {
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 Params & params,const FieldDescriptor * descriptor,map<string,string> * variables)53 void 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 
72 MessageFieldGenerator::
MessageFieldGenerator(const FieldDescriptor * descriptor,const Params & params)73 MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
74   : FieldGenerator(params), descriptor_(descriptor) {
75   SetMessageVariables(params, descriptor, &variables_);
76 }
77 
~MessageFieldGenerator()78 MessageFieldGenerator::~MessageFieldGenerator() {}
79 
80 void MessageFieldGenerator::
GenerateMembers(io::Printer * printer) const81 GenerateMembers(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 
105 void MessageFieldGenerator::
GenerateMergingCode(io::Printer * printer) const106 GenerateMergingCode(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 
113 void MessageFieldGenerator::
GenerateParsingCode(io::Printer * printer) const114 GenerateParsingCode(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 
130 void MessageFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const131 GenerateSerializationCode(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 
138 void MessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const139 GenerateSerializedSizeCode(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 
GetBoxedType() const147 string MessageFieldGenerator::GetBoxedType() const {
148   return ClassName(params_, descriptor_->message_type());
149 }
150 
151 // ===================================================================
152 
153 RepeatedMessageFieldGenerator::
RepeatedMessageFieldGenerator(const FieldDescriptor * descriptor,const Params & params)154 RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
155   : FieldGenerator(params), descriptor_(descriptor) {
156   SetMessageVariables(params, descriptor, &variables_);
157 }
158 
~RepeatedMessageFieldGenerator()159 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
160 
161 void RepeatedMessageFieldGenerator::
GenerateMembers(io::Printer * printer) const162 GenerateMembers(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 
226 void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer * printer) const227 GenerateMergingCode(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 
246 void RepeatedMessageFieldGenerator::
GenerateParsingCode(io::Printer * printer) const247 GenerateParsingCode(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 
263 void RepeatedMessageFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const264 GenerateSerializationCode(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 
278 void RepeatedMessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const279 GenerateSerializedSizeCode(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 
GetBoxedType() const295 string 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