diff options
Diffstat (limited to 'java/src/main/java/com/google/protobuf/Descriptors.java')
-rw-r--r-- | java/src/main/java/com/google/protobuf/Descriptors.java | 558 |
1 files changed, 315 insertions, 243 deletions
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java index 24499efb..0d5e47d1 100644 --- a/java/src/main/java/com/google/protobuf/Descriptors.java +++ b/java/src/main/java/com/google/protobuf/Descriptors.java @@ -37,11 +37,12 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.io.UnsupportedEncodingException; /** * Contains a collection of classes which describe protocol message types. * - * Every message type has a {@link Descriptors.Descriptor}, which lists all + * Every message type has a {@link Descriptor}, which lists all * its fields and other information about a type. You can get a message * type's descriptor by calling {@code MessageType.getDescriptor()}, or * (given a message object of the type) {@code message.getDescriptorForType()}. @@ -106,11 +107,13 @@ public final class Descriptors { public Descriptor findMessageTypeByName(String name) { // Don't allow looking up nested types. This will make optimization // easier later. - if (name.indexOf('.') != -1) return null; + if (name.indexOf('.') != -1) { + return null; + } if (getPackage().length() > 0) { - name = getPackage() + "." + name; + name = getPackage() + '.' + name; } - GenericDescriptor result = pool.findSymbol(name); + final GenericDescriptor result = pool.findSymbol(name); if (result != null && result instanceof Descriptor && result.getFile() == this) { return (Descriptor)result; @@ -128,11 +131,13 @@ public final class Descriptors { public EnumDescriptor findEnumTypeByName(String name) { // Don't allow looking up nested types. This will make optimization // easier later. - if (name.indexOf('.') != -1) return null; + if (name.indexOf('.') != -1) { + return null; + } if (getPackage().length() > 0) { - name = getPackage() + "." + name; + name = getPackage() + '.' + name; } - GenericDescriptor result = pool.findSymbol(name); + final GenericDescriptor result = pool.findSymbol(name); if (result != null && result instanceof EnumDescriptor && result.getFile() == this) { return (EnumDescriptor)result; @@ -150,11 +155,13 @@ public final class Descriptors { public ServiceDescriptor findServiceByName(String name) { // Don't allow looking up nested types. This will make optimization // easier later. - if (name.indexOf('.') != -1) return null; + if (name.indexOf('.') != -1) { + return null; + } if (getPackage().length() > 0) { - name = getPackage() + "." + name; + name = getPackage() + '.' + name; } - GenericDescriptor result = pool.findSymbol(name); + final GenericDescriptor result = pool.findSymbol(name); if (result != null && result instanceof ServiceDescriptor && result.getFile() == this) { return (ServiceDescriptor)result; @@ -171,11 +178,13 @@ public final class Descriptors { * @return The extension's descriptor, or {@code null} if not found. */ public FieldDescriptor findExtensionByName(String name) { - if (name.indexOf('.') != -1) return null; + if (name.indexOf('.') != -1) { + return null; + } if (getPackage().length() > 0) { - name = getPackage() + "." + name; + name = getPackage() + '.' + name; } - GenericDescriptor result = pool.findSymbol(name); + final GenericDescriptor result = pool.findSymbol(name); if (result != null && result instanceof FieldDescriptor && result.getFile() == this) { return (FieldDescriptor)result; @@ -196,8 +205,8 @@ public final class Descriptors { * because a field has an undefined type or because two messages * were defined with the same name. */ - public static FileDescriptor buildFrom(FileDescriptorProto proto, - FileDescriptor[] dependencies) + public static FileDescriptor buildFrom(final FileDescriptorProto proto, + final FileDescriptor[] dependencies) throws DescriptorValidationException { // Building decsriptors involves two steps: translating and linking. // In the translation step (implemented by FileDescriptor's @@ -208,8 +217,9 @@ public final class Descriptors { // FieldDescriptor for an embedded message contains a pointer directly // to the Descriptor for that message's type. We also detect undefined // types in the linking step. - DescriptorPool pool = new DescriptorPool(dependencies); - FileDescriptor result = new FileDescriptor(proto, dependencies, pool); + final DescriptorPool pool = new DescriptorPool(dependencies); + final FileDescriptor result = + new FileDescriptor(proto, dependencies, pool); if (dependencies.length != proto.getDependencyCount()) { throw new DescriptorValidationException(result, @@ -234,8 +244,8 @@ public final class Descriptors { * encoded in protocol buffer wire format. */ public static void internalBuildGeneratedFileFrom( - String descriptorData, FileDescriptor[] dependencies, - InternalDescriptorAssigner descriptorAssigner) { + final String descriptorData, final FileDescriptor[] dependencies, + final InternalDescriptorAssigner descriptorAssigner) { // Hack: We can't embed a raw byte array inside generated Java code // (at least, not efficiently), but we can embed Strings. So, the // protocol compiler embeds the FileDescriptorProto as a giant @@ -245,10 +255,10 @@ public final class Descriptors { // serialized form. So, if we convert it to bytes in ISO-8859-1, we // should get the original bytes that we want. - byte[] descriptorBytes; + final byte[] descriptorBytes; try { descriptorBytes = descriptorData.getBytes("ISO-8859-1"); - } catch (java.io.UnsupportedEncodingException e) { + } catch (UnsupportedEncodingException e) { throw new RuntimeException( "Standard encoding ISO-8859-1 not supported by JVM.", e); } @@ -261,7 +271,7 @@ public final class Descriptors { "Failed to parse protocol buffer descriptor for generated code.", e); } - FileDescriptor result; + final FileDescriptor result; try { result = buildFrom(proto, dependencies); } catch (DescriptorValidationException e) { @@ -269,7 +279,8 @@ public final class Descriptors { "Invalid embedded descriptor for \"" + proto.getName() + "\".", e); } - ExtensionRegistry registry = descriptorAssigner.assignDescriptors(result); + final ExtensionRegistry registry = + descriptorAssigner.assignDescriptors(result); if (registry != null) { // We must re-parse the proto using the registry. @@ -297,7 +308,7 @@ public final class Descriptors { * descriptor.proto. The callback may also return null to indicate that * no extensions are used in the decsriptor. */ - public static interface InternalDescriptorAssigner { + public interface InternalDescriptorAssigner { ExtensionRegistry assignDescriptors(FileDescriptor root); } @@ -309,9 +320,9 @@ public final class Descriptors { private final FileDescriptor[] dependencies; private final DescriptorPool pool; - private FileDescriptor(FileDescriptorProto proto, - FileDescriptor[] dependencies, - DescriptorPool pool) + private FileDescriptor(final FileDescriptorProto proto, + final FileDescriptor[] dependencies, + final DescriptorPool pool) throws DescriptorValidationException { this.pool = pool; this.proto = proto; @@ -344,16 +355,16 @@ public final class Descriptors { /** Look up and cross-link all field types, etc. */ private void crossLink() throws DescriptorValidationException { - for (int i = 0; i < messageTypes.length; i++) { - messageTypes[i].crossLink(); + for (final Descriptor messageType : messageTypes) { + messageType.crossLink(); } - for (int i = 0; i < services.length; i++) { - services[i].crossLink(); + for (final ServiceDescriptor service : services) { + service.crossLink(); } - for (int i = 0; i < extensions.length; i++) { - extensions[i].crossLink(); + for (final FieldDescriptor extension : extensions) { + extension.crossLink(); } } @@ -367,7 +378,7 @@ public final class Descriptors { * protos. So, we have to parse the descriptor protos a second time after * constructing the descriptors. */ - private void setProto(FileDescriptorProto proto) { + private void setProto(final FileDescriptorProto proto) { this.proto = proto; for (int i = 0; i < messageTypes.length; i++) { @@ -456,8 +467,9 @@ public final class Descriptors { } /** Determines if the given field number is an extension. */ - public boolean isExtensionNumber(int number) { - for (DescriptorProto.ExtensionRange range : proto.getExtensionRangeList()) { + public boolean isExtensionNumber(final int number) { + for (final DescriptorProto.ExtensionRange range : + proto.getExtensionRangeList()) { if (range.getStart() <= number && number < range.getEnd()) { return true; } @@ -470,8 +482,9 @@ public final class Descriptors { * @param name The unqualified name of the field (e.g. "foo"). * @return The field's descriptor, or {@code null} if not found. */ - public FieldDescriptor findFieldByName(String name) { - GenericDescriptor result = file.pool.findSymbol(fullName + "." + name); + public FieldDescriptor findFieldByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); if (result != null && result instanceof FieldDescriptor) { return (FieldDescriptor)result; } else { @@ -484,7 +497,7 @@ public final class Descriptors { * @param number The field number within this message type. * @return The field's descriptor, or {@code null} if not found. */ - public FieldDescriptor findFieldByNumber(int number) { + public FieldDescriptor findFieldByNumber(final int number) { return file.pool.fieldsByNumber.get( new DescriptorPool.DescriptorIntPair(this, number)); } @@ -494,8 +507,9 @@ public final class Descriptors { * @param name The unqualified name of the nested type (e.g. "Foo"). * @return The types's descriptor, or {@code null} if not found. */ - public Descriptor findNestedTypeByName(String name) { - GenericDescriptor result = file.pool.findSymbol(fullName + "." + name); + public Descriptor findNestedTypeByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); if (result != null && result instanceof Descriptor) { return (Descriptor)result; } else { @@ -508,8 +522,9 @@ public final class Descriptors { * @param name The unqualified name of the nested type (e.g. "Foo"). * @return The types's descriptor, or {@code null} if not found. */ - public EnumDescriptor findEnumTypeByName(String name) { - GenericDescriptor result = file.pool.findSymbol(fullName + "." + name); + public EnumDescriptor findEnumTypeByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); if (result != null && result instanceof EnumDescriptor) { return (EnumDescriptor)result; } else { @@ -527,38 +542,38 @@ public final class Descriptors { private final FieldDescriptor[] fields; private final FieldDescriptor[] extensions; - private Descriptor(DescriptorProto proto, - FileDescriptor file, - Descriptor parent, - int index) + private Descriptor(final DescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index) throws DescriptorValidationException { this.index = index; this.proto = proto; - this.fullName = computeFullName(file, parent, proto.getName()); + fullName = computeFullName(file, parent, proto.getName()); this.file = file; - this.containingType = parent; + containingType = parent; - this.nestedTypes = new Descriptor[proto.getNestedTypeCount()]; + nestedTypes = new Descriptor[proto.getNestedTypeCount()]; for (int i = 0; i < proto.getNestedTypeCount(); i++) { - this.nestedTypes[i] = new Descriptor( + nestedTypes[i] = new Descriptor( proto.getNestedType(i), file, this, i); } - this.enumTypes = new EnumDescriptor[proto.getEnumTypeCount()]; + enumTypes = new EnumDescriptor[proto.getEnumTypeCount()]; for (int i = 0; i < proto.getEnumTypeCount(); i++) { - this.enumTypes[i] = new EnumDescriptor( + enumTypes[i] = new EnumDescriptor( proto.getEnumType(i), file, this, i); } - this.fields = new FieldDescriptor[proto.getFieldCount()]; + fields = new FieldDescriptor[proto.getFieldCount()]; for (int i = 0; i < proto.getFieldCount(); i++) { - this.fields[i] = new FieldDescriptor( + fields[i] = new FieldDescriptor( proto.getField(i), file, this, i, false); } - this.extensions = new FieldDescriptor[proto.getExtensionCount()]; + extensions = new FieldDescriptor[proto.getExtensionCount()]; for (int i = 0; i < proto.getExtensionCount(); i++) { - this.extensions[i] = new FieldDescriptor( + extensions[i] = new FieldDescriptor( proto.getExtension(i), file, this, i, true); } @@ -567,21 +582,21 @@ public final class Descriptors { /** Look up and cross-link all field types, etc. */ private void crossLink() throws DescriptorValidationException { - for (int i = 0; i < nestedTypes.length; i++) { - nestedTypes[i].crossLink(); + for (final Descriptor nestedType : nestedTypes) { + nestedType.crossLink(); } - for (int i = 0; i < fields.length; i++) { - fields[i].crossLink(); + for (final FieldDescriptor field : fields) { + field.crossLink(); } - for (int i = 0; i < extensions.length; i++) { - extensions[i].crossLink(); + for (final FieldDescriptor extension : extensions) { + extension.crossLink(); } } - /** See {@link FileDescriptor.setProto}. */ - private void setProto(DescriptorProto proto) { + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final DescriptorProto proto) { this.proto = proto; for (int i = 0; i < nestedTypes.length; i++) { @@ -606,10 +621,11 @@ public final class Descriptors { /** Describes a field of a message type. */ public static final class FieldDescriptor - implements GenericDescriptor, Comparable<FieldDescriptor> { + implements GenericDescriptor, Comparable<FieldDescriptor>, + FieldSet.FieldDescriptorLite<FieldDescriptor> { /** * Get the index of this descriptor within its parent. - * @see Descriptors.Descriptor#getIndex() + * @see Descriptor#getIndex() */ public int getIndex() { return index; } @@ -624,7 +640,7 @@ public final class Descriptors { /** * Get the field's fully-qualified name. - * @see Descriptors.Descriptor#getFullName() + * @see Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -634,12 +650,27 @@ public final class Descriptors { */ public JavaType getJavaType() { return type.getJavaType(); } + /** For internal use only. */ + public WireFormat.JavaType getLiteJavaType() { + return getLiteType().getJavaType(); + } + /** Get the {@code FileDescriptor} containing this descriptor. */ public FileDescriptor getFile() { return file; } /** Get the field's declared type. */ public Type getType() { return type; } + /** For internal use only. */ + public WireFormat.FieldType getLiteType() { + return table[type.ordinal()]; + } + // I'm pretty sure values() constructs a new array every time, since there + // is nothing stopping the caller from mutating the array. Therefore we + // make a static copy here. + private static final WireFormat.FieldType[] table = + WireFormat.FieldType.values(); + /** Is this field declared required? */ public boolean isRequired() { return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REQUIRED; @@ -655,6 +686,11 @@ public final class Descriptors { return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED; } + /** Does this field have the {@code [packed = true]} option? */ + public boolean isPacked() { + return getOptions().getPacked(); + } + /** Returns true if the field had an explicitly-defined default value. */ public boolean hasDefaultValue() { return proto.hasDefaultValue(); } @@ -742,7 +778,7 @@ public final class Descriptors { * @return negative, zero, or positive if {@code this} is less than, * equal to, or greater than {@code other}, respectively. */ - public int compareTo(FieldDescriptor other) { + public int compareTo(final FieldDescriptor other) { if (other.containingType != containingType) { throw new IllegalArgumentException( "FieldDescriptors can only be compared to other FieldDescriptors " + @@ -765,7 +801,7 @@ public final class Descriptors { private EnumDescriptor enumType; private Object defaultValue; - public static enum Type { + public enum Type { DOUBLE (FieldDescriptorProto.Type.TYPE_DOUBLE , JavaType.DOUBLE ), FLOAT (FieldDescriptorProto.Type.TYPE_FLOAT , JavaType.FLOAT ), INT64 (FieldDescriptorProto.Type.TYPE_INT64 , JavaType.LONG ), @@ -785,11 +821,11 @@ public final class Descriptors { SINT32 (FieldDescriptorProto.Type.TYPE_SINT32 , JavaType.INT ), SINT64 (FieldDescriptorProto.Type.TYPE_SINT64 , JavaType.LONG ); - private Type(FieldDescriptorProto.Type proto, JavaType javaType) { + Type(final FieldDescriptorProto.Type proto, final JavaType javaType) { this.proto = proto; this.javaType = javaType; - if (this.ordinal() != proto.getNumber() - 1) { + if (ordinal() != proto.getNumber() - 1) { throw new RuntimeException( "descriptor.proto changed but Desrciptors.java wasn't updated."); } @@ -801,7 +837,7 @@ public final class Descriptors { public FieldDescriptorProto.Type toProto() { return proto; } public JavaType getJavaType() { return javaType; } - public static Type valueOf(FieldDescriptorProto.Type type) { + public static Type valueOf(final FieldDescriptorProto.Type type) { return values()[type.getNumber() - 1]; } } @@ -815,7 +851,7 @@ public final class Descriptors { } } - public static enum JavaType { + public enum JavaType { INT(0), LONG(0L), FLOAT(0F), @@ -826,7 +862,7 @@ public final class Descriptors { ENUM(null), MESSAGE(null); - private JavaType(Object defaultDefault) { + JavaType(final Object defaultDefault) { this.defaultDefault = defaultDefault; } @@ -834,22 +870,22 @@ public final class Descriptors { * The default default value for fields of this type, if it's a primitive * type. This is meant for use inside this file only, hence is private. */ - private Object defaultDefault; + private final Object defaultDefault; } - private FieldDescriptor(FieldDescriptorProto proto, - FileDescriptor file, - Descriptor parent, - int index, - boolean isExtension) + private FieldDescriptor(final FieldDescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index, + final boolean isExtension) throws DescriptorValidationException { this.index = index; this.proto = proto; - this.fullName = computeFullName(file, parent, proto.getName()); + fullName = computeFullName(file, parent, proto.getName()); this.file = file; if (proto.hasType()) { - this.type = Type.valueOf(proto.getType()); + type = Type.valueOf(proto.getType()); } if (getNumber() <= 0) { @@ -875,19 +911,19 @@ public final class Descriptors { throw new DescriptorValidationException(this, "FieldDescriptorProto.extendee not set for extension field."); } - this.containingType = null; // Will be filled in when cross-linking + containingType = null; // Will be filled in when cross-linking if (parent != null) { - this.extensionScope = parent; + extensionScope = parent; } else { - this.extensionScope = null; + extensionScope = null; } } else { if (proto.hasExtendee()) { throw new DescriptorValidationException(this, "FieldDescriptorProto.extendee set for non-extension field."); } - this.containingType = parent; - this.extensionScope = null; + containingType = parent; + extensionScope = null; } file.pool.addSymbol(this); @@ -896,43 +932,44 @@ public final class Descriptors { /** Look up and cross-link all field types, etc. */ private void crossLink() throws DescriptorValidationException { if (proto.hasExtendee()) { - GenericDescriptor extendee = + final GenericDescriptor extendee = file.pool.lookupSymbol(proto.getExtendee(), this); if (!(extendee instanceof Descriptor)) { throw new DescriptorValidationException(this, - "\"" + proto.getExtendee() + "\" is not a message type."); + '\"' + proto.getExtendee() + "\" is not a message type."); } - this.containingType = (Descriptor)extendee; + containingType = (Descriptor)extendee; if (!getContainingType().isExtensionNumber(getNumber())) { throw new DescriptorValidationException(this, - "\"" + getContainingType().getFullName() + "\" does not declare " + - getNumber() + " as an extension number."); + '\"' + getContainingType().getFullName() + + "\" does not declare " + getNumber() + + " as an extension number."); } } if (proto.hasTypeName()) { - GenericDescriptor typeDescriptor = + final GenericDescriptor typeDescriptor = file.pool.lookupSymbol(proto.getTypeName(), this); if (!proto.hasType()) { // Choose field type based on symbol. if (typeDescriptor instanceof Descriptor) { - this.type = Type.MESSAGE; + type = Type.MESSAGE; } else if (typeDescriptor instanceof EnumDescriptor) { - this.type = Type.ENUM; + type = Type.ENUM; } else { throw new DescriptorValidationException(this, - "\"" + proto.getTypeName() + "\" is not a type."); + '\"' + proto.getTypeName() + "\" is not a type."); } } if (getJavaType() == JavaType.MESSAGE) { if (!(typeDescriptor instanceof Descriptor)) { throw new DescriptorValidationException(this, - "\"" + proto.getTypeName() + "\" is not a message type."); + '\"' + proto.getTypeName() + "\" is not a message type."); } - this.messageType = (Descriptor)typeDescriptor; + messageType = (Descriptor)typeDescriptor; if (proto.hasDefaultValue()) { throw new DescriptorValidationException(this, @@ -941,9 +978,9 @@ public final class Descriptors { } else if (getJavaType() == JavaType.ENUM) { if (!(typeDescriptor instanceof EnumDescriptor)) { throw new DescriptorValidationException(this, - "\"" + proto.getTypeName() + "\" is not an enum type."); + '\"' + proto.getTypeName() + "\" is not an enum type."); } - this.enumType = (EnumDescriptor)typeDescriptor; + enumType = (EnumDescriptor)typeDescriptor; } else { throw new DescriptorValidationException(this, "Field with primitive type has type_name."); @@ -972,20 +1009,18 @@ public final class Descriptors { defaultValue = TextFormat.parseInt32(proto.getDefaultValue()); break; case UINT32: - case FIXED32: { + case FIXED32: defaultValue = TextFormat.parseUInt32(proto.getDefaultValue()); break; - } case INT64: case SINT64: case SFIXED64: defaultValue = TextFormat.parseInt64(proto.getDefaultValue()); break; case UINT64: - case FIXED64: { + case FIXED64: defaultValue = TextFormat.parseUInt64(proto.getDefaultValue()); break; - } case FLOAT: defaultValue = Float.valueOf(proto.getDefaultValue()); break; @@ -1002,9 +1037,9 @@ public final class Descriptors { try { defaultValue = TextFormat.unescapeBytes(proto.getDefaultValue()); - } catch (TextFormat.InvalidEscapeSequence e) { + } catch (TextFormat.InvalidEscapeSequenceException e) { throw new DescriptorValidationException(this, - "Couldn't parse default value: " + e.getMessage()); + "Couldn't parse default value: " + e.getMessage(), e); } break; case ENUM: @@ -1012,7 +1047,7 @@ public final class Descriptors { if (defaultValue == null) { throw new DescriptorValidationException(this, "Unknown enum default value: \"" + - proto.getDefaultValue() + "\""); + proto.getDefaultValue() + '\"'); } break; case MESSAGE: @@ -1021,17 +1056,17 @@ public final class Descriptors { "Message type had default value."); } } catch (NumberFormatException e) { - DescriptorValidationException validationException = + final DescriptorValidationException validationException = new DescriptorValidationException(this, "Could not parse default value: \"" + - proto.getDefaultValue() + "\""); + proto.getDefaultValue() + '\"'); validationException.initCause(e); throw validationException; } } else { // Determine the default default for this field. if (isRepeated()) { - defaultValue = Collections.EMPTY_LIST; + defaultValue = Collections.emptyList(); } else { switch (getJavaType()) { case ENUM: @@ -1067,19 +1102,32 @@ public final class Descriptors { } } - /** See {@link FileDescriptor.setProto}. */ - private void setProto(FieldDescriptorProto proto) { + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final FieldDescriptorProto proto) { this.proto = proto; } + + /** + * For internal use only. This is to satisfy the FieldDescriptorLite + * interface. + */ + @Override + public MessageLite.Builder internalMergeFrom( + MessageLite.Builder to, MessageLite from) { + // FieldDescriptors are only used with non-lite messages so we can just + // down-cast and call mergeFrom directly. + return ((Message.Builder) to).mergeFrom((Message) from); + } } // ================================================================= /** Describes an enum type. */ - public static final class EnumDescriptor implements GenericDescriptor { + public static final class EnumDescriptor + implements GenericDescriptor, Internal.EnumLiteMap<EnumValueDescriptor> { /** * Get the index of this descriptor within its parent. - * @see Descriptors.Descriptor#getIndex() + * @see Descriptor#getIndex() */ public int getIndex() { return index; } @@ -1091,7 +1139,7 @@ public final class Descriptors { /** * Get the type's fully-qualified name. - * @see Descriptors.Descriptor#getFullName() + * @see Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -1114,8 +1162,9 @@ public final class Descriptors { * @param name The unqualified name of the value (e.g. "FOO"). * @return the value's decsriptor, or {@code null} if not found. */ - public EnumValueDescriptor findValueByName(String name) { - GenericDescriptor result = file.pool.findSymbol(fullName + "." + name); + public EnumValueDescriptor findValueByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); if (result != null && result instanceof EnumValueDescriptor) { return (EnumValueDescriptor)result; } else { @@ -1129,7 +1178,7 @@ public final class Descriptors { * @param number The value's number. * @return the value's decsriptor, or {@code null} if not found. */ - public EnumValueDescriptor findValueByNumber(int number) { + public EnumValueDescriptor findValueByNumber(final int number) { return file.pool.enumValuesByNumber.get( new DescriptorPool.DescriptorIntPair(this, number)); } @@ -1141,16 +1190,16 @@ public final class Descriptors { private final Descriptor containingType; private EnumValueDescriptor[] values; - private EnumDescriptor(EnumDescriptorProto proto, - FileDescriptor file, - Descriptor parent, - int index) + private EnumDescriptor(final EnumDescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index) throws DescriptorValidationException { this.index = index; this.proto = proto; - this.fullName = computeFullName(file, parent, proto.getName()); + fullName = computeFullName(file, parent, proto.getName()); this.file = file; - this.containingType = parent; + containingType = parent; if (proto.getValueCount() == 0) { // We cannot allow enums with no values because this would mean there @@ -1161,15 +1210,15 @@ public final class Descriptors { values = new EnumValueDescriptor[proto.getValueCount()]; for (int i = 0; i < proto.getValueCount(); i++) { - this.values[i] = new EnumValueDescriptor( + values[i] = new EnumValueDescriptor( proto.getValue(i), file, this, i); } file.pool.addSymbol(this); } - /** See {@link FileDescriptor.setProto}. */ - private void setProto(EnumDescriptorProto proto) { + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final EnumDescriptorProto proto) { this.proto = proto; for (int i = 0; i < values.length; i++) { @@ -1186,10 +1235,11 @@ public final class Descriptors { * with the same number after the first become aliases of the first. * However, they still have independent EnumValueDescriptors. */ - public static final class EnumValueDescriptor implements GenericDescriptor { + public static final class EnumValueDescriptor + implements GenericDescriptor, Internal.EnumLite { /** * Get the index of this descriptor within its parent. - * @see Descriptors.Descriptor#getIndex() + * @see Descriptor#getIndex() */ public int getIndex() { return index; } @@ -1204,7 +1254,7 @@ public final class Descriptors { /** * Get the value's fully-qualified name. - * @see Descriptors.Descriptor#getFullName() + * @see Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -1225,24 +1275,24 @@ public final class Descriptors { private final FileDescriptor file; private final EnumDescriptor type; - private EnumValueDescriptor(EnumValueDescriptorProto proto, - FileDescriptor file, - EnumDescriptor parent, - int index) + private EnumValueDescriptor(final EnumValueDescriptorProto proto, + final FileDescriptor file, + final EnumDescriptor parent, + final int index) throws DescriptorValidationException { this.index = index; this.proto = proto; this.file = file; - this.type = parent; + type = parent; - this.fullName = parent.getFullName() + "." + proto.getName(); + fullName = parent.getFullName() + '.' + proto.getName(); file.pool.addSymbol(this); file.pool.addEnumValueByNumber(this); } - /** See {@link FileDescriptor.setProto}. */ - private void setProto(EnumValueDescriptorProto proto) { + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final EnumValueDescriptorProto proto) { this.proto = proto; } } @@ -1265,7 +1315,7 @@ public final class Descriptors { /** * Get the type's fully-qualified name. - * @see Descriptors.Descriptor#getFullName() + * @see Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -1285,8 +1335,9 @@ public final class Descriptors { * @param name The unqualified name of the method (e.g. "Foo"). * @return the method's decsriptor, or {@code null} if not found. */ - public MethodDescriptor findMethodByName(String name) { - GenericDescriptor result = file.pool.findSymbol(fullName + "." + name); + public MethodDescriptor findMethodByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); if (result != null && result instanceof MethodDescriptor) { return (MethodDescriptor)result; } else { @@ -1300,18 +1351,18 @@ public final class Descriptors { private final FileDescriptor file; private MethodDescriptor[] methods; - private ServiceDescriptor(ServiceDescriptorProto proto, - FileDescriptor file, - int index) + private ServiceDescriptor(final ServiceDescriptorProto proto, + final FileDescriptor file, + final int index) throws DescriptorValidationException { this.index = index; this.proto = proto; - this.fullName = computeFullName(file, null, proto.getName()); + fullName = computeFullName(file, null, proto.getName()); this.file = file; - this.methods = new MethodDescriptor[proto.getMethodCount()]; + methods = new MethodDescriptor[proto.getMethodCount()]; for (int i = 0; i < proto.getMethodCount(); i++) { - this.methods[i] = new MethodDescriptor( + methods[i] = new MethodDescriptor( proto.getMethod(i), file, this, i); } @@ -1319,13 +1370,13 @@ public final class Descriptors { } private void crossLink() throws DescriptorValidationException { - for (int i = 0; i < methods.length; i++) { - methods[i].crossLink(); + for (final MethodDescriptor method : methods) { + method.crossLink(); } } - /** See {@link FileDescriptor.setProto}. */ - private void setProto(ServiceDescriptorProto proto) { + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final ServiceDescriptorProto proto) { this.proto = proto; for (int i = 0; i < methods.length; i++) { @@ -1354,7 +1405,7 @@ public final class Descriptors { /** * Get the method's fully-qualified name. - * @see Descriptors.Descriptor#getFullName() + * @see Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -1385,54 +1436,54 @@ public final class Descriptors { private Descriptor inputType; private Descriptor outputType; - private MethodDescriptor(MethodDescriptorProto proto, - FileDescriptor file, - ServiceDescriptor parent, - int index) + private MethodDescriptor(final MethodDescriptorProto proto, + final FileDescriptor file, + final ServiceDescriptor parent, + final int index) throws DescriptorValidationException { this.index = index; this.proto = proto; this.file = file; - this.service = parent; + service = parent; - this.fullName = parent.getFullName() + "." + proto.getName(); + fullName = parent.getFullName() + '.' + proto.getName(); file.pool.addSymbol(this); } private void crossLink() throws DescriptorValidationException { - GenericDescriptor inputType = + final GenericDescriptor input = file.pool.lookupSymbol(proto.getInputType(), this); - if (!(inputType instanceof Descriptor)) { + if (!(input instanceof Descriptor)) { throw new DescriptorValidationException(this, - "\"" + proto.getInputType() + "\" is not a message type."); + '\"' + proto.getInputType() + "\" is not a message type."); } - this.inputType = (Descriptor)inputType; + inputType = (Descriptor)input; - GenericDescriptor outputType = + final GenericDescriptor output = file.pool.lookupSymbol(proto.getOutputType(), this); - if (!(outputType instanceof Descriptor)) { + if (!(output instanceof Descriptor)) { throw new DescriptorValidationException(this, - "\"" + proto.getOutputType() + "\" is not a message type."); + '\"' + proto.getOutputType() + "\" is not a message type."); } - this.outputType = (Descriptor)outputType; + outputType = (Descriptor)output; } - /** See {@link FileDescriptor.setProto}. */ - private void setProto(MethodDescriptorProto proto) { + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final MethodDescriptorProto proto) { this.proto = proto; } } // ================================================================= - private static String computeFullName(FileDescriptor file, - Descriptor parent, - String name) { + private static String computeFullName(final FileDescriptor file, + final Descriptor parent, + final String name) { if (parent != null) { - return parent.getFullName() + "." + name; + return parent.getFullName() + '.' + name; } else if (file.getPackage().length() > 0) { - return file.getPackage() + "." + name; + return file.getPackage() + '.' + name; } else { return name; } @@ -1444,7 +1495,7 @@ public final class Descriptors { * All descriptors except {@code FileDescriptor} implement this to make * {@code DescriptorPool}'s life easier. */ - private static interface GenericDescriptor { + private interface GenericDescriptor { Message toProto(); String getName(); String getFullName(); @@ -1456,6 +1507,8 @@ public final class Descriptors { * are not valid. */ public static class DescriptorValidationException extends Exception { + private static final long serialVersionUID = 5750205775490483148L; + /** Gets the full name of the descriptor where the error occurred. */ public String getProblemSymbolName() { return name; } @@ -1473,27 +1526,36 @@ public final class Descriptors { private final Message proto; private final String description; - private DescriptorValidationException(GenericDescriptor problemDescriptor, - String description) { - super(problemDescriptor.getFullName() + ": " + description); + private DescriptorValidationException( + final GenericDescriptor problemDescriptor, + final String description) { + this(problemDescriptor, description, null); + } + + private DescriptorValidationException( + final GenericDescriptor problemDescriptor, + final String description, + final Throwable cause) { + super(problemDescriptor.getFullName() + ": " + description, cause); // Note that problemDescriptor may be partially uninitialized, so we // don't want to expose it directly to the user. So, we only provide // the name and the original proto. - this.name = problemDescriptor.getFullName(); - this.proto = problemDescriptor.toProto(); + name = problemDescriptor.getFullName(); + proto = problemDescriptor.toProto(); this.description = description; } - private DescriptorValidationException(FileDescriptor problemDescriptor, - String description) { + private DescriptorValidationException( + final FileDescriptor problemDescriptor, + final String description) { super(problemDescriptor.getName() + ": " + description); // Note that problemDescriptor may be partially uninitialized, so we // don't want to expose it directly to the user. So, we only provide // the name and the original proto. - this.name = problemDescriptor.getName(); - this.proto = problemDescriptor.toProto(); + name = problemDescriptor.getName(); + proto = problemDescriptor.toProto(); this.description = description; } } @@ -1505,16 +1567,16 @@ public final class Descriptors { * descriptors defined in a particular file. */ private static final class DescriptorPool { - DescriptorPool(FileDescriptor[] dependencies) { + DescriptorPool(final FileDescriptor[] dependencies) { this.dependencies = new DescriptorPool[dependencies.length]; for (int i = 0; i < dependencies.length; i++) { this.dependencies[i] = dependencies[i].pool; } - for (int i = 0; i < dependencies.length; i++) { + for (final FileDescriptor dependency : dependencies) { try { - addPackage(dependencies[i].getPackage(), dependencies[i]); + addPackage(dependency.getPackage(), dependency); } catch (DescriptorValidationException e) { // Can't happen, because addPackage() only fails when the name // conflicts with a non-package, but we have not yet added any @@ -1524,23 +1586,27 @@ public final class Descriptors { } } - final DescriptorPool[] dependencies; + private final DescriptorPool[] dependencies; - final Map<String, GenericDescriptor> descriptorsByName = + private final Map<String, GenericDescriptor> descriptorsByName = new HashMap<String, GenericDescriptor>(); - final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber = + private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber = new HashMap<DescriptorIntPair, FieldDescriptor>(); - final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber = - new HashMap<DescriptorIntPair, EnumValueDescriptor>(); + private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber + = new HashMap<DescriptorIntPair, EnumValueDescriptor>(); /** Find a generic descriptor by fully-qualified name. */ - GenericDescriptor findSymbol(String fullName) { + GenericDescriptor findSymbol(final String fullName) { GenericDescriptor result = descriptorsByName.get(fullName); - if (result != null) return result; + if (result != null) { + return result; + } - for (int i = 0; i < dependencies.length; i++) { - result = dependencies[i].descriptorsByName.get(fullName); - if (result != null) return result; + for (final DescriptorPool dependency : dependencies) { + result = dependency.descriptorsByName.get(fullName); + if (result != null) { + return result; + } } return null; @@ -1552,8 +1618,8 @@ public final class Descriptors { * partially-qualified, or unqualified. C++-like name lookup semantics * are used to search for the matching descriptor. */ - GenericDescriptor lookupSymbol(String name, - GenericDescriptor relativeTo) + GenericDescriptor lookupSymbol(final String name, + final GenericDescriptor relativeTo) throws DescriptorValidationException { // TODO(kenton): This could be optimized in a number of ways. @@ -1564,8 +1630,8 @@ public final class Descriptors { } else { // If "name" is a compound identifier, we want to search for the // first component of it, then search within it for the rest. - int firstPartLength = name.indexOf('.'); - String firstPart; + final int firstPartLength = name.indexOf('.'); + final String firstPart; if (firstPartLength == -1) { firstPart = name; } else { @@ -1574,11 +1640,12 @@ public final class Descriptors { // We will search each parent scope of "relativeTo" looking for the // symbol. - StringBuilder scopeToTry = new StringBuilder(relativeTo.getFullName()); + final StringBuilder scopeToTry = + new StringBuilder(relativeTo.getFullName()); while (true) { // Chop off the last component of the scope. - int dotpos = scopeToTry.lastIndexOf("."); + final int dotpos = scopeToTry.lastIndexOf("."); if (dotpos == -1) { result = findSymbol(name); break; @@ -1609,7 +1676,7 @@ public final class Descriptors { if (result == null) { throw new DescriptorValidationException(relativeTo, - "\"" + name + "\" is not defined."); + '\"' + name + "\" is not defined."); } else { return result; } @@ -1619,30 +1686,30 @@ public final class Descriptors { * Adds a symbol to the symbol table. If a symbol with the same name * already exists, throws an error. */ - void addSymbol(GenericDescriptor descriptor) + void addSymbol(final GenericDescriptor descriptor) throws DescriptorValidationException { validateSymbolName(descriptor); - String fullName = descriptor.getFullName(); - int dotpos = fullName.lastIndexOf('.'); + final String fullName = descriptor.getFullName(); + final int dotpos = fullName.lastIndexOf('.'); - GenericDescriptor old = descriptorsByName.put(fullName, descriptor); + final GenericDescriptor old = descriptorsByName.put(fullName, descriptor); if (old != null) { descriptorsByName.put(fullName, old); if (descriptor.getFile() == old.getFile()) { if (dotpos == -1) { throw new DescriptorValidationException(descriptor, - "\"" + fullName + "\" is already defined."); + '\"' + fullName + "\" is already defined."); } else { throw new DescriptorValidationException(descriptor, - "\"" + fullName.substring(dotpos + 1) + + '\"' + fullName.substring(dotpos + 1) + "\" is already defined in \"" + fullName.substring(0, dotpos) + "\"."); } } else { throw new DescriptorValidationException(descriptor, - "\"" + fullName + "\" is already defined in file \"" + + '\"' + fullName + "\" is already defined in file \"" + old.getFile().getName() + "\"."); } } @@ -1653,21 +1720,22 @@ public final class Descriptors { * just as placeholders so that someone cannot define, say, a message type * that has the same name as an existing package. */ - static final class PackageDescriptor implements GenericDescriptor { + private static final class PackageDescriptor implements GenericDescriptor { public Message toProto() { return file.toProto(); } public String getName() { return name; } public String getFullName() { return fullName; } public FileDescriptor getFile() { return file; } - PackageDescriptor(String name, String fullName, FileDescriptor file) { + PackageDescriptor(final String name, final String fullName, + final FileDescriptor file) { this.file = file; this.fullName = fullName; this.name = name; } - String name; - String fullName; - FileDescriptor file; + private final String name; + private final String fullName; + private final FileDescriptor file; } /** @@ -1676,46 +1744,50 @@ public final class Descriptors { * under the same name, an exception is thrown. If the package has * multiple components, this also adds the parent package(s). */ - void addPackage(String fullName, FileDescriptor file) + void addPackage(final String fullName, final FileDescriptor file) throws DescriptorValidationException { - int dotpos = fullName.lastIndexOf('.'); - String name; - if (dotpos != -1) { + final int dotpos = fullName.lastIndexOf('.'); + final String name; + if (dotpos == -1) { + name = fullName; + } else { addPackage(fullName.substring(0, dotpos), file); name = fullName.substring(dotpos + 1); - } else { - name = fullName; } - GenericDescriptor old = + final GenericDescriptor old = descriptorsByName.put(fullName, new PackageDescriptor(name, fullName, file)); if (old != null) { descriptorsByName.put(fullName, old); if (!(old instanceof PackageDescriptor)) { throw new DescriptorValidationException(file, - "\"" + name + "\" is already defined (as something other than a " + - "package) in file \"" + old.getFile().getName() + "\"."); + '\"' + name + "\" is already defined (as something other than a " + + "package) in file \"" + old.getFile().getName() + "\"."); } } } /** A (GenericDescriptor, int) pair, used as a map key. */ - static final class DescriptorIntPair { - final GenericDescriptor descriptor; - final int number; + private static final class DescriptorIntPair { + private final GenericDescriptor descriptor; + private final int number; - DescriptorIntPair(GenericDescriptor descriptor, int number) { + DescriptorIntPair(final GenericDescriptor descriptor, final int number) { this.descriptor = descriptor; this.number = number; } + @Override public int hashCode() { return descriptor.hashCode() * ((1 << 16) - 1) + number; } - public boolean equals(Object obj) { - if (!(obj instanceof DescriptorIntPair)) return false; - DescriptorIntPair other = (DescriptorIntPair)obj; + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof DescriptorIntPair)) { + return false; + } + final DescriptorIntPair other = (DescriptorIntPair)obj; return descriptor == other.descriptor && number == other.number; } } @@ -1724,11 +1796,11 @@ public final class Descriptors { * Adds a field to the fieldsByNumber table. Throws an exception if a * field with hte same containing type and number already exists. */ - void addFieldByNumber(FieldDescriptor field) + void addFieldByNumber(final FieldDescriptor field) throws DescriptorValidationException { - DescriptorIntPair key = + final DescriptorIntPair key = new DescriptorIntPair(field.getContainingType(), field.getNumber()); - FieldDescriptor old = fieldsByNumber.put(key, field); + final FieldDescriptor old = fieldsByNumber.put(key, field); if (old != null) { fieldsByNumber.put(key, old); throw new DescriptorValidationException(field, @@ -1744,10 +1816,10 @@ public final class Descriptors { * with the same type and number already exists, does nothing. (This is * allowed; the first value define with the number takes precedence.) */ - void addEnumValueByNumber(EnumValueDescriptor value) { - DescriptorIntPair key = + void addEnumValueByNumber(final EnumValueDescriptor value) { + final DescriptorIntPair key = new DescriptorIntPair(value.getType(), value.getNumber()); - EnumValueDescriptor old = enumValuesByNumber.put(key, value); + final EnumValueDescriptor old = enumValuesByNumber.put(key, value); if (old != null) { enumValuesByNumber.put(key, old); // Not an error: Multiple enum values may have the same number, but @@ -1759,15 +1831,15 @@ public final class Descriptors { * Verifies that the descriptor's name is valid (i.e. it contains only * letters, digits, and underscores, and does not start with a digit). */ - void validateSymbolName(GenericDescriptor descriptor) - throws DescriptorValidationException { - String name = descriptor.getName(); + static void validateSymbolName(final GenericDescriptor descriptor) + throws DescriptorValidationException { + final String name = descriptor.getName(); if (name.length() == 0) { throw new DescriptorValidationException(descriptor, "Missing name."); } else { boolean valid = true; for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); + final char c = name.charAt(i); // Non-ASCII characters are not valid in protobuf identifiers, even // if they are letters or digits. if (c >= 128) { @@ -1784,7 +1856,7 @@ public final class Descriptors { } if (!valid) { throw new DescriptorValidationException(descriptor, - "\"" + name + "\" is not a valid identifier."); + '\"' + name + "\" is not a valid identifier."); } } } |