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 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ 36 #define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ 37 38 #include <string> 39 #include <google/protobuf/descriptor.pb.h> 40 #include <google/protobuf/descriptor.h> 41 42 namespace google { 43 namespace protobuf { 44 namespace compiler { 45 namespace java { 46 47 // Commonly-used separator comments. Thick is a line of '=', thin is a line 48 // of '-'. 49 extern const char kThickSeparator[]; 50 extern const char kThinSeparator[]; 51 52 // Converts a name to camel-case. If cap_first_letter is true, capitalize the 53 // first letter. 54 string UnderscoresToCamelCase(const string& name, bool cap_first_letter); 55 // Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes 56 // "fooBarBaz" or "FooBarBaz", respectively. 57 string UnderscoresToCamelCase(const FieldDescriptor* field); 58 string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); 59 60 // Similar, but for method names. (Typically, this merely has the effect 61 // of lower-casing the first letter of the name.) 62 string UnderscoresToCamelCase(const MethodDescriptor* method); 63 64 // Get an identifier that uniquely identifies this type within the file. 65 // This is used to declare static variables related to this type at the 66 // outermost file scope. 67 string UniqueFileScopeIdentifier(const Descriptor* descriptor); 68 69 // Strips ".proto" or ".protodevel" from the end of a filename. 70 string StripProto(const string& filename); 71 72 // Gets the unqualified class name for the file. For each .proto file, there 73 // will be one Java class containing all the immutable messages and another 74 // Java class containing all the mutable messages. 75 // TODO(xiaofeng): remove the default value after updating client code. 76 string FileClassName(const FileDescriptor* file, bool immutable = true); 77 78 // Returns the file's Java package name. 79 string FileJavaPackage(const FileDescriptor* file, bool immutable = true); 80 81 // Returns output directory for the given package name. 82 string JavaPackageToDir(string package_name); 83 84 // Converts the given fully-qualified name in the proto namespace to its 85 // fully-qualified name in the Java namespace, given that it is in the given 86 // file. 87 // TODO(xiaofeng): this method is deprecated and should be removed in the 88 // future. 89 string ToJavaName(const string& full_name, 90 const FileDescriptor* file); 91 92 // TODO(xiaofeng): the following methods are kept for they are exposed 93 // publicly in //google/protobuf/compiler/java/names.h. They return 94 // immutable names only and should be removed after mutable API is 95 // integrated into google3. 96 string ClassName(const Descriptor* descriptor); 97 string ClassName(const EnumDescriptor* descriptor); 98 string ClassName(const ServiceDescriptor* descriptor); 99 string ClassName(const FileDescriptor* descriptor); 100 101 // Comma-separate list of option-specified interfaces implemented by the 102 // Message, to follow the "implements" declaration of the Message definition. 103 string ExtraMessageInterfaces(const Descriptor* descriptor); 104 // Comma-separate list of option-specified interfaces implemented by the 105 // MutableMessage, to follow the "implements" declaration of the MutableMessage 106 // definition. 107 string ExtraMutableMessageInterfaces(const Descriptor* descriptor); 108 // Comma-separate list of option-specified interfaces implemented by the 109 // Builder, to follow the "implements" declaration of the Builder definition. 110 string ExtraBuilderInterfaces(const Descriptor* descriptor); 111 // Comma-separate list of option-specified interfaces extended by the 112 // MessageOrBuilder, to follow the "extends" declaration of the 113 // MessageOrBuilder definition. 114 string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor); 115 116 // Get the unqualified Java class name for mutable messages. i.e. without 117 // package or outer classnames. 118 inline string ShortMutableJavaClassName(const Descriptor* descriptor) { 119 return descriptor->name(); 120 } 121 122 123 // Whether we should generate multiple java files for messages. 124 inline bool MultipleJavaFiles( 125 const FileDescriptor* descriptor, bool immutable) { 126 return descriptor->options().java_multiple_files(); 127 } 128 129 // Get the unqualified name that should be used for a field's field 130 // number constant. 131 string FieldConstantName(const FieldDescriptor *field); 132 133 // Returns the type of the FieldDescriptor. 134 // This does nothing interesting for the open source release, but is used for 135 // hacks that improve compatibility with version 1 protocol buffers at Google. 136 FieldDescriptor::Type GetType(const FieldDescriptor* field); 137 138 enum JavaType { 139 JAVATYPE_INT, 140 JAVATYPE_LONG, 141 JAVATYPE_FLOAT, 142 JAVATYPE_DOUBLE, 143 JAVATYPE_BOOLEAN, 144 JAVATYPE_STRING, 145 JAVATYPE_BYTES, 146 JAVATYPE_ENUM, 147 JAVATYPE_MESSAGE 148 }; 149 150 JavaType GetJavaType(const FieldDescriptor* field); 151 152 const char* PrimitiveTypeName(JavaType type); 153 154 // Get the fully-qualified class name for a boxed primitive type, e.g. 155 // "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message 156 // types. 157 const char* BoxedPrimitiveTypeName(JavaType type); 158 159 // Get the name of the java enum constant representing this type. E.g., 160 // "INT32" for FieldDescriptor::TYPE_INT32. The enum constant's full 161 // name is "com.google.protobuf.WireFormat.FieldType.INT32". 162 const char* FieldTypeName(const FieldDescriptor::Type field_type); 163 164 class ClassNameResolver; 165 string DefaultValue(const FieldDescriptor* field, bool immutable, 166 ClassNameResolver* name_resolver); 167 inline string ImmutableDefaultValue(const FieldDescriptor* field, 168 ClassNameResolver* name_resolver) { 169 return DefaultValue(field, true, name_resolver); 170 } 171 bool IsDefaultValueJavaDefault(const FieldDescriptor* field); 172 173 // Does this message have specialized equals() and hashCode() methods? 174 inline bool HasEqualsAndHashCode(const Descriptor* descriptor) { 175 return descriptor->file()->options().java_generate_equals_and_hash(); 176 } 177 178 // Does this message class have descriptor and reflection methods? 179 inline bool HasDescriptorMethods(const Descriptor* descriptor, 180 bool enforce_lite) { 181 return !enforce_lite && 182 descriptor->file()->options().optimize_for() != 183 FileOptions::LITE_RUNTIME; 184 } 185 inline bool HasDescriptorMethods(const EnumDescriptor* descriptor, 186 bool enforce_lite) { 187 return !enforce_lite && 188 descriptor->file()->options().optimize_for() != 189 FileOptions::LITE_RUNTIME; 190 } 191 inline bool HasDescriptorMethods(const FileDescriptor* descriptor, 192 bool enforce_lite) { 193 return !enforce_lite && 194 descriptor->options().optimize_for() != FileOptions::LITE_RUNTIME; 195 } 196 197 // Should we generate generic services for this file? 198 inline bool HasGenericServices(const FileDescriptor *file, bool enforce_lite) { 199 return file->service_count() > 0 && 200 HasDescriptorMethods(file, enforce_lite) && 201 file->options().java_generic_services(); 202 } 203 204 inline bool IsLazy(const FieldDescriptor* descriptor, bool enforce_lite) { 205 // Currently, the proto-lite version suports lazy field. 206 // TODO(niwasaki): Support lazy fields also for other proto runtimes. 207 if (HasDescriptorMethods(descriptor->file(), enforce_lite)) { 208 return false; 209 } 210 return descriptor->options().lazy(); 211 } 212 213 // Methods for shared bitfields. 214 215 // Gets the name of the shared bitfield for the given index. 216 string GetBitFieldName(int index); 217 218 // Gets the name of the shared bitfield for the given bit index. 219 // Effectively, GetBitFieldName(bitIndex / 32) 220 string GetBitFieldNameForBit(int bitIndex); 221 222 // Generates the java code for the expression that returns the boolean value 223 // of the bit of the shared bitfields for the given bit index. 224 // Example: "((bitField1_ & 0x04) == 0x04)" 225 string GenerateGetBit(int bitIndex); 226 227 // Generates the java code for the expression that sets the bit of the shared 228 // bitfields for the given bit index. 229 // Example: "bitField1_ = (bitField1_ | 0x04)" 230 string GenerateSetBit(int bitIndex); 231 232 // Generates the java code for the expression that clears the bit of the shared 233 // bitfields for the given bit index. 234 // Example: "bitField1_ = (bitField1_ & ~0x04)" 235 string GenerateClearBit(int bitIndex); 236 237 // Does the same as GenerateGetBit but operates on the bit field on a local 238 // variable. This is used by the builder to copy the value in the builder to 239 // the message. 240 // Example: "((from_bitField1_ & 0x04) == 0x04)" 241 string GenerateGetBitFromLocal(int bitIndex); 242 243 // Does the same as GenerateSetBit but operates on the bit field on a local 244 // variable. This is used by the builder to copy the value in the builder to 245 // the message. 246 // Example: "to_bitField1_ = (to_bitField1_ | 0x04)" 247 string GenerateSetBitToLocal(int bitIndex); 248 249 // Does the same as GenerateGetBit but operates on the bit field on a local 250 // variable. This is used by the parsing constructor to record if a repeated 251 // field is mutable. 252 // Example: "((mutable_bitField1_ & 0x04) == 0x04)" 253 string GenerateGetBitMutableLocal(int bitIndex); 254 255 // Does the same as GenerateSetBit but operates on the bit field on a local 256 // variable. This is used by the parsing constructor to record if a repeated 257 // field is mutable. 258 // Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)" 259 string GenerateSetBitMutableLocal(int bitIndex); 260 261 // Returns whether the JavaType is a reference type. 262 bool IsReferenceType(JavaType type); 263 264 // Returns the capitalized name for calling relative functions in 265 // CodedInputStream 266 const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable); 267 268 // For encodings with fixed sizes, returns that size in bytes. Otherwise 269 // returns -1. 270 int FixedSize(FieldDescriptor::Type type); 271 272 // Comparators used to sort fields in MessageGenerator 273 struct FieldOrderingByNumber { 274 inline bool operator()(const FieldDescriptor* a, 275 const FieldDescriptor* b) const { 276 return a->number() < b->number(); 277 } 278 }; 279 280 struct ExtensionRangeOrdering { 281 bool operator()(const Descriptor::ExtensionRange* a, 282 const Descriptor::ExtensionRange* b) const { 283 return a->start < b->start; 284 } 285 }; 286 287 // Sort the fields of the given Descriptor by number into a new[]'d array 288 // and return it. The caller should delete the returned array. 289 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor); 290 291 // Does this message class have any packed fields? 292 inline bool HasPackedFields(const Descriptor* descriptor) { 293 for (int i = 0; i < descriptor->field_count(); i++) { 294 if (descriptor->field(i)->is_packed()) { 295 return true; 296 } 297 } 298 return false; 299 } 300 301 // Check a message type and its sub-message types recursively to see if any of 302 // them has a required field. Return true if a required field is found. 303 bool HasRequiredFields(const Descriptor* descriptor); 304 305 // Whether a .proto file supports field presence test for non-message types. 306 inline bool SupportFieldPresence(const FileDescriptor* descriptor) { 307 return descriptor->syntax() != FileDescriptor::SYNTAX_PROTO3; 308 } 309 310 // Whether generate classes expose public PARSER instances. 311 inline bool ExposePublicParser(const FileDescriptor* descriptor) { 312 // TODO(liujisi): Mark the PARSER private in 3.1.x releases. 313 return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2; 314 } 315 316 // Whether unknown enum values are kept (i.e., not stored in UnknownFieldSet 317 // but in the message and can be queried using additional getters that return 318 // ints. 319 inline bool SupportUnknownEnumValue(const FileDescriptor* descriptor) { 320 return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3; 321 } 322 323 // Check whether a mesasge has repeated fields. 324 bool HasRepeatedFields(const Descriptor* descriptor); 325 326 inline bool IsMapEntry(const Descriptor* descriptor) { 327 return descriptor->options().map_entry(); 328 } 329 330 inline bool IsMapField(const FieldDescriptor* descriptor) { 331 return descriptor->is_map(); 332 } 333 334 inline bool PreserveUnknownFields(const Descriptor* descriptor) { 335 return descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3; 336 } 337 338 inline bool IsAnyMessage(const Descriptor* descriptor) { 339 return descriptor->full_name() == "google.protobuf.Any"; 340 } 341 342 inline bool CheckUtf8(const FieldDescriptor* descriptor) { 343 return descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 || 344 descriptor->file()->options().java_string_check_utf8(); 345 } 346 347 } // namespace java 348 } // namespace compiler 349 } // namespace protobuf 350 351 } // namespace google 352 #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ 353