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