1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format 2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc. All rights reserved. 3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// http://code.google.com/p/protobuf/ 4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without 6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are 7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met: 8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Redistributions of source code must retain the above copyright 10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer. 11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Redistributions in binary form must reproduce the above 12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer 13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the 14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution. 15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Neither the name of Google Inc. nor the names of its 16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from 17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission. 18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillepackage com.google.protobuf; 32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport com.google.protobuf.DescriptorProtos.*; 34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.util.Arrays; 36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.util.Collections; 37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.util.HashMap; 38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.util.List; 39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.util.Map; 40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.io.UnsupportedEncodingException; 41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville/** 43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Contains a collection of classes which describe protocol message types. 44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Every message type has a {@link Descriptor}, which lists all 46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * its fields and other information about a type. You can get a message 47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * type's descriptor by calling {@code MessageType.getDescriptor()}, or 48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * (given a message object of the type) {@code message.getDescriptorForType()}. 49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Descriptors are built from DescriptorProtos, as defined in 51d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville * {@code google/protobuf/descriptor.proto}. 52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @author kenton@google.com Kenton Varda 54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 55fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillepublic final class Descriptors { 56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Describes a {@code .proto} file, including everything defined within. 58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public static final class FileDescriptor { 60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Convert the descriptor to its protocol message representation. */ 61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FileDescriptorProto toProto() { return proto; } 62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the file name. */ 64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getName() { return proto.getName(); } 65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the proto package name. This is the package name given by the 68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * {@code package} statement in the {@code .proto} file, which differs 69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * from the Java package. 70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getPackage() { return proto.getPackage(); } 72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the {@code FileOptions}, defined in {@code descriptor.proto}. */ 74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FileOptions getOptions() { return proto.getOptions(); } 75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get a list of top-level message types declared in this file. */ 77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public List<Descriptor> getMessageTypes() { 78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return Collections.unmodifiableList(Arrays.asList(messageTypes)); 79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get a list of top-level enum types declared in this file. */ 82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public List<EnumDescriptor> getEnumTypes() { 83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return Collections.unmodifiableList(Arrays.asList(enumTypes)); 84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get a list of top-level services declared in this file. */ 87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public List<ServiceDescriptor> getServices() { 88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return Collections.unmodifiableList(Arrays.asList(services)); 89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get a list of top-level extensions declared in this file. */ 92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public List<FieldDescriptor> getExtensions() { 93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return Collections.unmodifiableList(Arrays.asList(extensions)); 94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get a list of this file's dependencies (imports). */ 97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public List<FileDescriptor> getDependencies() { 98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return Collections.unmodifiableList(Arrays.asList(dependencies)); 99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Find a message type in the file by name. Does not find nested types. 103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param name The unqualified type name to look for. 105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @return The message type's descriptor, or {@code null} if not found. 106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Descriptor findMessageTypeByName(String name) { 108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Don't allow looking up nested types. This will make optimization 109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // easier later. 110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (name.indexOf('.') != -1) { 111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (getPackage().length() > 0) { 114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name = getPackage() + '.' + name; 115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor result = pool.findSymbol(name); 117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != null && result instanceof Descriptor && 118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result.getFile() == this) { 119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return (Descriptor)result; 120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Find an enum type in the file by name. Does not find nested types. 127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param name The unqualified type name to look for. 129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @return The enum type's descriptor, or {@code null} if not found. 130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public EnumDescriptor findEnumTypeByName(String name) { 132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Don't allow looking up nested types. This will make optimization 133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // easier later. 134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (name.indexOf('.') != -1) { 135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (getPackage().length() > 0) { 138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name = getPackage() + '.' + name; 139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor result = pool.findSymbol(name); 141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != null && result instanceof EnumDescriptor && 142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result.getFile() == this) { 143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return (EnumDescriptor)result; 144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Find a service type in the file by name. 151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param name The unqualified type name to look for. 153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @return The service type's descriptor, or {@code null} if not found. 154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public ServiceDescriptor findServiceByName(String name) { 156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Don't allow looking up nested types. This will make optimization 157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // easier later. 158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (name.indexOf('.') != -1) { 159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (getPackage().length() > 0) { 162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name = getPackage() + '.' + name; 163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor result = pool.findSymbol(name); 165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != null && result instanceof ServiceDescriptor && 166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result.getFile() == this) { 167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return (ServiceDescriptor)result; 168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Find an extension in the file by name. Does not find extensions nested 175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * inside message types. 176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param name The unqualified extension name to look for. 178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @return The extension's descriptor, or {@code null} if not found. 179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FieldDescriptor findExtensionByName(String name) { 181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (name.indexOf('.') != -1) { 182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (getPackage().length() > 0) { 185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name = getPackage() + '.' + name; 186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor result = pool.findSymbol(name); 188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != null && result instanceof FieldDescriptor && 189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result.getFile() == this) { 190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return (FieldDescriptor)result; 191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Construct a {@code FileDescriptor}. 198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param proto The protocol message form of the FileDescriptor. 200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param dependencies {@code FileDescriptor}s corresponding to all of 201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * the file's dependencies, in the exact order listed 202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * in {@code proto}. 203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @throws DescriptorValidationException {@code proto} is not a valid 204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * descriptor. This can occur for a number of reasons, e.g. 205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * because a field has an undefined type or because two messages 206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * were defined with the same name. 207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public static FileDescriptor buildFrom(final FileDescriptorProto proto, 209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor[] dependencies) 210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Building decsriptors involves two steps: translating and linking. 212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // In the translation step (implemented by FileDescriptor's 213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // constructor), we build an object tree mirroring the 214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // FileDescriptorProto's tree and put all of the descriptors into the 215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // DescriptorPool's lookup tables. In the linking step, we look up all 216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // type references in the DescriptorPool, so that, for example, a 217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // FieldDescriptor for an embedded message contains a pointer directly 218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // to the Descriptor for that message's type. We also detect undefined 219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // types in the linking step. 220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final DescriptorPool pool = new DescriptorPool(dependencies); 221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor result = 222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville new FileDescriptor(proto, dependencies, pool); 223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (dependencies.length != proto.getDependencyCount()) { 225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(result, 226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Dependencies passed to FileDescriptor.buildFrom() don't match " + 227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "those listed in the FileDescriptorProto."); 228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < proto.getDependencyCount(); i++) { 230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!dependencies[i].getName().equals(proto.getDependency(i))) { 231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(result, 232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Dependencies passed to FileDescriptor.buildFrom() don't match " + 233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "those listed in the FileDescriptorProto."); 234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result.crossLink(); 238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result; 239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * This method is to be called by generated code only. It is equivalent 243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * to {@code buildFrom} except that the {@code FileDescriptorProto} is 244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * encoded in protocol buffer wire format. 245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public static void internalBuildGeneratedFileFrom( 247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final String[] descriptorDataParts, 248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor[] dependencies, 249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final InternalDescriptorAssigner descriptorAssigner) { 250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Hack: We can't embed a raw byte array inside generated Java code 251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // (at least, not efficiently), but we can embed Strings. So, the 252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // protocol compiler embeds the FileDescriptorProto as a giant 253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // string literal which is passed to this function to construct the 254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // file's FileDescriptor. The string literal contains only 8-bit 255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // characters, each one representing a byte of the FileDescriptorProto's 256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // serialized form. So, if we convert it to bytes in ISO-8859-1, we 257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // should get the original bytes that we want. 258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // descriptorData may contain multiple strings in order to get around the 260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Java 64k string literal limit. 261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville StringBuilder descriptorData = new StringBuilder(); 262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (String part : descriptorDataParts) { 263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptorData.append(part); 264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 266fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final byte[] descriptorBytes; 267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try { 268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptorBytes = descriptorData.toString().getBytes("ISO-8859-1"); 269fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } catch (UnsupportedEncodingException e) { 270fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new RuntimeException( 271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Standard encoding ISO-8859-1 not supported by JVM.", e); 272fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 273fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 274fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FileDescriptorProto proto; 275fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try { 276fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto = FileDescriptorProto.parseFrom(descriptorBytes); 277fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } catch (InvalidProtocolBufferException e) { 278fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new IllegalArgumentException( 279fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Failed to parse protocol buffer descriptor for generated code.", e); 280fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 281fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 282fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor result; 283fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try { 284fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result = buildFrom(proto, dependencies); 285fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } catch (DescriptorValidationException e) { 286fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new IllegalArgumentException( 287fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Invalid embedded descriptor for \"" + proto.getName() + "\".", e); 288fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 289fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 290fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final ExtensionRegistry registry = 291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptorAssigner.assignDescriptors(result); 292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 293fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (registry != null) { 294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // We must re-parse the proto using the registry. 295fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try { 296fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto = FileDescriptorProto.parseFrom(descriptorBytes, registry); 297fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } catch (InvalidProtocolBufferException e) { 298fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new IllegalArgumentException( 299fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Failed to parse protocol buffer descriptor for generated code.", 300fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville e); 301fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 302fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result.setProto(proto); 304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 306fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 307fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 308fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * This class should be used by generated code only. When calling 309fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * {@link FileDescriptor#internalBuildGeneratedFileFrom}, the caller 310fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * provides a callback implementing this interface. The callback is called 311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * after the FileDescriptor has been constructed, in order to assign all 312fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * the global variales defined in the generated code which point at parts 313fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * of the FileDescriptor. The callback returns an ExtensionRegistry which 314fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * contains any extensions which might be used in the descriptor -- that 315fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * is, extensions of the various "Options" messages defined in 316fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * descriptor.proto. The callback may also return null to indicate that 317fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * no extensions are used in the decsriptor. 318fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 319fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public interface InternalDescriptorAssigner { 320fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ExtensionRegistry assignDescriptors(FileDescriptor root); 321fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 322fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 323fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private FileDescriptorProto proto; 324fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final Descriptor[] messageTypes; 325fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final EnumDescriptor[] enumTypes; 326fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final ServiceDescriptor[] services; 327fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final FieldDescriptor[] extensions; 328fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final FileDescriptor[] dependencies; 329fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final DescriptorPool pool; 330fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 331fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private FileDescriptor(final FileDescriptorProto proto, 332fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor[] dependencies, 333fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final DescriptorPool pool) 334fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 335fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.pool = pool; 336fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 337fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.dependencies = dependencies.clone(); 338fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 339fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville pool.addPackage(getPackage(), this); 340fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 341fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville messageTypes = new Descriptor[proto.getMessageTypeCount()]; 342fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < proto.getMessageTypeCount(); i++) { 343fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville messageTypes[i] = 344fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville new Descriptor(proto.getMessageType(i), this, null, i); 345fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 346fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 347fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enumTypes = new EnumDescriptor[proto.getEnumTypeCount()]; 348fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < proto.getEnumTypeCount(); i++) { 349fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enumTypes[i] = new EnumDescriptor(proto.getEnumType(i), this, null, i); 350fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 351fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 352fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville services = new ServiceDescriptor[proto.getServiceCount()]; 353fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < proto.getServiceCount(); i++) { 354fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville services[i] = new ServiceDescriptor(proto.getService(i), this, i); 355fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 356fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 357fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville extensions = new FieldDescriptor[proto.getExtensionCount()]; 358fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < proto.getExtensionCount(); i++) { 359fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville extensions[i] = new FieldDescriptor( 360fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto.getExtension(i), this, null, i, true); 361fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 362fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 363fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 364fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Look up and cross-link all field types, etc. */ 365fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private void crossLink() throws DescriptorValidationException { 366fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (final Descriptor messageType : messageTypes) { 367fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville messageType.crossLink(); 368fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 369fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 370fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (final ServiceDescriptor service : services) { 371fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville service.crossLink(); 372fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 373fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 374fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (final FieldDescriptor extension : extensions) { 375fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville extension.crossLink(); 376fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 377fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 378fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 379fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 380fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Replace our {@link FileDescriptorProto} with the given one, which is 381fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * identical except that it might contain extensions that weren't present 382fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * in the original. This method is needed for bootstrapping when a file 383fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * defines custom options. The options may be defined in the file itself, 384fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * so we can't actually parse them until we've constructed the descriptors, 385fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * but to construct the decsriptors we have to have parsed the descriptor 386fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * protos. So, we have to parse the descriptor protos a second time after 387fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * constructing the descriptors. 388fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 389fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private void setProto(final FileDescriptorProto proto) { 390fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 391fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 392fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < messageTypes.length; i++) { 393fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville messageTypes[i].setProto(proto.getMessageType(i)); 394fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 395fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 396fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < enumTypes.length; i++) { 397fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enumTypes[i].setProto(proto.getEnumType(i)); 398fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 399fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 400fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < services.length; i++) { 401fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville services[i].setProto(proto.getService(i)); 402fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 403fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 404fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < extensions.length; i++) { 405fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville extensions[i].setProto(proto.getExtension(i)); 406fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 407fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 408fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 409fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 410fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // ================================================================= 411fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 412fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Describes a message type. */ 413fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public static final class Descriptor implements GenericDescriptor { 414fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 415fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the index of this descriptor within its parent. In other words, 416fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * given a {@link FileDescriptor} {@code file}, the following is true: 417fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * <pre> 418fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * for all i in [0, file.getMessageTypeCount()): 419fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * file.getMessageType(i).getIndex() == i 420fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * </pre> 421fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Similarly, for a {@link Descriptor} {@code messageType}: 422fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * <pre> 423fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * for all i in [0, messageType.getNestedTypeCount()): 424fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * messageType.getNestedType(i).getIndex() == i 425fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * </pre> 426fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 427fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public int getIndex() { return index; } 428fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 429fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Convert the descriptor to its protocol message representation. */ 430fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public DescriptorProto toProto() { return proto; } 431fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 432fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the type's unqualified name. */ 433fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getName() { return proto.getName(); } 434fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 435fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 436fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the type's fully-qualified name, within the proto language's 437fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * namespace. This differs from the Java name. For example, given this 438fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * {@code .proto}: 439fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * <pre> 440fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * package foo.bar; 441fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * option java_package = "com.example.protos" 442fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * message Baz {} 443fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * </pre> 444fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * {@code Baz}'s full name is "foo.bar.Baz". 445fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 446fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getFullName() { return fullName; } 447fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 448fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the {@link FileDescriptor} containing this descriptor. */ 449fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FileDescriptor getFile() { return file; } 450fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 451fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** If this is a nested type, get the outer descriptor, otherwise null. */ 452fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Descriptor getContainingType() { return containingType; } 453fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 454fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the {@code MessageOptions}, defined in {@code descriptor.proto}. */ 455fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public MessageOptions getOptions() { return proto.getOptions(); } 456fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 457fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get a list of this message type's fields. */ 458fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public List<FieldDescriptor> getFields() { 459fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return Collections.unmodifiableList(Arrays.asList(fields)); 460fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 461fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 462fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get a list of this message type's extensions. */ 463fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public List<FieldDescriptor> getExtensions() { 464fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return Collections.unmodifiableList(Arrays.asList(extensions)); 465fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 466fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 467fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get a list of message types nested within this one. */ 468fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public List<Descriptor> getNestedTypes() { 469fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return Collections.unmodifiableList(Arrays.asList(nestedTypes)); 470fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 471fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 472fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get a list of enum types nested within this one. */ 473fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public List<EnumDescriptor> getEnumTypes() { 474fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return Collections.unmodifiableList(Arrays.asList(enumTypes)); 475fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 476fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 477fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Determines if the given field number is an extension. */ 478fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public boolean isExtensionNumber(final int number) { 479fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (final DescriptorProto.ExtensionRange range : 480fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto.getExtensionRangeList()) { 481fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (range.getStart() <= number && number < range.getEnd()) { 482fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return true; 483fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 484fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 485fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 486fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 487fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 488fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 489fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Finds a field by name. 490fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param name The unqualified name of the field (e.g. "foo"). 491fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @return The field's descriptor, or {@code null} if not found. 492fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 493fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FieldDescriptor findFieldByName(final String name) { 494fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor result = 495fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.findSymbol(fullName + '.' + name); 496fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != null && result instanceof FieldDescriptor) { 497fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return (FieldDescriptor)result; 498fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 499fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 500fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 501fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 502fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 503fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 504fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Finds a field by field number. 505fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param number The field number within this message type. 506fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @return The field's descriptor, or {@code null} if not found. 507fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 508fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FieldDescriptor findFieldByNumber(final int number) { 509fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return file.pool.fieldsByNumber.get( 510fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville new DescriptorPool.DescriptorIntPair(this, number)); 511fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 512fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 513fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 514fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Finds a nested message type by name. 515fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param name The unqualified name of the nested type (e.g. "Foo"). 516fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @return The types's descriptor, or {@code null} if not found. 517fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 518fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Descriptor findNestedTypeByName(final String name) { 519fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor result = 520fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.findSymbol(fullName + '.' + name); 521fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != null && result instanceof Descriptor) { 522fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return (Descriptor)result; 523fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 524fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 525fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 526fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 527fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 528fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 529fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Finds a nested enum type by name. 530fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param name The unqualified name of the nested type (e.g. "Foo"). 531fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @return The types's descriptor, or {@code null} if not found. 532fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 533fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public EnumDescriptor findEnumTypeByName(final String name) { 534fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor result = 535fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.findSymbol(fullName + '.' + name); 536fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != null && result instanceof EnumDescriptor) { 537fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return (EnumDescriptor)result; 538fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 539fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 540fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 541fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 542fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 543fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final int index; 544fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private DescriptorProto proto; 545fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final String fullName; 546fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final FileDescriptor file; 547fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final Descriptor containingType; 548fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final Descriptor[] nestedTypes; 549fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final EnumDescriptor[] enumTypes; 550fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final FieldDescriptor[] fields; 551fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final FieldDescriptor[] extensions; 552fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 553fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private Descriptor(final DescriptorProto proto, 554fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor file, 555fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final Descriptor parent, 556fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final int index) 557fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 558fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.index = index; 559fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 560fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville fullName = computeFullName(file, parent, proto.getName()); 561fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.file = file; 562fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville containingType = parent; 563fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 564fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville nestedTypes = new Descriptor[proto.getNestedTypeCount()]; 565fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < proto.getNestedTypeCount(); i++) { 566fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville nestedTypes[i] = new Descriptor( 567fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto.getNestedType(i), file, this, i); 568fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 569fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 570fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enumTypes = new EnumDescriptor[proto.getEnumTypeCount()]; 571fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < proto.getEnumTypeCount(); i++) { 572fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enumTypes[i] = new EnumDescriptor( 573fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto.getEnumType(i), file, this, i); 574fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 575fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 576fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville fields = new FieldDescriptor[proto.getFieldCount()]; 577fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < proto.getFieldCount(); i++) { 578fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville fields[i] = new FieldDescriptor( 579fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto.getField(i), file, this, i, false); 580fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 581fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 582fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville extensions = new FieldDescriptor[proto.getExtensionCount()]; 583fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < proto.getExtensionCount(); i++) { 584fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville extensions[i] = new FieldDescriptor( 585fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto.getExtension(i), file, this, i, true); 586fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 587fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 588fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.addSymbol(this); 589fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 590fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 591fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Look up and cross-link all field types, etc. */ 592fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private void crossLink() throws DescriptorValidationException { 593fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (final Descriptor nestedType : nestedTypes) { 594fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville nestedType.crossLink(); 595fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 596fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 597fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (final FieldDescriptor field : fields) { 598fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville field.crossLink(); 599fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 600fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 601fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (final FieldDescriptor extension : extensions) { 602fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville extension.crossLink(); 603fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 604fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 605fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 606fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** See {@link FileDescriptor#setProto}. */ 607fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private void setProto(final DescriptorProto proto) { 608fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 609fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 610fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < nestedTypes.length; i++) { 611fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville nestedTypes[i].setProto(proto.getNestedType(i)); 612fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 613fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 614fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < enumTypes.length; i++) { 615fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enumTypes[i].setProto(proto.getEnumType(i)); 616fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 617fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 618fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < fields.length; i++) { 619fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville fields[i].setProto(proto.getField(i)); 620fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 621fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 622fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < extensions.length; i++) { 623fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville extensions[i].setProto(proto.getExtension(i)); 624fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 625fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 626fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 627fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 628fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // ================================================================= 629fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 630fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Describes a field of a message type. */ 631fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public static final class FieldDescriptor 632fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville implements GenericDescriptor, Comparable<FieldDescriptor>, 633fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FieldSet.FieldDescriptorLite<FieldDescriptor> { 634fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 635fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the index of this descriptor within its parent. 636fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @see Descriptor#getIndex() 637fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 638fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public int getIndex() { return index; } 639fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 640fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Convert the descriptor to its protocol message representation. */ 641fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FieldDescriptorProto toProto() { return proto; } 642fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 643fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the field's unqualified name. */ 644fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getName() { return proto.getName(); } 645fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 646fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the field's number. */ 647fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public int getNumber() { return proto.getNumber(); } 648fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 649fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 650fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the field's fully-qualified name. 651fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @see Descriptor#getFullName() 652fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 653fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getFullName() { return fullName; } 654fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 655fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 656fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the field's java type. This is just for convenience. Every 657fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * {@code FieldDescriptorProto.Type} maps to exactly one Java type. 658fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 659fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public JavaType getJavaType() { return type.getJavaType(); } 660fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 661fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** For internal use only. */ 662fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public WireFormat.JavaType getLiteJavaType() { 663fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return getLiteType().getJavaType(); 664fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 665fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 666fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the {@code FileDescriptor} containing this descriptor. */ 667fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FileDescriptor getFile() { return file; } 668fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 669fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the field's declared type. */ 670fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Type getType() { return type; } 671fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 672fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** For internal use only. */ 673fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public WireFormat.FieldType getLiteType() { 674fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return table[type.ordinal()]; 675fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 676fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // I'm pretty sure values() constructs a new array every time, since there 677fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // is nothing stopping the caller from mutating the array. Therefore we 678fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // make a static copy here. 679fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private static final WireFormat.FieldType[] table = 680fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville WireFormat.FieldType.values(); 681fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 682fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Is this field declared required? */ 683fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public boolean isRequired() { 684fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REQUIRED; 685fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 686fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 687fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Is this field declared optional? */ 688fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public boolean isOptional() { 689fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return proto.getLabel() == FieldDescriptorProto.Label.LABEL_OPTIONAL; 690fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 691fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 692fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Is this field declared repeated? */ 693fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public boolean isRepeated() { 694fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED; 695fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 696fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 697fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Does this field have the {@code [packed = true]} option? */ 698fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public boolean isPacked() { 699fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return getOptions().getPacked(); 700fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 701fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 702d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville /** Can this field be packed? i.e. is it a repeated primitive field? */ 703d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville public boolean isPackable() { 704d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return isRepeated() && getLiteType().isPackable(); 705d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 706d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 707fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Returns true if the field had an explicitly-defined default value. */ 708fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public boolean hasDefaultValue() { return proto.hasDefaultValue(); } 709fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 710fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 711fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Returns the field's default value. Valid for all types except for 712fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * messages and groups. For all other types, the object returned is of 713fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * the same class that would returned by Message.getField(this). 714fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 715fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Object getDefaultValue() { 716fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (getJavaType() == JavaType.MESSAGE) { 717fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new UnsupportedOperationException( 718fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "FieldDescriptor.getDefaultValue() called on an embedded message " + 719fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "field."); 720fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 721fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return defaultValue; 722fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 723fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 724fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the {@code FieldOptions}, defined in {@code descriptor.proto}. */ 725fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FieldOptions getOptions() { return proto.getOptions(); } 726fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 727fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Is this field an extension? */ 728fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public boolean isExtension() { return proto.hasExtendee(); } 729fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 730fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 731fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the field's containing type. For extensions, this is the type being 732fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * extended, not the location where the extension was defined. See 733fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * {@link #getExtensionScope()}. 734fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 735fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Descriptor getContainingType() { return containingType; } 736fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 737fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 738fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * For extensions defined nested within message types, gets the outer 739fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * type. Not valid for non-extension fields. For example, consider 740fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * this {@code .proto} file: 741fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * <pre> 742fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * message Foo { 743fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * extensions 1000 to max; 744fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * } 745fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * extend Foo { 746fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * optional int32 baz = 1234; 747fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * } 748fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * message Bar { 749fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * extend Foo { 750fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * optional int32 qux = 4321; 751fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * } 752fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * } 753fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * </pre> 754fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Both {@code baz}'s and {@code qux}'s containing type is {@code Foo}. 755fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * However, {@code baz}'s extension scope is {@code null} while 756fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * {@code qux}'s extension scope is {@code Bar}. 757fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 758fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Descriptor getExtensionScope() { 759fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!isExtension()) { 760fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new UnsupportedOperationException( 761fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "This field is not an extension."); 762fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 763fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return extensionScope; 764fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 765fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 766fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** For embedded message and group fields, gets the field's type. */ 767fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Descriptor getMessageType() { 768fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (getJavaType() != JavaType.MESSAGE) { 769fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new UnsupportedOperationException( 770fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "This field is not of message type."); 771fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 772fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return messageType; 773fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 774fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 775fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** For enum fields, gets the field's type. */ 776fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public EnumDescriptor getEnumType() { 777fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (getJavaType() != JavaType.ENUM) { 778fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new UnsupportedOperationException( 779fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "This field is not of enum type."); 780fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 781fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return enumType; 782fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 783fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 784fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 785fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Compare with another {@code FieldDescriptor}. This orders fields in 786fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * "canonical" order, which simply means ascending order by field number. 787fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * {@code other} must be a field of the same type -- i.e. 788fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * {@code getContainingType()} must return the same {@code Descriptor} for 789fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * both fields. 790fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 791fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @return negative, zero, or positive if {@code this} is less than, 792fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * equal to, or greater than {@code other}, respectively. 793fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 794fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public int compareTo(final FieldDescriptor other) { 795fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (other.containingType != containingType) { 796fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new IllegalArgumentException( 797fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "FieldDescriptors can only be compared to other FieldDescriptors " + 798fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "for fields of the same message type."); 799fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 800fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return getNumber() - other.getNumber(); 801fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 802fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 803fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final int index; 804fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 805fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private FieldDescriptorProto proto; 806fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final String fullName; 807fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final FileDescriptor file; 808fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final Descriptor extensionScope; 809fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 810fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Possibly initialized during cross-linking. 811fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private Type type; 812fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private Descriptor containingType; 813fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private Descriptor messageType; 814fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private EnumDescriptor enumType; 815fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private Object defaultValue; 816fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 817fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public enum Type { 818d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville DOUBLE (JavaType.DOUBLE ), 819d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville FLOAT (JavaType.FLOAT ), 820d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville INT64 (JavaType.LONG ), 821d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville UINT64 (JavaType.LONG ), 822d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville INT32 (JavaType.INT ), 823d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville FIXED64 (JavaType.LONG ), 824d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville FIXED32 (JavaType.INT ), 825d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville BOOL (JavaType.BOOLEAN ), 826d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville STRING (JavaType.STRING ), 827d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GROUP (JavaType.MESSAGE ), 828d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville MESSAGE (JavaType.MESSAGE ), 829d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville BYTES (JavaType.BYTE_STRING), 830d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville UINT32 (JavaType.INT ), 831d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ENUM (JavaType.ENUM ), 832d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville SFIXED32(JavaType.INT ), 833d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville SFIXED64(JavaType.LONG ), 834d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville SINT32 (JavaType.INT ), 835d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville SINT64 (JavaType.LONG ); 836d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 837d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville Type(final JavaType javaType) { 838fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.javaType = javaType; 839fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 840fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 841fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private JavaType javaType; 842fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 843d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville public FieldDescriptorProto.Type toProto() { 844d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return FieldDescriptorProto.Type.valueOf(ordinal() + 1); 845d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 846fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public JavaType getJavaType() { return javaType; } 847fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 848fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public static Type valueOf(final FieldDescriptorProto.Type type) { 849fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return values()[type.getNumber() - 1]; 850fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 851fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 852fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 853fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville static { 854fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Refuse to init if someone added a new declared type. 855fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (Type.values().length != FieldDescriptorProto.Type.values().length) { 856fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new RuntimeException( 857fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "descriptor.proto has a new declared type but Desrciptors.java " + 858fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "wasn't updated."); 859fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 860fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 861fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 862fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public enum JavaType { 863fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville INT(0), 864fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville LONG(0L), 865fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FLOAT(0F), 866fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DOUBLE(0D), 867fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville BOOLEAN(false), 868fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville STRING(""), 869fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville BYTE_STRING(ByteString.EMPTY), 870fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ENUM(null), 871fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MESSAGE(null); 872fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 873fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville JavaType(final Object defaultDefault) { 874fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.defaultDefault = defaultDefault; 875fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 876fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 877fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 878fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * The default default value for fields of this type, if it's a primitive 879fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * type. This is meant for use inside this file only, hence is private. 880fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 881fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final Object defaultDefault; 882fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 883fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 884fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private FieldDescriptor(final FieldDescriptorProto proto, 885fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor file, 886fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final Descriptor parent, 887fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final int index, 888fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final boolean isExtension) 889fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 890fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.index = index; 891fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 892fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville fullName = computeFullName(file, parent, proto.getName()); 893fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.file = file; 894fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 895fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (proto.hasType()) { 896fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville type = Type.valueOf(proto.getType()); 897fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 898fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 899fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (getNumber() <= 0) { 900fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 901fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Field numbers must be positive integers."); 902fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 903fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 904fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Only repeated primitive fields may be packed. 905d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (proto.getOptions().getPacked() && !isPackable()) { 906d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville throw new DescriptorValidationException(this, 907d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "[packed = true] can only be specified for repeated primitive " + 908d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "fields."); 909fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 910fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 911fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (isExtension) { 912fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!proto.hasExtendee()) { 913fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 914fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "FieldDescriptorProto.extendee not set for extension field."); 915fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 916fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville containingType = null; // Will be filled in when cross-linking 917fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (parent != null) { 918fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville extensionScope = parent; 919fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 920fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville extensionScope = null; 921fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 922fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 923fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (proto.hasExtendee()) { 924fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 925fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "FieldDescriptorProto.extendee set for non-extension field."); 926fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 927fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville containingType = parent; 928fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville extensionScope = null; 929fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 930fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 931fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.addSymbol(this); 932fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 933fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 934fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Look up and cross-link all field types, etc. */ 935fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private void crossLink() throws DescriptorValidationException { 936fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (proto.hasExtendee()) { 937fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor extendee = 938fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.lookupSymbol(proto.getExtendee(), this); 939fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!(extendee instanceof Descriptor)) { 940fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 941fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + proto.getExtendee() + "\" is not a message type."); 942fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 943fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville containingType = (Descriptor)extendee; 944fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 945fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!getContainingType().isExtensionNumber(getNumber())) { 946fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 947fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + getContainingType().getFullName() + 948fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "\" does not declare " + getNumber() + 949fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " as an extension number."); 950fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 951fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 952fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 953fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (proto.hasTypeName()) { 954fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor typeDescriptor = 955fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.lookupSymbol(proto.getTypeName(), this); 956fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 957fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!proto.hasType()) { 958fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Choose field type based on symbol. 959fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (typeDescriptor instanceof Descriptor) { 960fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville type = Type.MESSAGE; 961fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (typeDescriptor instanceof EnumDescriptor) { 962fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville type = Type.ENUM; 963fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 964fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 965fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + proto.getTypeName() + "\" is not a type."); 966fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 967fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 968fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 969fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (getJavaType() == JavaType.MESSAGE) { 970fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!(typeDescriptor instanceof Descriptor)) { 971fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 972fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + proto.getTypeName() + "\" is not a message type."); 973fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 974fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville messageType = (Descriptor)typeDescriptor; 975fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 976fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (proto.hasDefaultValue()) { 977fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 978fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Messages can't have default values."); 979fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 980fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (getJavaType() == JavaType.ENUM) { 981fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!(typeDescriptor instanceof EnumDescriptor)) { 982fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 983fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + proto.getTypeName() + "\" is not an enum type."); 984fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 985fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enumType = (EnumDescriptor)typeDescriptor; 986fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 987fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 988fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Field with primitive type has type_name."); 989fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 990fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 991fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (getJavaType() == JavaType.MESSAGE || 992fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville getJavaType() == JavaType.ENUM) { 993fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 994fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Field with message or enum type missing type_name."); 995fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 996fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 997fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 998fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // We don't attempt to parse the default value until here because for 999fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // enums we need the enum type's descriptor. 1000fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (proto.hasDefaultValue()) { 1001fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (isRepeated()) { 1002fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 1003fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Repeated fields cannot have default values."); 1004fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1005fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1006fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try { 1007fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville switch (getType()) { 1008fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case INT32: 1009fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case SINT32: 1010fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case SFIXED32: 1011fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville defaultValue = TextFormat.parseInt32(proto.getDefaultValue()); 1012fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1013fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case UINT32: 1014fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case FIXED32: 1015fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville defaultValue = TextFormat.parseUInt32(proto.getDefaultValue()); 1016fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1017fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case INT64: 1018fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case SINT64: 1019fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case SFIXED64: 1020fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville defaultValue = TextFormat.parseInt64(proto.getDefaultValue()); 1021fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1022fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case UINT64: 1023fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case FIXED64: 1024fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville defaultValue = TextFormat.parseUInt64(proto.getDefaultValue()); 1025fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1026fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case FLOAT: 1027d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (proto.getDefaultValue().equals("inf")) { 1028d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville defaultValue = Float.POSITIVE_INFINITY; 1029d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else if (proto.getDefaultValue().equals("-inf")) { 1030d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville defaultValue = Float.NEGATIVE_INFINITY; 1031d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else if (proto.getDefaultValue().equals("nan")) { 1032d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville defaultValue = Float.NaN; 1033d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 1034d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville defaultValue = Float.valueOf(proto.getDefaultValue()); 1035d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1036fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1037fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case DOUBLE: 1038d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (proto.getDefaultValue().equals("inf")) { 1039d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville defaultValue = Double.POSITIVE_INFINITY; 1040d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else if (proto.getDefaultValue().equals("-inf")) { 1041d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville defaultValue = Double.NEGATIVE_INFINITY; 1042d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else if (proto.getDefaultValue().equals("nan")) { 1043d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville defaultValue = Double.NaN; 1044d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 1045d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville defaultValue = Double.valueOf(proto.getDefaultValue()); 1046d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1047fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1048fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case BOOL: 1049fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville defaultValue = Boolean.valueOf(proto.getDefaultValue()); 1050fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1051fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case STRING: 1052fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville defaultValue = proto.getDefaultValue(); 1053fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1054fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case BYTES: 1055fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try { 1056fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville defaultValue = 1057fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville TextFormat.unescapeBytes(proto.getDefaultValue()); 1058fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } catch (TextFormat.InvalidEscapeSequenceException e) { 1059fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 1060fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Couldn't parse default value: " + e.getMessage(), e); 1061fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1062fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1063fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case ENUM: 1064fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville defaultValue = enumType.findValueByName(proto.getDefaultValue()); 1065fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (defaultValue == null) { 1066fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 1067fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Unknown enum default value: \"" + 1068fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto.getDefaultValue() + '\"'); 1069fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1070fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1071fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case MESSAGE: 1072fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case GROUP: 1073fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 1074fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Message type had default value."); 1075fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1076fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } catch (NumberFormatException e) { 1077d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville throw new DescriptorValidationException(this, 1078d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "Could not parse default value: \"" + 1079d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville proto.getDefaultValue() + '\"', e); 1080fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1081fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1082fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Determine the default default for this field. 1083fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (isRepeated()) { 1084fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville defaultValue = Collections.emptyList(); 1085fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1086fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville switch (getJavaType()) { 1087fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case ENUM: 1088fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // We guarantee elsewhere that an enum type always has at least 1089fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // one possible value. 1090fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville defaultValue = enumType.getValues().get(0); 1091fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1092fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case MESSAGE: 1093fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville defaultValue = null; 1094fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1095fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville default: 1096fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville defaultValue = getJavaType().defaultDefault; 1097fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1098fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1099fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!isExtension()) { 1103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.addFieldByNumber(this); 1104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (containingType != null && 1107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville containingType.getOptions().getMessageSetWireFormat()) { 1108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (isExtension()) { 1109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!isOptional() || getType() != Type.MESSAGE) { 1110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 1111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Extensions of MessageSets must be optional messages."); 1112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 1115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "MessageSets cannot have fields, only extensions."); 1116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** See {@link FileDescriptor#setProto}. */ 1121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private void setProto(final FieldDescriptorProto proto) { 1122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 1123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * For internal use only. This is to satisfy the FieldDescriptorLite 1127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * interface. 1128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public MessageLite.Builder internalMergeFrom( 1130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MessageLite.Builder to, MessageLite from) { 1131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // FieldDescriptors are only used with non-lite messages so we can just 1132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // down-cast and call mergeFrom directly. 1133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return ((Message.Builder) to).mergeFrom((Message) from); 1134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // ================================================================= 1138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Describes an enum type. */ 1140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public static final class EnumDescriptor 1141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville implements GenericDescriptor, Internal.EnumLiteMap<EnumValueDescriptor> { 1142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the index of this descriptor within its parent. 1144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @see Descriptor#getIndex() 1145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public int getIndex() { return index; } 1147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Convert the descriptor to its protocol message representation. */ 1149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public EnumDescriptorProto toProto() { return proto; } 1150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the type's unqualified name. */ 1152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getName() { return proto.getName(); } 1153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the type's fully-qualified name. 1156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @see Descriptor#getFullName() 1157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getFullName() { return fullName; } 1159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the {@link FileDescriptor} containing this descriptor. */ 1161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FileDescriptor getFile() { return file; } 1162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** If this is a nested type, get the outer descriptor, otherwise null. */ 1164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Descriptor getContainingType() { return containingType; } 1165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the {@code EnumOptions}, defined in {@code descriptor.proto}. */ 1167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public EnumOptions getOptions() { return proto.getOptions(); } 1168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get a list of defined values for this enum. */ 1170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public List<EnumValueDescriptor> getValues() { 1171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return Collections.unmodifiableList(Arrays.asList(values)); 1172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Find an enum value by name. 1176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param name The unqualified name of the value (e.g. "FOO"). 1177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @return the value's decsriptor, or {@code null} if not found. 1178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public EnumValueDescriptor findValueByName(final String name) { 1180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor result = 1181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.findSymbol(fullName + '.' + name); 1182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != null && result instanceof EnumValueDescriptor) { 1183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return (EnumValueDescriptor)result; 1184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 1186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Find an enum value by number. If multiple enum values have the same 1191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * number, this returns the first defined value with that number. 1192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param number The value's number. 1193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @return the value's decsriptor, or {@code null} if not found. 1194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public EnumValueDescriptor findValueByNumber(final int number) { 1196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return file.pool.enumValuesByNumber.get( 1197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville new DescriptorPool.DescriptorIntPair(this, number)); 1198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final int index; 1201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private EnumDescriptorProto proto; 1202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final String fullName; 1203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final FileDescriptor file; 1204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final Descriptor containingType; 1205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private EnumValueDescriptor[] values; 1206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private EnumDescriptor(final EnumDescriptorProto proto, 1208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor file, 1209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final Descriptor parent, 1210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final int index) 1211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 1212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.index = index; 1213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 1214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville fullName = computeFullName(file, parent, proto.getName()); 1215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.file = file; 1216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville containingType = parent; 1217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (proto.getValueCount() == 0) { 1219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // We cannot allow enums with no values because this would mean there 1220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // would be no valid default value for fields of this type. 1221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 1222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Enums must contain at least one value."); 1223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville values = new EnumValueDescriptor[proto.getValueCount()]; 1226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < proto.getValueCount(); i++) { 1227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville values[i] = new EnumValueDescriptor( 1228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto.getValue(i), file, this, i); 1229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.addSymbol(this); 1232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** See {@link FileDescriptor#setProto}. */ 1235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private void setProto(final EnumDescriptorProto proto) { 1236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 1237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < values.length; i++) { 1239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville values[i].setProto(proto.getValue(i)); 1240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // ================================================================= 1245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Describes one value within an enum type. Note that multiple defined 1248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * values may have the same number. In generated Java code, all values 1249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * with the same number after the first become aliases of the first. 1250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * However, they still have independent EnumValueDescriptors. 1251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public static final class EnumValueDescriptor 1253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville implements GenericDescriptor, Internal.EnumLite { 1254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the index of this descriptor within its parent. 1256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @see Descriptor#getIndex() 1257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public int getIndex() { return index; } 1259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Convert the descriptor to its protocol message representation. */ 1261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public EnumValueDescriptorProto toProto() { return proto; } 1262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the value's unqualified name. */ 1264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getName() { return proto.getName(); } 1265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1266fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the value's number. */ 1267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public int getNumber() { return proto.getNumber(); } 1268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1269fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1270fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the value's fully-qualified name. 1271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @see Descriptor#getFullName() 1272fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1273fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getFullName() { return fullName; } 1274fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1275fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the {@link FileDescriptor} containing this descriptor. */ 1276fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FileDescriptor getFile() { return file; } 1277fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1278fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the value's enum type. */ 1279fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public EnumDescriptor getType() { return type; } 1280fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1281fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1282fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the {@code EnumValueOptions}, defined in {@code descriptor.proto}. 1283fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1284fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public EnumValueOptions getOptions() { return proto.getOptions(); } 1285fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1286fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final int index; 1287fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private EnumValueDescriptorProto proto; 1288fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final String fullName; 1289fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final FileDescriptor file; 1290fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final EnumDescriptor type; 1291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private EnumValueDescriptor(final EnumValueDescriptorProto proto, 1293fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor file, 1294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final EnumDescriptor parent, 1295fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final int index) 1296fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 1297fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.index = index; 1298fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 1299fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.file = file; 1300fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville type = parent; 1301fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1302fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville fullName = parent.getFullName() + '.' + proto.getName(); 1303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.addSymbol(this); 1305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.addEnumValueByNumber(this); 1306fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1307fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1308fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** See {@link FileDescriptor#setProto}. */ 1309fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private void setProto(final EnumValueDescriptorProto proto) { 1310fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 1311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1312fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1313fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1314fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // ================================================================= 1315fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1316fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Describes a service type. */ 1317fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public static final class ServiceDescriptor implements GenericDescriptor { 1318fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1319fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the index of this descriptor within its parent. 1320fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * * @see Descriptors.Descriptor#getIndex() 1321fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1322fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public int getIndex() { return index; } 1323fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1324fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Convert the descriptor to its protocol message representation. */ 1325fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public ServiceDescriptorProto toProto() { return proto; } 1326fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1327fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the type's unqualified name. */ 1328fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getName() { return proto.getName(); } 1329fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1330fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1331fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the type's fully-qualified name. 1332fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @see Descriptor#getFullName() 1333fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1334fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getFullName() { return fullName; } 1335fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1336fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the {@link FileDescriptor} containing this descriptor. */ 1337fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FileDescriptor getFile() { return file; } 1338fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1339fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the {@code ServiceOptions}, defined in {@code descriptor.proto}. */ 1340fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public ServiceOptions getOptions() { return proto.getOptions(); } 1341fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1342fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get a list of methods for this service. */ 1343fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public List<MethodDescriptor> getMethods() { 1344fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return Collections.unmodifiableList(Arrays.asList(methods)); 1345fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1346fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1347fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1348fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Find a method by name. 1349fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @param name The unqualified name of the method (e.g. "Foo"). 1350fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @return the method's decsriptor, or {@code null} if not found. 1351fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1352fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public MethodDescriptor findMethodByName(final String name) { 1353fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor result = 1354fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.findSymbol(fullName + '.' + name); 1355fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != null && result instanceof MethodDescriptor) { 1356fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return (MethodDescriptor)result; 1357fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1358fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 1359fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1360fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1361fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1362fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final int index; 1363fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private ServiceDescriptorProto proto; 1364fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final String fullName; 1365fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final FileDescriptor file; 1366fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private MethodDescriptor[] methods; 1367fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1368fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private ServiceDescriptor(final ServiceDescriptorProto proto, 1369fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor file, 1370fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final int index) 1371fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 1372fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.index = index; 1373fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 1374fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville fullName = computeFullName(file, null, proto.getName()); 1375fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.file = file; 1376fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1377fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville methods = new MethodDescriptor[proto.getMethodCount()]; 1378fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < proto.getMethodCount(); i++) { 1379fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville methods[i] = new MethodDescriptor( 1380fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto.getMethod(i), file, this, i); 1381fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1382fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1383fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.addSymbol(this); 1384fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1385fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1386fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private void crossLink() throws DescriptorValidationException { 1387fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (final MethodDescriptor method : methods) { 1388fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville method.crossLink(); 1389fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1390fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1391fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1392fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** See {@link FileDescriptor#setProto}. */ 1393fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private void setProto(final ServiceDescriptorProto proto) { 1394fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 1395fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1396fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < methods.length; i++) { 1397fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville methods[i].setProto(proto.getMethod(i)); 1398fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1399fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1400fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1401fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1402fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // ================================================================= 1403fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1404fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1405fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Describes one method within a service type. 1406fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1407fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public static final class MethodDescriptor implements GenericDescriptor { 1408fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1409fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the index of this descriptor within its parent. 1410fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * * @see Descriptors.Descriptor#getIndex() 1411fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1412fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public int getIndex() { return index; } 1413fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1414fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Convert the descriptor to its protocol message representation. */ 1415fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public MethodDescriptorProto toProto() { return proto; } 1416fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1417fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the method's unqualified name. */ 1418fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getName() { return proto.getName(); } 1419fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1420fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1421fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the method's fully-qualified name. 1422fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @see Descriptor#getFullName() 1423fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1424fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getFullName() { return fullName; } 1425fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1426fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the {@link FileDescriptor} containing this descriptor. */ 1427fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FileDescriptor getFile() { return file; } 1428fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1429fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the method's service type. */ 1430fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public ServiceDescriptor getService() { return service; } 1431fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1432fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the method's input type. */ 1433fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Descriptor getInputType() { return inputType; } 1434fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1435fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Get the method's output type. */ 1436fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Descriptor getOutputType() { return outputType; } 1437fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1438fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1439fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Get the {@code MethodOptions}, defined in {@code descriptor.proto}. 1440fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1441fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public MethodOptions getOptions() { return proto.getOptions(); } 1442fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1443fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final int index; 1444fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private MethodDescriptorProto proto; 1445fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final String fullName; 1446fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final FileDescriptor file; 1447fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final ServiceDescriptor service; 1448fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1449fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Initialized during cross-linking. 1450fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private Descriptor inputType; 1451fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private Descriptor outputType; 1452fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1453fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private MethodDescriptor(final MethodDescriptorProto proto, 1454fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor file, 1455fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final ServiceDescriptor parent, 1456fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final int index) 1457fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 1458fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.index = index; 1459fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 1460fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.file = file; 1461fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville service = parent; 1462fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1463fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville fullName = parent.getFullName() + '.' + proto.getName(); 1464fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1465fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.addSymbol(this); 1466fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1467fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1468fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private void crossLink() throws DescriptorValidationException { 1469fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor input = 1470fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.lookupSymbol(proto.getInputType(), this); 1471fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!(input instanceof Descriptor)) { 1472fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 1473fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + proto.getInputType() + "\" is not a message type."); 1474fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1475fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville inputType = (Descriptor)input; 1476fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1477fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor output = 1478fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.pool.lookupSymbol(proto.getOutputType(), this); 1479fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!(output instanceof Descriptor)) { 1480fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(this, 1481fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + proto.getOutputType() + "\" is not a message type."); 1482fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1483fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville outputType = (Descriptor)output; 1484fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1485fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1486fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** See {@link FileDescriptor#setProto}. */ 1487fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private void setProto(final MethodDescriptorProto proto) { 1488fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.proto = proto; 1489fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1490fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1491fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1492fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // ================================================================= 1493fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1494fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private static String computeFullName(final FileDescriptor file, 1495fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final Descriptor parent, 1496fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final String name) { 1497fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (parent != null) { 1498fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return parent.getFullName() + '.' + name; 1499fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (file.getPackage().length() > 0) { 1500fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return file.getPackage() + '.' + name; 1501fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1502fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return name; 1503fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1504fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1505fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1506fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // ================================================================= 1507fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1508fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1509fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * All descriptors except {@code FileDescriptor} implement this to make 1510fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * {@code DescriptorPool}'s life easier. 1511fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1512fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private interface GenericDescriptor { 1513fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Message toProto(); 1514fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville String getName(); 1515fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville String getFullName(); 1516fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FileDescriptor getFile(); 1517fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1518fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1519fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1520fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Thrown when building descriptors fails because the source DescriptorProtos 1521fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * are not valid. 1522fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1523fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public static class DescriptorValidationException extends Exception { 1524fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private static final long serialVersionUID = 5750205775490483148L; 1525fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1526fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Gets the full name of the descriptor where the error occurred. */ 1527fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getProblemSymbolName() { return name; } 1528fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1529fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1530fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Gets the the protocol message representation of the invalid descriptor. 1531fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1532fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Message getProblemProto() { return proto; } 1533fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1534fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1535fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Gets a human-readable description of the error. 1536fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1537fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getDescription() { return description; } 1538fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1539fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final String name; 1540fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final Message proto; 1541fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final String description; 1542fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1543fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private DescriptorValidationException( 1544fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor problemDescriptor, 1545fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final String description) { 1546d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville super(problemDescriptor.getFullName() + ": " + description); 1547fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1548fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Note that problemDescriptor may be partially uninitialized, so we 1549fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // don't want to expose it directly to the user. So, we only provide 1550fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // the name and the original proto. 1551fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name = problemDescriptor.getFullName(); 1552fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto = problemDescriptor.toProto(); 1553fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.description = description; 1554fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1555fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1556fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private DescriptorValidationException( 1557d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville final GenericDescriptor problemDescriptor, 1558d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville final String description, 1559d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville final Throwable cause) { 1560d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville this(problemDescriptor, description); 1561d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville initCause(cause); 1562d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1563d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1564d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville private DescriptorValidationException( 1565fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor problemDescriptor, 1566fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final String description) { 1567fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville super(problemDescriptor.getName() + ": " + description); 1568fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1569fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Note that problemDescriptor may be partially uninitialized, so we 1570fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // don't want to expose it directly to the user. So, we only provide 1571fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // the name and the original proto. 1572fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name = problemDescriptor.getName(); 1573fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto = problemDescriptor.toProto(); 1574fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.description = description; 1575fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1576fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1577fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1578fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // ================================================================= 1579fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1580fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1581fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * A private helper class which contains lookup tables containing all the 1582fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * descriptors defined in a particular file. 1583fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1584fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private static final class DescriptorPool { 1585fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DescriptorPool(final FileDescriptor[] dependencies) { 1586fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.dependencies = new DescriptorPool[dependencies.length]; 1587fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1588fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < dependencies.length; i++) { 1589fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.dependencies[i] = dependencies[i].pool; 1590fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1591fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1592fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (final FileDescriptor dependency : dependencies) { 1593fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try { 1594fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville addPackage(dependency.getPackage(), dependency); 1595fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } catch (DescriptorValidationException e) { 1596fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Can't happen, because addPackage() only fails when the name 1597fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // conflicts with a non-package, but we have not yet added any 1598fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // non-packages at this point. 1599fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville assert false; 1600fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1601fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1602fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1603fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1604fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final DescriptorPool[] dependencies; 1605fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1606fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final Map<String, GenericDescriptor> descriptorsByName = 1607fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville new HashMap<String, GenericDescriptor>(); 1608fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber = 1609fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville new HashMap<DescriptorIntPair, FieldDescriptor>(); 1610fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber 1611fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville = new HashMap<DescriptorIntPair, EnumValueDescriptor>(); 1612fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1613fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Find a generic descriptor by fully-qualified name. */ 1614fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GenericDescriptor findSymbol(final String fullName) { 1615fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GenericDescriptor result = descriptorsByName.get(fullName); 1616fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != null) { 1617fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result; 1618fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1619fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1620fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (final DescriptorPool dependency : dependencies) { 1621fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result = dependency.descriptorsByName.get(fullName); 1622fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != null) { 1623fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result; 1624fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1625fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1626fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1627fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return null; 1628fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1629fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1630fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1631fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Look up a descriptor by name, relative to some other descriptor. 1632fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * The name may be fully-qualified (with a leading '.'), 1633fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * partially-qualified, or unqualified. C++-like name lookup semantics 1634fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * are used to search for the matching descriptor. 1635fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1636fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GenericDescriptor lookupSymbol(final String name, 1637fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor relativeTo) 1638fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 1639fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // TODO(kenton): This could be optimized in a number of ways. 1640fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1641fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GenericDescriptor result; 1642fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (name.startsWith(".")) { 1643fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Fully-qualified name. 1644fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result = findSymbol(name.substring(1)); 1645fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1646fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // If "name" is a compound identifier, we want to search for the 1647fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // first component of it, then search within it for the rest. 1648fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final int firstPartLength = name.indexOf('.'); 1649fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final String firstPart; 1650fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (firstPartLength == -1) { 1651fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville firstPart = name; 1652fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1653fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville firstPart = name.substring(0, firstPartLength); 1654fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1655fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1656fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // We will search each parent scope of "relativeTo" looking for the 1657fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // symbol. 1658fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final StringBuilder scopeToTry = 1659fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville new StringBuilder(relativeTo.getFullName()); 1660fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1661fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville while (true) { 1662fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Chop off the last component of the scope. 1663fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final int dotpos = scopeToTry.lastIndexOf("."); 1664fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (dotpos == -1) { 1665fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result = findSymbol(name); 1666fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1667fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1668fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville scopeToTry.setLength(dotpos + 1); 1669fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1670fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Append firstPart and try to find. 1671fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville scopeToTry.append(firstPart); 1672fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result = findSymbol(scopeToTry.toString()); 1673fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1674fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result != null) { 1675fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (firstPartLength != -1) { 1676fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // We only found the first part of the symbol. Now look for 1677fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // the whole thing. If this fails, we *don't* want to keep 1678fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // searching parent scopes. 1679fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville scopeToTry.setLength(dotpos + 1); 1680fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville scopeToTry.append(name); 1681fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result = findSymbol(scopeToTry.toString()); 1682fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1683fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 1684fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1685fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1686fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Not found. Remove the name so we can try again. 1687fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville scopeToTry.setLength(dotpos); 1688fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1689fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1690fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1691fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1692fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result == null) { 1693fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(relativeTo, 1694fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + name + "\" is not defined."); 1695fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1696fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result; 1697fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1698fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1699fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1700fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1701fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Adds a symbol to the symbol table. If a symbol with the same name 1702fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * already exists, throws an error. 1703fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1704fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void addSymbol(final GenericDescriptor descriptor) 1705fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 1706fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville validateSymbolName(descriptor); 1707fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1708fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final String fullName = descriptor.getFullName(); 1709fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final int dotpos = fullName.lastIndexOf('.'); 1710fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1711fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor old = descriptorsByName.put(fullName, descriptor); 1712fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (old != null) { 1713fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptorsByName.put(fullName, old); 1714fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1715fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (descriptor.getFile() == old.getFile()) { 1716fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (dotpos == -1) { 1717fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(descriptor, 1718fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + fullName + "\" is already defined."); 1719fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1720fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(descriptor, 1721fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + fullName.substring(dotpos + 1) + 1722fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "\" is already defined in \"" + 1723fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville fullName.substring(0, dotpos) + "\"."); 1724fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1725fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1726fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(descriptor, 1727fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + fullName + "\" is already defined in file \"" + 1728fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville old.getFile().getName() + "\"."); 1729fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1730fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1731fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1732fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1733fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1734fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Represents a package in the symbol table. We use PackageDescriptors 1735fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * just as placeholders so that someone cannot define, say, a message type 1736fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * that has the same name as an existing package. 1737fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1738fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private static final class PackageDescriptor implements GenericDescriptor { 1739fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public Message toProto() { return file.toProto(); } 1740fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getName() { return name; } 1741fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public String getFullName() { return fullName; } 1742fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public FileDescriptor getFile() { return file; } 1743fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1744fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville PackageDescriptor(final String name, final String fullName, 1745fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FileDescriptor file) { 1746fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.file = file; 1747fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.fullName = fullName; 1748fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.name = name; 1749fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1750fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1751fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final String name; 1752fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final String fullName; 1753fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final FileDescriptor file; 1754fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1755fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1756fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1757fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Adds a package to the symbol tables. If a package by the same name 1758fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * already exists, that is fine, but if some other kind of symbol exists 1759fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * under the same name, an exception is thrown. If the package has 1760fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * multiple components, this also adds the parent package(s). 1761fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1762fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void addPackage(final String fullName, final FileDescriptor file) 1763fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 1764fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final int dotpos = fullName.lastIndexOf('.'); 1765fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final String name; 1766fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (dotpos == -1) { 1767fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name = fullName; 1768fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1769fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville addPackage(fullName.substring(0, dotpos), file); 1770fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name = fullName.substring(dotpos + 1); 1771fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1772fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1773fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final GenericDescriptor old = 1774fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptorsByName.put(fullName, 1775fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville new PackageDescriptor(name, fullName, file)); 1776fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (old != null) { 1777fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptorsByName.put(fullName, old); 1778fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!(old instanceof PackageDescriptor)) { 1779fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(file, 1780fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + name + "\" is already defined (as something other than a " 1781fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville + "package) in file \"" + old.getFile().getName() + "\"."); 1782fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1783fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1784fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1785fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1786fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** A (GenericDescriptor, int) pair, used as a map key. */ 1787fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private static final class DescriptorIntPair { 1788fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final GenericDescriptor descriptor; 1789fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private final int number; 1790fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1791fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DescriptorIntPair(final GenericDescriptor descriptor, final int number) { 1792fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.descriptor = descriptor; 1793fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this.number = number; 1794fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1795fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1796fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville @Override 1797fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public int hashCode() { 1798fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return descriptor.hashCode() * ((1 << 16) - 1) + number; 1799fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1800fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville @Override 1801fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public boolean equals(final Object obj) { 1802fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!(obj instanceof DescriptorIntPair)) { 1803fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1804fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1805fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final DescriptorIntPair other = (DescriptorIntPair)obj; 1806fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return descriptor == other.descriptor && number == other.number; 1807fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1808fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1809fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1810fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1811fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Adds a field to the fieldsByNumber table. Throws an exception if a 1812fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * field with hte same containing type and number already exists. 1813fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1814fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void addFieldByNumber(final FieldDescriptor field) 1815fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 1816fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final DescriptorIntPair key = 1817fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville new DescriptorIntPair(field.getContainingType(), field.getNumber()); 1818fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final FieldDescriptor old = fieldsByNumber.put(key, field); 1819fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (old != null) { 1820fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville fieldsByNumber.put(key, old); 1821fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(field, 1822fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "Field number " + field.getNumber() + 1823fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "has already been used in \"" + 1824fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville field.getContainingType().getFullName() + 1825fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "\" by field \"" + old.getName() + "\"."); 1826fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1827fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1828fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1829fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1830fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Adds an enum value to the enumValuesByNumber table. If an enum value 1831fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * with the same type and number already exists, does nothing. (This is 1832fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * allowed; the first value define with the number takes precedence.) 1833fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1834fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void addEnumValueByNumber(final EnumValueDescriptor value) { 1835fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final DescriptorIntPair key = 1836fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville new DescriptorIntPair(value.getType(), value.getNumber()); 1837fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final EnumValueDescriptor old = enumValuesByNumber.put(key, value); 1838fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (old != null) { 1839fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enumValuesByNumber.put(key, old); 1840fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Not an error: Multiple enum values may have the same number, but 1841fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // we only want the first one in the map. 1842fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1843fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1844fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1845fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 1846fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Verifies that the descriptor's name is valid (i.e. it contains only 1847fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * letters, digits, and underscores, and does not start with a digit). 1848fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 1849fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville static void validateSymbolName(final GenericDescriptor descriptor) 1850fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throws DescriptorValidationException { 1851fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final String name = descriptor.getName(); 1852fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (name.length() == 0) { 1853fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(descriptor, "Missing name."); 1854fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1855fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville boolean valid = true; 1856fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < name.length(); i++) { 1857fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville final char c = name.charAt(i); 1858fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Non-ASCII characters are not valid in protobuf identifiers, even 1859fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // if they are letters or digits. 1860fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (c >= 128) { 1861fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville valid = false; 1862fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1863fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // First character must be letter or _. Subsequent characters may 1864fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // be letters, numbers, or digits. 1865fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (Character.isLetter(c) || c == '_' || 1866fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville (Character.isDigit(c) && i > 0)) { 1867fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Valid 1868fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1869fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville valid = false; 1870fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1871fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1872fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!valid) { 1873fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville throw new DescriptorValidationException(descriptor, 1874fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"' + name + "\" is not a valid identifier."); 1875fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1876fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1877fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1878fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1879fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 1880