| OLD | NEW |
| (Empty) |
| 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_enum.h> | |
| 39 #include <google/protobuf/compiler/java/java_doc_comment.h> | |
| 40 #include <google/protobuf/compiler/java/java_helpers.h> | |
| 41 #include <google/protobuf/io/printer.h> | |
| 42 #include <google/protobuf/descriptor.pb.h> | |
| 43 #include <google/protobuf/stubs/strutil.h> | |
| 44 | |
| 45 namespace google { | |
| 46 namespace protobuf { | |
| 47 namespace compiler { | |
| 48 namespace java { | |
| 49 | |
| 50 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) | |
| 51 : descriptor_(descriptor) { | |
| 52 for (int i = 0; i < descriptor_->value_count(); i++) { | |
| 53 const EnumValueDescriptor* value = descriptor_->value(i); | |
| 54 const EnumValueDescriptor* canonical_value = | |
| 55 descriptor_->FindValueByNumber(value->number()); | |
| 56 | |
| 57 if (value == canonical_value) { | |
| 58 canonical_values_.push_back(value); | |
| 59 } else { | |
| 60 Alias alias; | |
| 61 alias.value = value; | |
| 62 alias.canonical_value = canonical_value; | |
| 63 aliases_.push_back(alias); | |
| 64 } | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 EnumGenerator::~EnumGenerator() {} | |
| 69 | |
| 70 void EnumGenerator::Generate(io::Printer* printer) { | |
| 71 WriteEnumDocComment(printer, descriptor_); | |
| 72 if (HasDescriptorMethods(descriptor_)) { | |
| 73 printer->Print( | |
| 74 "public enum $classname$\n" | |
| 75 " implements com.google.protobuf.ProtocolMessageEnum {\n", | |
| 76 "classname", descriptor_->name()); | |
| 77 } else { | |
| 78 printer->Print( | |
| 79 "public enum $classname$\n" | |
| 80 " implements com.google.protobuf.Internal.EnumLite {\n", | |
| 81 "classname", descriptor_->name()); | |
| 82 } | |
| 83 printer->Indent(); | |
| 84 | |
| 85 for (int i = 0; i < canonical_values_.size(); i++) { | |
| 86 map<string, string> vars; | |
| 87 vars["name"] = canonical_values_[i]->name(); | |
| 88 vars["index"] = SimpleItoa(canonical_values_[i]->index()); | |
| 89 vars["number"] = SimpleItoa(canonical_values_[i]->number()); | |
| 90 WriteEnumValueDocComment(printer, canonical_values_[i]); | |
| 91 printer->Print(vars, | |
| 92 "$name$($index$, $number$),\n"); | |
| 93 } | |
| 94 | |
| 95 printer->Print( | |
| 96 ";\n" | |
| 97 "\n"); | |
| 98 | |
| 99 // ----------------------------------------------------------------- | |
| 100 | |
| 101 for (int i = 0; i < aliases_.size(); i++) { | |
| 102 map<string, string> vars; | |
| 103 vars["classname"] = descriptor_->name(); | |
| 104 vars["name"] = aliases_[i].value->name(); | |
| 105 vars["canonical_name"] = aliases_[i].canonical_value->name(); | |
| 106 WriteEnumValueDocComment(printer, aliases_[i].value); | |
| 107 printer->Print(vars, | |
| 108 "public static final $classname$ $name$ = $canonical_name$;\n"); | |
| 109 } | |
| 110 | |
| 111 for (int i = 0; i < descriptor_->value_count(); i++) { | |
| 112 map<string, string> vars; | |
| 113 vars["name"] = descriptor_->value(i)->name(); | |
| 114 vars["number"] = SimpleItoa(descriptor_->value(i)->number()); | |
| 115 WriteEnumValueDocComment(printer, descriptor_->value(i)); | |
| 116 printer->Print(vars, | |
| 117 "public static final int $name$_VALUE = $number$;\n"); | |
| 118 } | |
| 119 printer->Print("\n"); | |
| 120 | |
| 121 // ----------------------------------------------------------------- | |
| 122 | |
| 123 printer->Print( | |
| 124 "\n" | |
| 125 "public final int getNumber() { return value; }\n" | |
| 126 "\n" | |
| 127 "public static $classname$ valueOf(int value) {\n" | |
| 128 " switch (value) {\n", | |
| 129 "classname", descriptor_->name()); | |
| 130 printer->Indent(); | |
| 131 printer->Indent(); | |
| 132 | |
| 133 for (int i = 0; i < canonical_values_.size(); i++) { | |
| 134 printer->Print( | |
| 135 "case $number$: return $name$;\n", | |
| 136 "name", canonical_values_[i]->name(), | |
| 137 "number", SimpleItoa(canonical_values_[i]->number())); | |
| 138 } | |
| 139 | |
| 140 printer->Outdent(); | |
| 141 printer->Outdent(); | |
| 142 printer->Print( | |
| 143 " default: return null;\n" | |
| 144 " }\n" | |
| 145 "}\n" | |
| 146 "\n" | |
| 147 "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" | |
| 148 " internalGetValueMap() {\n" | |
| 149 " return internalValueMap;\n" | |
| 150 "}\n" | |
| 151 "private static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" | |
| 152 " internalValueMap =\n" | |
| 153 " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" | |
| 154 " public $classname$ findValueByNumber(int number) {\n" | |
| 155 " return $classname$.valueOf(number);\n" | |
| 156 " }\n" | |
| 157 " };\n" | |
| 158 "\n", | |
| 159 "classname", descriptor_->name()); | |
| 160 | |
| 161 // ----------------------------------------------------------------- | |
| 162 // Reflection | |
| 163 | |
| 164 if (HasDescriptorMethods(descriptor_)) { | |
| 165 printer->Print( | |
| 166 "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n" | |
| 167 " getValueDescriptor() {\n" | |
| 168 " return getDescriptor().getValues().get(index);\n" | |
| 169 "}\n" | |
| 170 "public final com.google.protobuf.Descriptors.EnumDescriptor\n" | |
| 171 " getDescriptorForType() {\n" | |
| 172 " return getDescriptor();\n" | |
| 173 "}\n" | |
| 174 "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" | |
| 175 " getDescriptor() {\n"); | |
| 176 | |
| 177 // TODO(kenton): Cache statically? Note that we can't access descriptors | |
| 178 // at module init time because it wouldn't work with descriptor.proto, but | |
| 179 // we can cache the value the first time getDescriptor() is called. | |
| 180 if (descriptor_->containing_type() == NULL) { | |
| 181 printer->Print( | |
| 182 " return $file$.getDescriptor().getEnumTypes().get($index$);\n", | |
| 183 "file", ClassName(descriptor_->file()), | |
| 184 "index", SimpleItoa(descriptor_->index())); | |
| 185 } else { | |
| 186 printer->Print( | |
| 187 " return $parent$.getDescriptor().getEnumTypes().get($index$);\n", | |
| 188 "parent", ClassName(descriptor_->containing_type()), | |
| 189 "index", SimpleItoa(descriptor_->index())); | |
| 190 } | |
| 191 | |
| 192 printer->Print( | |
| 193 "}\n" | |
| 194 "\n" | |
| 195 "private static final $classname$[] VALUES = ", | |
| 196 "classname", descriptor_->name()); | |
| 197 | |
| 198 if (CanUseEnumValues()) { | |
| 199 // If the constants we are going to output are exactly the ones we | |
| 200 // have declared in the Java enum in the same order, then we can use | |
| 201 // the values() method that the Java compiler automatically generates | |
| 202 // for every enum. | |
| 203 printer->Print("values();\n"); | |
| 204 } else { | |
| 205 printer->Print( | |
| 206 "{\n" | |
| 207 " "); | |
| 208 for (int i = 0; i < descriptor_->value_count(); i++) { | |
| 209 printer->Print("$name$, ", | |
| 210 "name", descriptor_->value(i)->name()); | |
| 211 } | |
| 212 printer->Print( | |
| 213 "\n" | |
| 214 "};\n"); | |
| 215 } | |
| 216 | |
| 217 printer->Print( | |
| 218 "\n" | |
| 219 "public static $classname$ valueOf(\n" | |
| 220 " com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n" | |
| 221 " if (desc.getType() != getDescriptor()) {\n" | |
| 222 " throw new java.lang.IllegalArgumentException(\n" | |
| 223 " \"EnumValueDescriptor is not for this type.\");\n" | |
| 224 " }\n" | |
| 225 " return VALUES[desc.getIndex()];\n" | |
| 226 "}\n" | |
| 227 "\n", | |
| 228 "classname", descriptor_->name()); | |
| 229 | |
| 230 // index is only used for reflection; lite implementation does not need it | |
| 231 printer->Print("private final int index;\n"); | |
| 232 } | |
| 233 | |
| 234 // ----------------------------------------------------------------- | |
| 235 | |
| 236 printer->Print( | |
| 237 "private final int value;\n\n" | |
| 238 "private $classname$(int index, int value) {\n", | |
| 239 "classname", descriptor_->name()); | |
| 240 if (HasDescriptorMethods(descriptor_)) { | |
| 241 printer->Print(" this.index = index;\n"); | |
| 242 } | |
| 243 printer->Print( | |
| 244 " this.value = value;\n" | |
| 245 "}\n"); | |
| 246 | |
| 247 printer->Print( | |
| 248 "\n" | |
| 249 "// @@protoc_insertion_point(enum_scope:$full_name$)\n", | |
| 250 "full_name", descriptor_->full_name()); | |
| 251 | |
| 252 printer->Outdent(); | |
| 253 printer->Print("}\n\n"); | |
| 254 } | |
| 255 | |
| 256 bool EnumGenerator::CanUseEnumValues() { | |
| 257 if (canonical_values_.size() != descriptor_->value_count()) { | |
| 258 return false; | |
| 259 } | |
| 260 for (int i = 0; i < descriptor_->value_count(); i++) { | |
| 261 if (descriptor_->value(i)->name() != canonical_values_[i]->name()) { | |
| 262 return false; | |
| 263 } | |
| 264 } | |
| 265 return true; | |
| 266 } | |
| 267 | |
| 268 } // namespace java | |
| 269 } // namespace compiler | |
| 270 } // namespace protobuf | |
| 271 } // namespace google | |
| OLD | NEW |