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 <google/protobuf/compiler/java/java_extension.h> 36#include <google/protobuf/compiler/java/java_doc_comment.h> 37#include <google/protobuf/compiler/java/java_helpers.h> 38#include <google/protobuf/stubs/strutil.h> 39#include <google/protobuf/io/printer.h> 40 41namespace google { 42namespace protobuf { 43namespace compiler { 44namespace java { 45 46namespace { 47 48const char* TypeName(FieldDescriptor::Type field_type) { 49 switch (field_type) { 50 case FieldDescriptor::TYPE_INT32 : return "INT32"; 51 case FieldDescriptor::TYPE_UINT32 : return "UINT32"; 52 case FieldDescriptor::TYPE_SINT32 : return "SINT32"; 53 case FieldDescriptor::TYPE_FIXED32 : return "FIXED32"; 54 case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32"; 55 case FieldDescriptor::TYPE_INT64 : return "INT64"; 56 case FieldDescriptor::TYPE_UINT64 : return "UINT64"; 57 case FieldDescriptor::TYPE_SINT64 : return "SINT64"; 58 case FieldDescriptor::TYPE_FIXED64 : return "FIXED64"; 59 case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64"; 60 case FieldDescriptor::TYPE_FLOAT : return "FLOAT"; 61 case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE"; 62 case FieldDescriptor::TYPE_BOOL : return "BOOL"; 63 case FieldDescriptor::TYPE_STRING : return "STRING"; 64 case FieldDescriptor::TYPE_BYTES : return "BYTES"; 65 case FieldDescriptor::TYPE_ENUM : return "ENUM"; 66 case FieldDescriptor::TYPE_GROUP : return "GROUP"; 67 case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE"; 68 69 // No default because we want the compiler to complain if any new 70 // types are added. 71 } 72 73 GOOGLE_LOG(FATAL) << "Can't get here."; 74 return NULL; 75} 76 77} 78 79ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) 80 : descriptor_(descriptor) { 81 if (descriptor_->extension_scope() != NULL) { 82 scope_ = ClassName(descriptor_->extension_scope()); 83 } else { 84 scope_ = ClassName(descriptor_->file()); 85 } 86} 87 88ExtensionGenerator::~ExtensionGenerator() {} 89 90// Initializes the vars referenced in the generated code templates. 91void InitTemplateVars(const FieldDescriptor* descriptor, 92 const string& scope, 93 map<string, string>* vars_pointer) { 94 map<string, string> &vars = *vars_pointer; 95 vars["scope"] = scope; 96 vars["name"] = UnderscoresToCamelCase(descriptor); 97 vars["containing_type"] = ClassName(descriptor->containing_type()); 98 vars["number"] = SimpleItoa(descriptor->number()); 99 vars["constant_name"] = FieldConstantName(descriptor); 100 vars["index"] = SimpleItoa(descriptor->index()); 101 vars["default"] = 102 descriptor->is_repeated() ? "" : DefaultValue(descriptor); 103 vars["type_constant"] = TypeName(GetType(descriptor)); 104 vars["packed"] = descriptor->options().packed() ? "true" : "false"; 105 vars["enum_map"] = "null"; 106 vars["prototype"] = "null"; 107 108 JavaType java_type = GetJavaType(descriptor); 109 string singular_type; 110 switch (java_type) { 111 case JAVATYPE_MESSAGE: 112 singular_type = ClassName(descriptor->message_type()); 113 vars["prototype"] = singular_type + ".getDefaultInstance()"; 114 break; 115 case JAVATYPE_ENUM: 116 singular_type = ClassName(descriptor->enum_type()); 117 vars["enum_map"] = singular_type + ".internalGetValueMap()"; 118 break; 119 default: 120 singular_type = BoxedPrimitiveTypeName(java_type); 121 break; 122 } 123 vars["type"] = descriptor->is_repeated() ? 124 "java.util.List<" + singular_type + ">" : singular_type; 125 vars["singular_type"] = singular_type; 126} 127 128void ExtensionGenerator::Generate(io::Printer* printer) { 129 map<string, string> vars; 130 InitTemplateVars(descriptor_, scope_, &vars); 131 printer->Print(vars, 132 "public static final int $constant_name$ = $number$;\n"); 133 134 WriteFieldDocComment(printer, descriptor_); 135 if (HasDescriptorMethods(descriptor_->file())) { 136 // Non-lite extensions 137 if (descriptor_->extension_scope() == NULL) { 138 // Non-nested 139 printer->Print( 140 vars, 141 "public static final\n" 142 " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" 143 " $containing_type$,\n" 144 " $type$> $name$ = com.google.protobuf.GeneratedMessage\n" 145 " .newFileScopedGeneratedExtension(\n" 146 " $singular_type$.class,\n" 147 " $prototype$);\n"); 148 } else { 149 // Nested 150 printer->Print( 151 vars, 152 "public static final\n" 153 " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" 154 " $containing_type$,\n" 155 " $type$> $name$ = com.google.protobuf.GeneratedMessage\n" 156 " .newMessageScopedGeneratedExtension(\n" 157 " $scope$.getDefaultInstance(),\n" 158 " $index$,\n" 159 " $singular_type$.class,\n" 160 " $prototype$);\n"); 161 } 162 } else { 163 // Lite extensions 164 if (descriptor_->is_repeated()) { 165 printer->Print( 166 vars, 167 "public static final\n" 168 " com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n" 169 " $containing_type$,\n" 170 " $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n" 171 " .newRepeatedGeneratedExtension(\n" 172 " $containing_type$.getDefaultInstance(),\n" 173 " $prototype$,\n" 174 " $enum_map$,\n" 175 " $number$,\n" 176 " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" 177 " $packed$);\n"); 178 } else { 179 printer->Print( 180 vars, 181 "public static final\n" 182 " com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n" 183 " $containing_type$,\n" 184 " $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n" 185 " .newSingularGeneratedExtension(\n" 186 " $containing_type$.getDefaultInstance(),\n" 187 " $default$,\n" 188 " $prototype$,\n" 189 " $enum_map$,\n" 190 " $number$,\n" 191 " com.google.protobuf.WireFormat.FieldType.$type_constant$);\n"); 192 } 193 } 194} 195 196void ExtensionGenerator::GenerateNonNestedInitializationCode( 197 io::Printer* printer) { 198 if (descriptor_->extension_scope() == NULL && 199 HasDescriptorMethods(descriptor_->file())) { 200 // Only applies to non-nested, non-lite extensions. 201 printer->Print( 202 "$name$.internalInit(descriptor.getExtensions().get($index$));\n", 203 "name", UnderscoresToCamelCase(descriptor_), 204 "index", SimpleItoa(descriptor_->index())); 205 } 206} 207 208void ExtensionGenerator::GenerateRegistrationCode(io::Printer* printer) { 209 printer->Print( 210 "registry.add($scope$.$name$);\n", 211 "scope", scope_, 212 "name", UnderscoresToCamelCase(descriptor_)); 213} 214 215} // namespace java 216} // namespace compiler 217} // namespace protobuf 218} // namespace google 219