1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 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_context.h> 39 #include <google/protobuf/compiler/java/java_enum_lite.h> 40 #include <google/protobuf/compiler/java/java_doc_comment.h> 41 #include <google/protobuf/compiler/java/java_helpers.h> 42 #include <google/protobuf/compiler/java/java_name_resolver.h> 43 #include <google/protobuf/io/printer.h> 44 #include <google/protobuf/descriptor.pb.h> 45 #include <google/protobuf/stubs/strutil.h> 46 47 namespace google { 48 namespace protobuf { 49 namespace compiler { 50 namespace java { 51 52 namespace { 53 bool EnumHasCustomOptions(const EnumDescriptor* descriptor) { 54 if (descriptor->options().unknown_fields().field_count() > 0) return true; 55 for (int i = 0; i < descriptor->value_count(); ++i) { 56 const EnumValueDescriptor* value = descriptor->value(i); 57 if (value->options().unknown_fields().field_count() > 0) return true; 58 } 59 return false; 60 } 61 } // namespace 62 63 EnumLiteGenerator::EnumLiteGenerator(const EnumDescriptor* descriptor, 64 bool immutable_api, 65 Context* context) 66 : descriptor_(descriptor), immutable_api_(immutable_api), 67 name_resolver_(context->GetNameResolver()) { 68 for (int i = 0; i < descriptor_->value_count(); i++) { 69 const EnumValueDescriptor* value = descriptor_->value(i); 70 const EnumValueDescriptor* canonical_value = 71 descriptor_->FindValueByNumber(value->number()); 72 73 if (value == canonical_value) { 74 canonical_values_.push_back(value); 75 } else { 76 Alias alias; 77 alias.value = value; 78 alias.canonical_value = canonical_value; 79 aliases_.push_back(alias); 80 } 81 } 82 } 83 84 EnumLiteGenerator::~EnumLiteGenerator() {} 85 86 void EnumLiteGenerator::Generate(io::Printer* printer) { 87 WriteEnumDocComment(printer, descriptor_); 88 printer->Print( 89 "public enum $classname$\n" 90 " implements com.google.protobuf.Internal.EnumLite {\n", 91 "classname", descriptor_->name()); 92 printer->Indent(); 93 94 for (int i = 0; i < canonical_values_.size(); i++) { 95 map<string, string> vars; 96 vars["name"] = canonical_values_[i]->name(); 97 vars["number"] = SimpleItoa(canonical_values_[i]->number()); 98 WriteEnumValueDocComment(printer, canonical_values_[i]); 99 if (canonical_values_[i]->options().deprecated()) { 100 printer->Print("@java.lang.Deprecated\n"); 101 } 102 printer->Print(vars, 103 "$name$($number$),\n"); 104 } 105 106 if (SupportUnknownEnumValue(descriptor_->file())) { 107 printer->Print("UNRECOGNIZED(-1),\n"); 108 } 109 110 printer->Print( 111 ";\n" 112 "\n"); 113 114 // ----------------------------------------------------------------- 115 116 for (int i = 0; i < aliases_.size(); i++) { 117 map<string, string> vars; 118 vars["classname"] = descriptor_->name(); 119 vars["name"] = aliases_[i].value->name(); 120 vars["canonical_name"] = aliases_[i].canonical_value->name(); 121 WriteEnumValueDocComment(printer, aliases_[i].value); 122 printer->Print(vars, 123 "public static final $classname$ $name$ = $canonical_name$;\n"); 124 } 125 126 for (int i = 0; i < descriptor_->value_count(); i++) { 127 map<string, string> vars; 128 vars["name"] = descriptor_->value(i)->name(); 129 vars["number"] = SimpleItoa(descriptor_->value(i)->number()); 130 WriteEnumValueDocComment(printer, descriptor_->value(i)); 131 printer->Print(vars, 132 "public static final int $name$_VALUE = $number$;\n"); 133 } 134 printer->Print("\n"); 135 136 // ----------------------------------------------------------------- 137 138 printer->Print( 139 "\n" 140 "public final int getNumber() {\n" 141 " return value;\n" 142 "}\n" 143 "\n" 144 "/**\n" 145 " * @deprecated Use {@link #forNumber(int)} instead.\n" 146 " */\n" 147 "@java.lang.Deprecated\n" 148 "public static $classname$ valueOf(int value) {\n" 149 " return forNumber(value);\n" 150 "}\n" 151 "\n" 152 "public static $classname$ forNumber(int value) {\n" 153 " switch (value) {\n", 154 "classname", descriptor_->name()); 155 printer->Indent(); 156 printer->Indent(); 157 158 for (int i = 0; i < canonical_values_.size(); i++) { 159 printer->Print( 160 "case $number$: return $name$;\n", 161 "name", canonical_values_[i]->name(), 162 "number", SimpleItoa(canonical_values_[i]->number())); 163 } 164 165 printer->Outdent(); 166 printer->Outdent(); 167 printer->Print( 168 " default: return null;\n" 169 " }\n" 170 "}\n" 171 "\n" 172 "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" 173 " internalGetValueMap() {\n" 174 " return internalValueMap;\n" 175 "}\n" 176 "private static final com.google.protobuf.Internal.EnumLiteMap<\n" 177 " $classname$> internalValueMap =\n" 178 " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" 179 " public $classname$ findValueByNumber(int number) {\n" 180 " return $classname$.forNumber(number);\n" 181 " }\n" 182 " };\n" 183 "\n", 184 "classname", descriptor_->name()); 185 186 printer->Print( 187 "private final int value;\n\n" 188 "private $classname$(int value) {\n", 189 "classname", descriptor_->name()); 190 printer->Print( 191 " this.value = value;\n" 192 "}\n"); 193 194 printer->Print( 195 "\n" 196 "// @@protoc_insertion_point(enum_scope:$full_name$)\n", 197 "full_name", descriptor_->full_name()); 198 199 printer->Outdent(); 200 printer->Print("}\n\n"); 201 } 202 203 bool EnumLiteGenerator::CanUseEnumValues() { 204 if (canonical_values_.size() != descriptor_->value_count()) { 205 return false; 206 } 207 for (int i = 0; i < descriptor_->value_count(); i++) { 208 if (descriptor_->value(i)->name() != canonical_values_[i]->name()) { 209 return false; 210 } 211 } 212 return true; 213 } 214 215 } // namespace java 216 } // namespace compiler 217 } // namespace protobuf 218 } // namespace google 219