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 <google/protobuf/compiler/java/java_extension.h> 36 37 #include <google/protobuf/compiler/java/java_context.h> 38 #include <google/protobuf/compiler/java/java_doc_comment.h> 39 #include <google/protobuf/compiler/java/java_helpers.h> 40 #include <google/protobuf/compiler/java/java_name_resolver.h> 41 #include <google/protobuf/io/printer.h> 42 #include <google/protobuf/stubs/strutil.h> 43 44 namespace google { 45 namespace protobuf { 46 namespace compiler { 47 namespace java { 48 49 ImmutableExtensionGenerator::ImmutableExtensionGenerator( 50 const FieldDescriptor* descriptor, Context* context) 51 : descriptor_(descriptor), context_(context), 52 name_resolver_(context->GetNameResolver()) { 53 if (descriptor_->extension_scope() != NULL) { 54 scope_ = name_resolver_->GetImmutableClassName( 55 descriptor_->extension_scope()); 56 } else { 57 scope_ = name_resolver_->GetImmutableClassName(descriptor_->file()); 58 } 59 } 60 61 ImmutableExtensionGenerator::~ImmutableExtensionGenerator() {} 62 63 // Initializes the vars referenced in the generated code templates. 64 void ExtensionGenerator::InitTemplateVars(const FieldDescriptor* descriptor, 65 const string& scope, 66 bool immutable, 67 ClassNameResolver* name_resolver, 68 map<string, string>* vars_pointer) { 69 map<string, string> &vars = *vars_pointer; 70 vars["scope"] = scope; 71 vars["name"] = UnderscoresToCamelCase(descriptor); 72 vars["containing_type"] = 73 name_resolver->GetClassName(descriptor->containing_type(), immutable); 74 vars["number"] = SimpleItoa(descriptor->number()); 75 vars["constant_name"] = FieldConstantName(descriptor); 76 vars["index"] = SimpleItoa(descriptor->index()); 77 vars["default"] = descriptor->is_repeated() ? 78 "" : DefaultValue(descriptor, immutable, name_resolver); 79 vars["type_constant"] = FieldTypeName(GetType(descriptor)); 80 vars["packed"] = descriptor->options().packed() ? "true" : "false"; 81 vars["enum_map"] = "null"; 82 vars["prototype"] = "null"; 83 84 JavaType java_type = GetJavaType(descriptor); 85 string singular_type; 86 switch (java_type) { 87 case JAVATYPE_MESSAGE: 88 singular_type = name_resolver->GetClassName(descriptor->message_type(), 89 immutable); 90 vars["prototype"] = singular_type + ".getDefaultInstance()"; 91 break; 92 case JAVATYPE_ENUM: 93 singular_type = name_resolver->GetClassName(descriptor->enum_type(), 94 immutable); 95 vars["enum_map"] = singular_type + ".internalGetValueMap()"; 96 break; 97 case JAVATYPE_STRING: 98 singular_type = "java.lang.String"; 99 break; 100 case JAVATYPE_BYTES: 101 singular_type = immutable ? "com.google.protobuf.ByteString" : "byte[]"; 102 break; 103 default: 104 singular_type = BoxedPrimitiveTypeName(java_type); 105 break; 106 } 107 vars["type"] = descriptor->is_repeated() ? 108 "java.util.List<" + singular_type + ">" : singular_type; 109 vars["singular_type"] = singular_type; 110 } 111 112 void ImmutableExtensionGenerator::Generate(io::Printer* printer) { 113 map<string, string> vars; 114 const bool kUseImmutableNames = true; 115 InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_, 116 &vars); 117 printer->Print(vars, 118 "public static final int $constant_name$ = $number$;\n"); 119 120 WriteFieldDocComment(printer, descriptor_); 121 if (descriptor_->extension_scope() == NULL) { 122 // Non-nested 123 printer->Print( 124 vars, 125 "public static final\n" 126 " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" 127 " $containing_type$,\n" 128 " $type$> $name$ = com.google.protobuf.GeneratedMessage\n" 129 " .newFileScopedGeneratedExtension(\n" 130 " $singular_type$.class,\n" 131 " $prototype$);\n"); 132 } else { 133 // Nested 134 printer->Print( 135 vars, 136 "public static final\n" 137 " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" 138 " $containing_type$,\n" 139 " $type$> $name$ = com.google.protobuf.GeneratedMessage\n" 140 " .newMessageScopedGeneratedExtension(\n" 141 " $scope$.getDefaultInstance(),\n" 142 " $index$,\n" 143 " $singular_type$.class,\n" 144 " $prototype$);\n"); 145 } 146 } 147 148 int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode( 149 io::Printer* printer) { 150 int bytecode_estimate = 0; 151 if (descriptor_->extension_scope() == NULL) { 152 // Only applies to non-nested extensions. 153 printer->Print( 154 "$name$.internalInit(descriptor.getExtensions().get($index$));\n", 155 "name", UnderscoresToCamelCase(descriptor_), 156 "index", SimpleItoa(descriptor_->index())); 157 bytecode_estimate += 21; 158 } 159 return bytecode_estimate; 160 } 161 162 int ImmutableExtensionGenerator::GenerateRegistrationCode( 163 io::Printer* printer) { 164 printer->Print( 165 "registry.add($scope$.$name$);\n", 166 "scope", scope_, 167 "name", UnderscoresToCamelCase(descriptor_)); 168 return 7; 169 } 170 171 } // namespace java 172 } // namespace compiler 173 } // namespace protobuf 174 } // namespace google 175