Home | History | Annotate | Download | only in java
      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