~statik/ubuntu/maverick/protobuf/A

« back to all changes in this revision

Viewing changes to java/src/main/java/com/google/protobuf/Descriptors.java

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2010-02-11 11:13:19 UTC
  • mfrom: (2.2.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100211111319-zdn8hmw0gh8s4cf8
Tags: 2.2.0a-0.1ubuntu1
* Merge from Debian testing.
* Remaining Ubuntu changes:
  - Don't use python2.4.
* Ubuntu changes dropped:
  - Disable death tests on Itanium, fixed upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
import java.util.HashMap;
38
38
import java.util.List;
39
39
import java.util.Map;
 
40
import java.io.UnsupportedEncodingException;
40
41
 
41
42
/**
42
43
 * Contains a collection of classes which describe protocol message types.
43
44
 *
44
 
 * Every message type has a {@link Descriptors.Descriptor}, which lists all
 
45
 * Every message type has a {@link Descriptor}, which lists all
45
46
 * its fields and other information about a type.  You can get a message
46
47
 * type's descriptor by calling {@code MessageType.getDescriptor()}, or
47
48
 * (given a message object of the type) {@code message.getDescriptorForType()}.
106
107
    public Descriptor findMessageTypeByName(String name) {
107
108
      // Don't allow looking up nested types.  This will make optimization
108
109
      // easier later.
109
 
      if (name.indexOf('.') != -1) return null;
 
110
      if (name.indexOf('.') != -1) {
 
111
        return null;
 
112
      }
110
113
      if (getPackage().length() > 0) {
111
 
        name = getPackage() + "." + name;
 
114
        name = getPackage() + '.' + name;
112
115
      }
113
 
      GenericDescriptor result = pool.findSymbol(name);
 
116
      final GenericDescriptor result = pool.findSymbol(name);
114
117
      if (result != null && result instanceof Descriptor &&
115
118
          result.getFile() == this) {
116
119
        return (Descriptor)result;
128
131
    public EnumDescriptor findEnumTypeByName(String name) {
129
132
      // Don't allow looking up nested types.  This will make optimization
130
133
      // easier later.
131
 
      if (name.indexOf('.') != -1) return null;
 
134
      if (name.indexOf('.') != -1) {
 
135
        return null;
 
136
      }
132
137
      if (getPackage().length() > 0) {
133
 
        name = getPackage() + "." + name;
 
138
        name = getPackage() + '.' + name;
134
139
      }
135
 
      GenericDescriptor result = pool.findSymbol(name);
 
140
      final GenericDescriptor result = pool.findSymbol(name);
136
141
      if (result != null && result instanceof EnumDescriptor &&
137
142
          result.getFile() == this) {
138
143
        return (EnumDescriptor)result;
150
155
    public ServiceDescriptor findServiceByName(String name) {
151
156
      // Don't allow looking up nested types.  This will make optimization
152
157
      // easier later.
153
 
      if (name.indexOf('.') != -1) return null;
 
158
      if (name.indexOf('.') != -1) {
 
159
        return null;
 
160
      }
154
161
      if (getPackage().length() > 0) {
155
 
        name = getPackage() + "." + name;
 
162
        name = getPackage() + '.' + name;
156
163
      }
157
 
      GenericDescriptor result = pool.findSymbol(name);
 
164
      final GenericDescriptor result = pool.findSymbol(name);
158
165
      if (result != null && result instanceof ServiceDescriptor &&
159
166
          result.getFile() == this) {
160
167
        return (ServiceDescriptor)result;
171
178
     * @return The extension's descriptor, or {@code null} if not found.
172
179
     */
173
180
    public FieldDescriptor findExtensionByName(String name) {
174
 
      if (name.indexOf('.') != -1) return null;
 
181
      if (name.indexOf('.') != -1) {
 
182
        return null;
 
183
      }
175
184
      if (getPackage().length() > 0) {
176
 
        name = getPackage() + "." + name;
 
185
        name = getPackage() + '.' + name;
177
186
      }
178
 
      GenericDescriptor result = pool.findSymbol(name);
 
187
      final GenericDescriptor result = pool.findSymbol(name);
179
188
      if (result != null && result instanceof FieldDescriptor &&
180
189
          result.getFile() == this) {
181
190
        return (FieldDescriptor)result;
196
205
     *           because a field has an undefined type or because two messages
197
206
     *           were defined with the same name.
198
207
     */
199
 
    public static FileDescriptor buildFrom(FileDescriptorProto proto,
200
 
                                           FileDescriptor[] dependencies)
 
208
    public static FileDescriptor buildFrom(final FileDescriptorProto proto,
 
209
                                           final FileDescriptor[] dependencies)
201
210
                                    throws DescriptorValidationException {
202
211
      // Building decsriptors involves two steps:  translating and linking.
203
212
      // In the translation step (implemented by FileDescriptor's
208
217
      // FieldDescriptor for an embedded message contains a pointer directly
209
218
      // to the Descriptor for that message's type.  We also detect undefined
210
219
      // types in the linking step.
211
 
      DescriptorPool pool = new DescriptorPool(dependencies);
212
 
      FileDescriptor result = new FileDescriptor(proto, dependencies, pool);
 
220
      final DescriptorPool pool = new DescriptorPool(dependencies);
 
221
      final FileDescriptor result =
 
222
          new FileDescriptor(proto, dependencies, pool);
213
223
 
214
224
      if (dependencies.length != proto.getDependencyCount()) {
215
225
        throw new DescriptorValidationException(result,
234
244
     * encoded in protocol buffer wire format.
235
245
     */
236
246
    public static void internalBuildGeneratedFileFrom(
237
 
        String descriptorData, FileDescriptor[] dependencies,
238
 
        InternalDescriptorAssigner descriptorAssigner) {
 
247
        final String[] descriptorDataParts,
 
248
        final FileDescriptor[] dependencies,
 
249
        final InternalDescriptorAssigner descriptorAssigner) {
239
250
      // Hack:  We can't embed a raw byte array inside generated Java code
240
251
      //   (at least, not efficiently), but we can embed Strings.  So, the
241
252
      //   protocol compiler embeds the FileDescriptorProto as a giant
245
256
      //   serialized form.  So, if we convert it to bytes in ISO-8859-1, we
246
257
      //   should get the original bytes that we want.
247
258
 
248
 
      byte[] descriptorBytes;
 
259
      // descriptorData may contain multiple strings in order to get around the
 
260
      // Java 64k string literal limit.
 
261
      StringBuilder descriptorData = new StringBuilder();
 
262
      for (String part : descriptorDataParts) {
 
263
        descriptorData.append(part);
 
264
      }
 
265
 
 
266
      final byte[] descriptorBytes;
249
267
      try {
250
 
        descriptorBytes = descriptorData.getBytes("ISO-8859-1");
251
 
      } catch (java.io.UnsupportedEncodingException e) {
 
268
        descriptorBytes = descriptorData.toString().getBytes("ISO-8859-1");
 
269
      } catch (UnsupportedEncodingException e) {
252
270
        throw new RuntimeException(
253
271
          "Standard encoding ISO-8859-1 not supported by JVM.", e);
254
272
      }
261
279
          "Failed to parse protocol buffer descriptor for generated code.", e);
262
280
      }
263
281
 
264
 
      FileDescriptor result;
 
282
      final FileDescriptor result;
265
283
      try {
266
284
        result = buildFrom(proto, dependencies);
267
285
      } catch (DescriptorValidationException e) {
269
287
          "Invalid embedded descriptor for \"" + proto.getName() + "\".", e);
270
288
      }
271
289
 
272
 
      ExtensionRegistry registry = descriptorAssigner.assignDescriptors(result);
 
290
      final ExtensionRegistry registry =
 
291
          descriptorAssigner.assignDescriptors(result);
273
292
 
274
293
      if (registry != null) {
275
294
        // We must re-parse the proto using the registry.
297
316
     * descriptor.proto.  The callback may also return null to indicate that
298
317
     * no extensions are used in the decsriptor.
299
318
     */
300
 
    public static interface InternalDescriptorAssigner {
 
319
    public interface InternalDescriptorAssigner {
301
320
      ExtensionRegistry assignDescriptors(FileDescriptor root);
302
321
    }
303
322
 
309
328
    private final FileDescriptor[] dependencies;
310
329
    private final DescriptorPool pool;
311
330
 
312
 
    private FileDescriptor(FileDescriptorProto proto,
313
 
                           FileDescriptor[] dependencies,
314
 
                           DescriptorPool pool)
 
331
    private FileDescriptor(final FileDescriptorProto proto,
 
332
                           final FileDescriptor[] dependencies,
 
333
                           final DescriptorPool pool)
315
334
                    throws DescriptorValidationException {
316
335
      this.pool = pool;
317
336
      this.proto = proto;
344
363
 
345
364
    /** Look up and cross-link all field types, etc. */
346
365
    private void crossLink() throws DescriptorValidationException {
347
 
      for (int i = 0; i < messageTypes.length; i++) {
348
 
        messageTypes[i].crossLink();
349
 
      }
350
 
 
351
 
      for (int i = 0; i < services.length; i++) {
352
 
        services[i].crossLink();
353
 
      }
354
 
 
355
 
      for (int i = 0; i < extensions.length; i++) {
356
 
        extensions[i].crossLink();
 
366
      for (final Descriptor messageType : messageTypes) {
 
367
        messageType.crossLink();
 
368
      }
 
369
 
 
370
      for (final ServiceDescriptor service : services) {
 
371
        service.crossLink();
 
372
      }
 
373
 
 
374
      for (final FieldDescriptor extension : extensions) {
 
375
        extension.crossLink();
357
376
      }
358
377
    }
359
378
 
367
386
     * protos.  So, we have to parse the descriptor protos a second time after
368
387
     * constructing the descriptors.
369
388
     */
370
 
    private void setProto(FileDescriptorProto proto) {
 
389
    private void setProto(final FileDescriptorProto proto) {
371
390
      this.proto = proto;
372
391
 
373
392
      for (int i = 0; i < messageTypes.length; i++) {
456
475
    }
457
476
 
458
477
    /** Determines if the given field number is an extension. */
459
 
    public boolean isExtensionNumber(int number) {
460
 
      for (DescriptorProto.ExtensionRange range : proto.getExtensionRangeList()) {
 
478
    public boolean isExtensionNumber(final int number) {
 
479
      for (final DescriptorProto.ExtensionRange range :
 
480
          proto.getExtensionRangeList()) {
461
481
        if (range.getStart() <= number && number < range.getEnd()) {
462
482
          return true;
463
483
        }
470
490
     * @param name The unqualified name of the field (e.g. "foo").
471
491
     * @return The field's descriptor, or {@code null} if not found.
472
492
     */
473
 
    public FieldDescriptor findFieldByName(String name) {
474
 
      GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
 
493
    public FieldDescriptor findFieldByName(final String name) {
 
494
      final GenericDescriptor result =
 
495
          file.pool.findSymbol(fullName + '.' + name);
475
496
      if (result != null && result instanceof FieldDescriptor) {
476
497
        return (FieldDescriptor)result;
477
498
      } else {
484
505
     * @param number The field number within this message type.
485
506
     * @return The field's descriptor, or {@code null} if not found.
486
507
     */
487
 
    public FieldDescriptor findFieldByNumber(int number) {
 
508
    public FieldDescriptor findFieldByNumber(final int number) {
488
509
      return file.pool.fieldsByNumber.get(
489
510
        new DescriptorPool.DescriptorIntPair(this, number));
490
511
    }
494
515
     * @param name The unqualified name of the nested type (e.g. "Foo").
495
516
     * @return The types's descriptor, or {@code null} if not found.
496
517
     */
497
 
    public Descriptor findNestedTypeByName(String name) {
498
 
      GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
 
518
    public Descriptor findNestedTypeByName(final String name) {
 
519
      final GenericDescriptor result =
 
520
          file.pool.findSymbol(fullName + '.' + name);
499
521
      if (result != null && result instanceof Descriptor) {
500
522
        return (Descriptor)result;
501
523
      } else {
508
530
     * @param name The unqualified name of the nested type (e.g. "Foo").
509
531
     * @return The types's descriptor, or {@code null} if not found.
510
532
     */
511
 
    public EnumDescriptor findEnumTypeByName(String name) {
512
 
      GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
 
533
    public EnumDescriptor findEnumTypeByName(final String name) {
 
534
      final GenericDescriptor result =
 
535
          file.pool.findSymbol(fullName + '.' + name);
513
536
      if (result != null && result instanceof EnumDescriptor) {
514
537
        return (EnumDescriptor)result;
515
538
      } else {
527
550
    private final FieldDescriptor[] fields;
528
551
    private final FieldDescriptor[] extensions;
529
552
 
530
 
    private Descriptor(DescriptorProto proto,
531
 
                       FileDescriptor file,
532
 
                       Descriptor parent,
533
 
                       int index)
 
553
    private Descriptor(final DescriptorProto proto,
 
554
                       final FileDescriptor file,
 
555
                       final Descriptor parent,
 
556
                       final int index)
534
557
                throws DescriptorValidationException {
535
558
      this.index = index;
536
559
      this.proto = proto;
537
 
      this.fullName = computeFullName(file, parent, proto.getName());
 
560
      fullName = computeFullName(file, parent, proto.getName());
538
561
      this.file = file;
539
 
      this.containingType = parent;
 
562
      containingType = parent;
540
563
 
541
 
      this.nestedTypes = new Descriptor[proto.getNestedTypeCount()];
 
564
      nestedTypes = new Descriptor[proto.getNestedTypeCount()];
542
565
      for (int i = 0; i < proto.getNestedTypeCount(); i++) {
543
 
        this.nestedTypes[i] = new Descriptor(
 
566
        nestedTypes[i] = new Descriptor(
544
567
          proto.getNestedType(i), file, this, i);
545
568
      }
546
569
 
547
 
      this.enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
 
570
      enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
548
571
      for (int i = 0; i < proto.getEnumTypeCount(); i++) {
549
 
        this.enumTypes[i] = new EnumDescriptor(
 
572
        enumTypes[i] = new EnumDescriptor(
550
573
          proto.getEnumType(i), file, this, i);
551
574
      }
552
575
 
553
 
      this.fields = new FieldDescriptor[proto.getFieldCount()];
 
576
      fields = new FieldDescriptor[proto.getFieldCount()];
554
577
      for (int i = 0; i < proto.getFieldCount(); i++) {
555
 
        this.fields[i] = new FieldDescriptor(
 
578
        fields[i] = new FieldDescriptor(
556
579
          proto.getField(i), file, this, i, false);
557
580
      }
558
581
 
559
 
      this.extensions = new FieldDescriptor[proto.getExtensionCount()];
 
582
      extensions = new FieldDescriptor[proto.getExtensionCount()];
560
583
      for (int i = 0; i < proto.getExtensionCount(); i++) {
561
 
        this.extensions[i] = new FieldDescriptor(
 
584
        extensions[i] = new FieldDescriptor(
562
585
          proto.getExtension(i), file, this, i, true);
563
586
      }
564
587
 
567
590
 
568
591
    /** Look up and cross-link all field types, etc. */
569
592
    private void crossLink() throws DescriptorValidationException {
570
 
      for (int i = 0; i < nestedTypes.length; i++) {
571
 
        nestedTypes[i].crossLink();
572
 
      }
573
 
 
574
 
      for (int i = 0; i < fields.length; i++) {
575
 
        fields[i].crossLink();
576
 
      }
577
 
 
578
 
      for (int i = 0; i < extensions.length; i++) {
579
 
        extensions[i].crossLink();
 
593
      for (final Descriptor nestedType : nestedTypes) {
 
594
        nestedType.crossLink();
 
595
      }
 
596
 
 
597
      for (final FieldDescriptor field : fields) {
 
598
        field.crossLink();
 
599
      }
 
600
 
 
601
      for (final FieldDescriptor extension : extensions) {
 
602
        extension.crossLink();
580
603
      }
581
604
    }
582
605
 
583
 
    /** See {@link FileDescriptor.setProto}. */
584
 
    private void setProto(DescriptorProto proto) {
 
606
    /** See {@link FileDescriptor#setProto}. */
 
607
    private void setProto(final DescriptorProto proto) {
585
608
      this.proto = proto;
586
609
 
587
610
      for (int i = 0; i < nestedTypes.length; i++) {
606
629
 
607
630
  /** Describes a field of a message type. */
608
631
  public static final class FieldDescriptor
609
 
      implements GenericDescriptor, Comparable<FieldDescriptor> {
 
632
      implements GenericDescriptor, Comparable<FieldDescriptor>,
 
633
                 FieldSet.FieldDescriptorLite<FieldDescriptor> {
610
634
    /**
611
635
     * Get the index of this descriptor within its parent.
612
 
     * @see Descriptors.Descriptor#getIndex()
 
636
     * @see Descriptor#getIndex()
613
637
     */
614
638
    public int getIndex() { return index; }
615
639
 
624
648
 
625
649
    /**
626
650
     * Get the field's fully-qualified name.
627
 
     * @see Descriptors.Descriptor#getFullName()
 
651
     * @see Descriptor#getFullName()
628
652
     */
629
653
    public String getFullName() { return fullName; }
630
654
 
634
658
     */
635
659
    public JavaType getJavaType() { return type.getJavaType(); }
636
660
 
 
661
    /** For internal use only. */
 
662
    public WireFormat.JavaType getLiteJavaType() {
 
663
      return getLiteType().getJavaType();
 
664
    }
 
665
 
637
666
    /** Get the {@code FileDescriptor} containing this descriptor. */
638
667
    public FileDescriptor getFile() { return file; }
639
668
 
640
669
    /** Get the field's declared type. */
641
670
    public Type getType() { return type; }
642
671
 
 
672
    /** For internal use only. */
 
673
    public WireFormat.FieldType getLiteType() {
 
674
      return table[type.ordinal()];
 
675
    }
 
676
    // I'm pretty sure values() constructs a new array every time, since there
 
677
    // is nothing stopping the caller from mutating the array.  Therefore we
 
678
    // make a static copy here.
 
679
    private static final WireFormat.FieldType[] table =
 
680
        WireFormat.FieldType.values();
 
681
 
643
682
    /** Is this field declared required? */
644
683
    public boolean isRequired() {
645
684
      return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REQUIRED;
655
694
      return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED;
656
695
    }
657
696
 
 
697
    /** Does this field have the {@code [packed = true]} option? */
 
698
    public boolean isPacked() {
 
699
      return getOptions().getPacked();
 
700
    }
 
701
 
658
702
    /** Returns true if the field had an explicitly-defined default value. */
659
703
    public boolean hasDefaultValue() { return proto.hasDefaultValue(); }
660
704
 
742
786
     * @return negative, zero, or positive if {@code this} is less than,
743
787
     *         equal to, or greater than {@code other}, respectively.
744
788
     */
745
 
    public int compareTo(FieldDescriptor other) {
 
789
    public int compareTo(final FieldDescriptor other) {
746
790
      if (other.containingType != containingType) {
747
791
        throw new IllegalArgumentException(
748
792
          "FieldDescriptors can only be compared to other FieldDescriptors " +
765
809
    private EnumDescriptor enumType;
766
810
    private Object defaultValue;
767
811
 
768
 
    public static enum Type {
 
812
    public enum Type {
769
813
      DOUBLE  (FieldDescriptorProto.Type.TYPE_DOUBLE  , JavaType.DOUBLE     ),
770
814
      FLOAT   (FieldDescriptorProto.Type.TYPE_FLOAT   , JavaType.FLOAT      ),
771
815
      INT64   (FieldDescriptorProto.Type.TYPE_INT64   , JavaType.LONG       ),
785
829
      SINT32  (FieldDescriptorProto.Type.TYPE_SINT32  , JavaType.INT        ),
786
830
      SINT64  (FieldDescriptorProto.Type.TYPE_SINT64  , JavaType.LONG       );
787
831
 
788
 
      private Type(FieldDescriptorProto.Type proto, JavaType javaType) {
 
832
      Type(final FieldDescriptorProto.Type proto, final JavaType javaType) {
789
833
        this.proto = proto;
790
834
        this.javaType = javaType;
791
835
 
792
 
        if (this.ordinal() != proto.getNumber() - 1) {
 
836
        if (ordinal() != proto.getNumber() - 1) {
793
837
          throw new RuntimeException(
794
838
            "descriptor.proto changed but Desrciptors.java wasn't updated.");
795
839
        }
801
845
      public FieldDescriptorProto.Type toProto() { return proto; }
802
846
      public JavaType getJavaType() { return javaType; }
803
847
 
804
 
      public static Type valueOf(FieldDescriptorProto.Type type) {
 
848
      public static Type valueOf(final FieldDescriptorProto.Type type) {
805
849
        return values()[type.getNumber() - 1];
806
850
      }
807
851
    }
815
859
      }
816
860
    }
817
861
 
818
 
    public static enum JavaType {
 
862
    public enum JavaType {
819
863
      INT(0),
820
864
      LONG(0L),
821
865
      FLOAT(0F),
826
870
      ENUM(null),
827
871
      MESSAGE(null);
828
872
 
829
 
      private JavaType(Object defaultDefault) {
 
873
      JavaType(final Object defaultDefault) {
830
874
        this.defaultDefault = defaultDefault;
831
875
      }
832
876
 
834
878
       * The default default value for fields of this type, if it's a primitive
835
879
       * type.  This is meant for use inside this file only, hence is private.
836
880
       */
837
 
      private Object defaultDefault;
 
881
      private final Object defaultDefault;
838
882
    }
839
883
 
840
 
    private FieldDescriptor(FieldDescriptorProto proto,
841
 
                            FileDescriptor file,
842
 
                            Descriptor parent,
843
 
                            int index,
844
 
                            boolean isExtension)
 
884
    private FieldDescriptor(final FieldDescriptorProto proto,
 
885
                            final FileDescriptor file,
 
886
                            final Descriptor parent,
 
887
                            final int index,
 
888
                            final boolean isExtension)
845
889
                     throws DescriptorValidationException {
846
890
      this.index = index;
847
891
      this.proto = proto;
848
 
      this.fullName = computeFullName(file, parent, proto.getName());
 
892
      fullName = computeFullName(file, parent, proto.getName());
849
893
      this.file = file;
850
894
 
851
895
      if (proto.hasType()) {
852
 
        this.type = Type.valueOf(proto.getType());
 
896
        type = Type.valueOf(proto.getType());
853
897
      }
854
898
 
855
899
      if (getNumber() <= 0) {
875
919
          throw new DescriptorValidationException(this,
876
920
            "FieldDescriptorProto.extendee not set for extension field.");
877
921
        }
878
 
        this.containingType = null;  // Will be filled in when cross-linking
 
922
        containingType = null;  // Will be filled in when cross-linking
879
923
        if (parent != null) {
880
 
          this.extensionScope = parent;
 
924
          extensionScope = parent;
881
925
        } else {
882
 
          this.extensionScope = null;
 
926
          extensionScope = null;
883
927
        }
884
928
      } else {
885
929
        if (proto.hasExtendee()) {
886
930
          throw new DescriptorValidationException(this,
887
931
            "FieldDescriptorProto.extendee set for non-extension field.");
888
932
        }
889
 
        this.containingType = parent;
890
 
        this.extensionScope = null;
 
933
        containingType = parent;
 
934
        extensionScope = null;
891
935
      }
892
936
 
893
937
      file.pool.addSymbol(this);
896
940
    /** Look up and cross-link all field types, etc. */
897
941
    private void crossLink() throws DescriptorValidationException {
898
942
      if (proto.hasExtendee()) {
899
 
        GenericDescriptor extendee =
 
943
        final GenericDescriptor extendee =
900
944
          file.pool.lookupSymbol(proto.getExtendee(), this);
901
945
        if (!(extendee instanceof Descriptor)) {
902
946
          throw new DescriptorValidationException(this,
903
 
            "\"" + proto.getExtendee() + "\" is not a message type.");
 
947
              '\"' + proto.getExtendee() + "\" is not a message type.");
904
948
        }
905
 
        this.containingType = (Descriptor)extendee;
 
949
        containingType = (Descriptor)extendee;
906
950
 
907
951
        if (!getContainingType().isExtensionNumber(getNumber())) {
908
952
          throw new DescriptorValidationException(this,
909
 
            "\"" + getContainingType().getFullName() + "\" does not declare " +
910
 
            getNumber() + " as an extension number.");
 
953
              '\"' + getContainingType().getFullName() +
 
954
              "\" does not declare " + getNumber() +
 
955
              " as an extension number.");
911
956
        }
912
957
      }
913
958
 
914
959
      if (proto.hasTypeName()) {
915
 
        GenericDescriptor typeDescriptor =
 
960
        final GenericDescriptor typeDescriptor =
916
961
          file.pool.lookupSymbol(proto.getTypeName(), this);
917
962
 
918
963
        if (!proto.hasType()) {
919
964
          // Choose field type based on symbol.
920
965
          if (typeDescriptor instanceof Descriptor) {
921
 
            this.type = Type.MESSAGE;
 
966
            type = Type.MESSAGE;
922
967
          } else if (typeDescriptor instanceof EnumDescriptor) {
923
 
            this.type = Type.ENUM;
 
968
            type = Type.ENUM;
924
969
          } else {
925
970
            throw new DescriptorValidationException(this,
926
 
              "\"" + proto.getTypeName() + "\" is not a type.");
 
971
                '\"' + proto.getTypeName() + "\" is not a type.");
927
972
          }
928
973
        }
929
974
 
930
975
        if (getJavaType() == JavaType.MESSAGE) {
931
976
          if (!(typeDescriptor instanceof Descriptor)) {
932
977
            throw new DescriptorValidationException(this,
933
 
              "\"" + proto.getTypeName() + "\" is not a message type.");
 
978
                '\"' + proto.getTypeName() + "\" is not a message type.");
934
979
          }
935
 
          this.messageType = (Descriptor)typeDescriptor;
 
980
          messageType = (Descriptor)typeDescriptor;
936
981
 
937
982
          if (proto.hasDefaultValue()) {
938
983
            throw new DescriptorValidationException(this,
941
986
        } else if (getJavaType() == JavaType.ENUM) {
942
987
          if (!(typeDescriptor instanceof EnumDescriptor)) {
943
988
            throw new DescriptorValidationException(this,
944
 
              "\"" + proto.getTypeName() + "\" is not an enum type.");
 
989
                '\"' + proto.getTypeName() + "\" is not an enum type.");
945
990
          }
946
 
          this.enumType = (EnumDescriptor)typeDescriptor;
 
991
          enumType = (EnumDescriptor)typeDescriptor;
947
992
        } else {
948
993
          throw new DescriptorValidationException(this,
949
994
            "Field with primitive type has type_name.");
972
1017
              defaultValue = TextFormat.parseInt32(proto.getDefaultValue());
973
1018
              break;
974
1019
            case UINT32:
975
 
            case FIXED32: {
 
1020
            case FIXED32:
976
1021
              defaultValue = TextFormat.parseUInt32(proto.getDefaultValue());
977
1022
              break;
978
 
            }
979
1023
            case INT64:
980
1024
            case SINT64:
981
1025
            case SFIXED64:
982
1026
              defaultValue = TextFormat.parseInt64(proto.getDefaultValue());
983
1027
              break;
984
1028
            case UINT64:
985
 
            case FIXED64: {
 
1029
            case FIXED64:
986
1030
              defaultValue = TextFormat.parseUInt64(proto.getDefaultValue());
987
1031
              break;
988
 
            }
989
1032
            case FLOAT:
990
1033
              defaultValue = Float.valueOf(proto.getDefaultValue());
991
1034
              break;
1002
1045
              try {
1003
1046
                defaultValue =
1004
1047
                  TextFormat.unescapeBytes(proto.getDefaultValue());
1005
 
              } catch (TextFormat.InvalidEscapeSequence e) {
 
1048
              } catch (TextFormat.InvalidEscapeSequenceException e) {
1006
1049
                throw new DescriptorValidationException(this,
1007
 
                  "Couldn't parse default value: " + e.getMessage());
 
1050
                  "Couldn't parse default value: " + e.getMessage(), e);
1008
1051
              }
1009
1052
              break;
1010
1053
            case ENUM:
1012
1055
              if (defaultValue == null) {
1013
1056
                throw new DescriptorValidationException(this,
1014
1057
                  "Unknown enum default value: \"" +
1015
 
                  proto.getDefaultValue() + "\"");
 
1058
                  proto.getDefaultValue() + '\"');
1016
1059
              }
1017
1060
              break;
1018
1061
            case MESSAGE:
1021
1064
                "Message type had default value.");
1022
1065
          }
1023
1066
        } catch (NumberFormatException e) {
1024
 
          DescriptorValidationException validationException =
 
1067
          final DescriptorValidationException validationException =
1025
1068
            new DescriptorValidationException(this,
1026
1069
              "Could not parse default value: \"" +
1027
 
              proto.getDefaultValue() + "\"");
 
1070
              proto.getDefaultValue() + '\"');
1028
1071
          validationException.initCause(e);
1029
1072
          throw validationException;
1030
1073
        }
1031
1074
      } else {
1032
1075
        // Determine the default default for this field.
1033
1076
        if (isRepeated()) {
1034
 
          defaultValue = Collections.EMPTY_LIST;
 
1077
          defaultValue = Collections.emptyList();
1035
1078
        } else {
1036
1079
          switch (getJavaType()) {
1037
1080
            case ENUM:
1067
1110
      }
1068
1111
    }
1069
1112
 
1070
 
    /** See {@link FileDescriptor.setProto}. */
1071
 
    private void setProto(FieldDescriptorProto proto) {
 
1113
    /** See {@link FileDescriptor#setProto}. */
 
1114
    private void setProto(final FieldDescriptorProto proto) {
1072
1115
      this.proto = proto;
1073
1116
    }
 
1117
 
 
1118
    /**
 
1119
     * For internal use only.  This is to satisfy the FieldDescriptorLite
 
1120
     * interface.
 
1121
     */
 
1122
    public MessageLite.Builder internalMergeFrom(
 
1123
        MessageLite.Builder to, MessageLite from) {
 
1124
      // FieldDescriptors are only used with non-lite messages so we can just
 
1125
      // down-cast and call mergeFrom directly.
 
1126
      return ((Message.Builder) to).mergeFrom((Message) from);
 
1127
    }
1074
1128
  }
1075
1129
 
1076
1130
  // =================================================================
1077
1131
 
1078
1132
  /** Describes an enum type. */
1079
 
  public static final class EnumDescriptor implements GenericDescriptor {
 
1133
  public static final class EnumDescriptor
 
1134
      implements GenericDescriptor, Internal.EnumLiteMap<EnumValueDescriptor> {
1080
1135
    /**
1081
1136
     * Get the index of this descriptor within its parent.
1082
 
     * @see Descriptors.Descriptor#getIndex()
 
1137
     * @see Descriptor#getIndex()
1083
1138
     */
1084
1139
    public int getIndex() { return index; }
1085
1140
 
1091
1146
 
1092
1147
    /**
1093
1148
     * Get the type's fully-qualified name.
1094
 
     * @see Descriptors.Descriptor#getFullName()
 
1149
     * @see Descriptor#getFullName()
1095
1150
     */
1096
1151
    public String getFullName() { return fullName; }
1097
1152
 
1114
1169
     * @param name The unqualified name of the value (e.g. "FOO").
1115
1170
     * @return the value's decsriptor, or {@code null} if not found.
1116
1171
     */
1117
 
    public EnumValueDescriptor findValueByName(String name) {
1118
 
      GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
 
1172
    public EnumValueDescriptor findValueByName(final String name) {
 
1173
      final GenericDescriptor result =
 
1174
          file.pool.findSymbol(fullName + '.' + name);
1119
1175
      if (result != null && result instanceof EnumValueDescriptor) {
1120
1176
        return (EnumValueDescriptor)result;
1121
1177
      } else {
1129
1185
     * @param number The value's number.
1130
1186
     * @return the value's decsriptor, or {@code null} if not found.
1131
1187
     */
1132
 
    public EnumValueDescriptor findValueByNumber(int number) {
 
1188
    public EnumValueDescriptor findValueByNumber(final int number) {
1133
1189
      return file.pool.enumValuesByNumber.get(
1134
1190
        new DescriptorPool.DescriptorIntPair(this, number));
1135
1191
    }
1141
1197
    private final Descriptor containingType;
1142
1198
    private EnumValueDescriptor[] values;
1143
1199
 
1144
 
    private EnumDescriptor(EnumDescriptorProto proto,
1145
 
                           FileDescriptor file,
1146
 
                           Descriptor parent,
1147
 
                           int index)
 
1200
    private EnumDescriptor(final EnumDescriptorProto proto,
 
1201
                           final FileDescriptor file,
 
1202
                           final Descriptor parent,
 
1203
                           final int index)
1148
1204
                    throws DescriptorValidationException {
1149
1205
      this.index = index;
1150
1206
      this.proto = proto;
1151
 
      this.fullName = computeFullName(file, parent, proto.getName());
 
1207
      fullName = computeFullName(file, parent, proto.getName());
1152
1208
      this.file = file;
1153
 
      this.containingType = parent;
 
1209
      containingType = parent;
1154
1210
 
1155
1211
      if (proto.getValueCount() == 0) {
1156
1212
        // We cannot allow enums with no values because this would mean there
1161
1217
 
1162
1218
      values = new EnumValueDescriptor[proto.getValueCount()];
1163
1219
      for (int i = 0; i < proto.getValueCount(); i++) {
1164
 
        this.values[i] = new EnumValueDescriptor(
 
1220
        values[i] = new EnumValueDescriptor(
1165
1221
          proto.getValue(i), file, this, i);
1166
1222
      }
1167
1223
 
1168
1224
      file.pool.addSymbol(this);
1169
1225
    }
1170
1226
 
1171
 
    /** See {@link FileDescriptor.setProto}. */
1172
 
    private void setProto(EnumDescriptorProto proto) {
 
1227
    /** See {@link FileDescriptor#setProto}. */
 
1228
    private void setProto(final EnumDescriptorProto proto) {
1173
1229
      this.proto = proto;
1174
1230
 
1175
1231
      for (int i = 0; i < values.length; i++) {
1186
1242
   * with the same number after the first become aliases of the first.
1187
1243
   * However, they still have independent EnumValueDescriptors.
1188
1244
   */
1189
 
  public static final class EnumValueDescriptor implements GenericDescriptor {
 
1245
  public static final class EnumValueDescriptor
 
1246
      implements GenericDescriptor, Internal.EnumLite {
1190
1247
    /**
1191
1248
     * Get the index of this descriptor within its parent.
1192
 
     * @see Descriptors.Descriptor#getIndex()
 
1249
     * @see Descriptor#getIndex()
1193
1250
     */
1194
1251
    public int getIndex() { return index; }
1195
1252
 
1204
1261
 
1205
1262
    /**
1206
1263
     * Get the value's fully-qualified name.
1207
 
     * @see Descriptors.Descriptor#getFullName()
 
1264
     * @see Descriptor#getFullName()
1208
1265
     */
1209
1266
    public String getFullName() { return fullName; }
1210
1267
 
1225
1282
    private final FileDescriptor file;
1226
1283
    private final EnumDescriptor type;
1227
1284
 
1228
 
    private EnumValueDescriptor(EnumValueDescriptorProto proto,
1229
 
                                FileDescriptor file,
1230
 
                                EnumDescriptor parent,
1231
 
                                int index)
 
1285
    private EnumValueDescriptor(final EnumValueDescriptorProto proto,
 
1286
                                final FileDescriptor file,
 
1287
                                final EnumDescriptor parent,
 
1288
                                final int index)
1232
1289
                         throws DescriptorValidationException {
1233
1290
      this.index = index;
1234
1291
      this.proto = proto;
1235
1292
      this.file = file;
1236
 
      this.type = parent;
 
1293
      type = parent;
1237
1294
 
1238
 
      this.fullName = parent.getFullName() + "." + proto.getName();
 
1295
      fullName = parent.getFullName() + '.' + proto.getName();
1239
1296
 
1240
1297
      file.pool.addSymbol(this);
1241
1298
      file.pool.addEnumValueByNumber(this);
1242
1299
    }
1243
1300
 
1244
 
    /** See {@link FileDescriptor.setProto}. */
1245
 
    private void setProto(EnumValueDescriptorProto proto) {
 
1301
    /** See {@link FileDescriptor#setProto}. */
 
1302
    private void setProto(final EnumValueDescriptorProto proto) {
1246
1303
      this.proto = proto;
1247
1304
    }
1248
1305
  }
1265
1322
 
1266
1323
    /**
1267
1324
     * Get the type's fully-qualified name.
1268
 
     * @see Descriptors.Descriptor#getFullName()
 
1325
     * @see Descriptor#getFullName()
1269
1326
     */
1270
1327
    public String getFullName() { return fullName; }
1271
1328
 
1285
1342
     * @param name The unqualified name of the method (e.g. "Foo").
1286
1343
     * @return the method's decsriptor, or {@code null} if not found.
1287
1344
     */
1288
 
    public MethodDescriptor findMethodByName(String name) {
1289
 
      GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
 
1345
    public MethodDescriptor findMethodByName(final String name) {
 
1346
      final GenericDescriptor result =
 
1347
          file.pool.findSymbol(fullName + '.' + name);
1290
1348
      if (result != null && result instanceof MethodDescriptor) {
1291
1349
        return (MethodDescriptor)result;
1292
1350
      } else {
1300
1358
    private final FileDescriptor file;
1301
1359
    private MethodDescriptor[] methods;
1302
1360
 
1303
 
    private ServiceDescriptor(ServiceDescriptorProto proto,
1304
 
                              FileDescriptor file,
1305
 
                              int index)
 
1361
    private ServiceDescriptor(final ServiceDescriptorProto proto,
 
1362
                              final FileDescriptor file,
 
1363
                              final int index)
1306
1364
                       throws DescriptorValidationException {
1307
1365
      this.index = index;
1308
1366
      this.proto = proto;
1309
 
      this.fullName = computeFullName(file, null, proto.getName());
 
1367
      fullName = computeFullName(file, null, proto.getName());
1310
1368
      this.file = file;
1311
1369
 
1312
 
      this.methods = new MethodDescriptor[proto.getMethodCount()];
 
1370
      methods = new MethodDescriptor[proto.getMethodCount()];
1313
1371
      for (int i = 0; i < proto.getMethodCount(); i++) {
1314
 
        this.methods[i] = new MethodDescriptor(
 
1372
        methods[i] = new MethodDescriptor(
1315
1373
          proto.getMethod(i), file, this, i);
1316
1374
      }
1317
1375
 
1319
1377
    }
1320
1378
 
1321
1379
    private void crossLink() throws DescriptorValidationException {
1322
 
      for (int i = 0; i < methods.length; i++) {
1323
 
        methods[i].crossLink();
 
1380
      for (final MethodDescriptor method : methods) {
 
1381
        method.crossLink();
1324
1382
      }
1325
1383
    }
1326
1384
 
1327
 
    /** See {@link FileDescriptor.setProto}. */
1328
 
    private void setProto(ServiceDescriptorProto proto) {
 
1385
    /** See {@link FileDescriptor#setProto}. */
 
1386
    private void setProto(final ServiceDescriptorProto proto) {
1329
1387
      this.proto = proto;
1330
1388
 
1331
1389
      for (int i = 0; i < methods.length; i++) {
1354
1412
 
1355
1413
    /**
1356
1414
     * Get the method's fully-qualified name.
1357
 
     * @see Descriptors.Descriptor#getFullName()
 
1415
     * @see Descriptor#getFullName()
1358
1416
     */
1359
1417
    public String getFullName() { return fullName; }
1360
1418
 
1385
1443
    private Descriptor inputType;
1386
1444
    private Descriptor outputType;
1387
1445
 
1388
 
    private MethodDescriptor(MethodDescriptorProto proto,
1389
 
                             FileDescriptor file,
1390
 
                             ServiceDescriptor parent,
1391
 
                             int index)
 
1446
    private MethodDescriptor(final MethodDescriptorProto proto,
 
1447
                             final FileDescriptor file,
 
1448
                             final ServiceDescriptor parent,
 
1449
                             final int index)
1392
1450
                      throws DescriptorValidationException {
1393
1451
      this.index = index;
1394
1452
      this.proto = proto;
1395
1453
      this.file = file;
1396
 
      this.service = parent;
 
1454
      service = parent;
1397
1455
 
1398
 
      this.fullName = parent.getFullName() + "." + proto.getName();
 
1456
      fullName = parent.getFullName() + '.' + proto.getName();
1399
1457
 
1400
1458
      file.pool.addSymbol(this);
1401
1459
    }
1402
1460
 
1403
1461
    private void crossLink() throws DescriptorValidationException {
1404
 
      GenericDescriptor inputType =
 
1462
      final GenericDescriptor input =
1405
1463
        file.pool.lookupSymbol(proto.getInputType(), this);
1406
 
      if (!(inputType instanceof Descriptor)) {
 
1464
      if (!(input instanceof Descriptor)) {
1407
1465
        throw new DescriptorValidationException(this,
1408
 
          "\"" + proto.getInputType() + "\" is not a message type.");
 
1466
            '\"' + proto.getInputType() + "\" is not a message type.");
1409
1467
      }
1410
 
      this.inputType = (Descriptor)inputType;
 
1468
      inputType = (Descriptor)input;
1411
1469
 
1412
 
      GenericDescriptor outputType =
 
1470
      final GenericDescriptor output =
1413
1471
        file.pool.lookupSymbol(proto.getOutputType(), this);
1414
 
      if (!(outputType instanceof Descriptor)) {
 
1472
      if (!(output instanceof Descriptor)) {
1415
1473
        throw new DescriptorValidationException(this,
1416
 
          "\"" + proto.getOutputType() + "\" is not a message type.");
 
1474
            '\"' + proto.getOutputType() + "\" is not a message type.");
1417
1475
      }
1418
 
      this.outputType = (Descriptor)outputType;
 
1476
      outputType = (Descriptor)output;
1419
1477
    }
1420
1478
 
1421
 
    /** See {@link FileDescriptor.setProto}. */
1422
 
    private void setProto(MethodDescriptorProto proto) {
 
1479
    /** See {@link FileDescriptor#setProto}. */
 
1480
    private void setProto(final MethodDescriptorProto proto) {
1423
1481
      this.proto = proto;
1424
1482
    }
1425
1483
  }
1426
1484
 
1427
1485
  // =================================================================
1428
1486
 
1429
 
  private static String computeFullName(FileDescriptor file,
1430
 
                                        Descriptor parent,
1431
 
                                        String name) {
 
1487
  private static String computeFullName(final FileDescriptor file,
 
1488
                                        final Descriptor parent,
 
1489
                                        final String name) {
1432
1490
    if (parent != null) {
1433
 
      return parent.getFullName() + "." + name;
 
1491
      return parent.getFullName() + '.' + name;
1434
1492
    } else if (file.getPackage().length() > 0) {
1435
 
      return file.getPackage() + "." + name;
 
1493
      return file.getPackage() + '.' + name;
1436
1494
    } else {
1437
1495
      return name;
1438
1496
    }
1444
1502
   * All descriptors except {@code FileDescriptor} implement this to make
1445
1503
   * {@code DescriptorPool}'s life easier.
1446
1504
   */
1447
 
  private static interface GenericDescriptor {
 
1505
  private interface GenericDescriptor {
1448
1506
    Message toProto();
1449
1507
    String getName();
1450
1508
    String getFullName();
1456
1514
   * are not valid.
1457
1515
   */
1458
1516
  public static class DescriptorValidationException extends Exception {
 
1517
    private static final long serialVersionUID = 5750205775490483148L;
 
1518
 
1459
1519
    /** Gets the full name of the descriptor where the error occurred. */
1460
1520
    public String getProblemSymbolName() { return name; }
1461
1521
 
1473
1533
    private final Message proto;
1474
1534
    private final String description;
1475
1535
 
1476
 
    private DescriptorValidationException(GenericDescriptor problemDescriptor,
1477
 
                                          String description) {
1478
 
      super(problemDescriptor.getFullName() + ": " + description);
 
1536
    private DescriptorValidationException(
 
1537
        final GenericDescriptor problemDescriptor,
 
1538
        final String description) {
 
1539
      this(problemDescriptor, description, null);
 
1540
    }
 
1541
 
 
1542
    private DescriptorValidationException(
 
1543
        final GenericDescriptor problemDescriptor,
 
1544
        final String description,
 
1545
        final Throwable cause) {
 
1546
      super(problemDescriptor.getFullName() + ": " + description, cause);
1479
1547
 
1480
1548
      // Note that problemDescriptor may be partially uninitialized, so we
1481
1549
      // don't want to expose it directly to the user.  So, we only provide
1482
1550
      // the name and the original proto.
1483
 
      this.name = problemDescriptor.getFullName();
1484
 
      this.proto = problemDescriptor.toProto();
 
1551
      name = problemDescriptor.getFullName();
 
1552
      proto = problemDescriptor.toProto();
1485
1553
      this.description = description;
1486
1554
    }
1487
1555
 
1488
 
    private DescriptorValidationException(FileDescriptor problemDescriptor,
1489
 
                                          String description) {
 
1556
    private DescriptorValidationException(
 
1557
        final FileDescriptor problemDescriptor,
 
1558
        final String description) {
1490
1559
      super(problemDescriptor.getName() + ": " + description);
1491
1560
 
1492
1561
      // Note that problemDescriptor may be partially uninitialized, so we
1493
1562
      // don't want to expose it directly to the user.  So, we only provide
1494
1563
      // the name and the original proto.
1495
 
      this.name = problemDescriptor.getName();
1496
 
      this.proto = problemDescriptor.toProto();
 
1564
      name = problemDescriptor.getName();
 
1565
      proto = problemDescriptor.toProto();
1497
1566
      this.description = description;
1498
1567
    }
1499
1568
  }
1505
1574
   * descriptors defined in a particular file.
1506
1575
   */
1507
1576
  private static final class DescriptorPool {
1508
 
    DescriptorPool(FileDescriptor[] dependencies) {
 
1577
    DescriptorPool(final FileDescriptor[] dependencies) {
1509
1578
      this.dependencies = new DescriptorPool[dependencies.length];
1510
1579
 
1511
1580
      for (int i = 0; i < dependencies.length; i++)  {
1512
1581
        this.dependencies[i] = dependencies[i].pool;
1513
1582
      }
1514
1583
 
1515
 
      for (int i = 0; i < dependencies.length; i++)  {
 
1584
      for (final FileDescriptor dependency : dependencies) {
1516
1585
        try {
1517
 
          addPackage(dependencies[i].getPackage(), dependencies[i]);
 
1586
          addPackage(dependency.getPackage(), dependency);
1518
1587
        } catch (DescriptorValidationException e) {
1519
1588
          // Can't happen, because addPackage() only fails when the name
1520
1589
          // conflicts with a non-package, but we have not yet added any
1524
1593
      }
1525
1594
    }
1526
1595
 
1527
 
    final DescriptorPool[] dependencies;
 
1596
    private final DescriptorPool[] dependencies;
1528
1597
 
1529
 
    final Map<String, GenericDescriptor> descriptorsByName =
 
1598
    private final Map<String, GenericDescriptor> descriptorsByName =
1530
1599
      new HashMap<String, GenericDescriptor>();
1531
 
    final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
 
1600
    private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
1532
1601
      new HashMap<DescriptorIntPair, FieldDescriptor>();
1533
 
    final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber =
1534
 
      new HashMap<DescriptorIntPair, EnumValueDescriptor>();
 
1602
    private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber
 
1603
        = new HashMap<DescriptorIntPair, EnumValueDescriptor>();
1535
1604
 
1536
1605
    /** Find a generic descriptor by fully-qualified name. */
1537
 
    GenericDescriptor findSymbol(String fullName) {
 
1606
    GenericDescriptor findSymbol(final String fullName) {
1538
1607
      GenericDescriptor result = descriptorsByName.get(fullName);
1539
 
      if (result != null) return result;
 
1608
      if (result != null) {
 
1609
        return result;
 
1610
      }
1540
1611
 
1541
 
      for (int i = 0; i < dependencies.length; i++) {
1542
 
        result = dependencies[i].descriptorsByName.get(fullName);
1543
 
        if (result != null) return result;
 
1612
      for (final DescriptorPool dependency : dependencies) {
 
1613
        result = dependency.descriptorsByName.get(fullName);
 
1614
        if (result != null) {
 
1615
          return result;
 
1616
        }
1544
1617
      }
1545
1618
 
1546
1619
      return null;
1552
1625
     * partially-qualified, or unqualified.  C++-like name lookup semantics
1553
1626
     * are used to search for the matching descriptor.
1554
1627
     */
1555
 
    GenericDescriptor lookupSymbol(String name,
1556
 
                                   GenericDescriptor relativeTo)
 
1628
    GenericDescriptor lookupSymbol(final String name,
 
1629
                                   final GenericDescriptor relativeTo)
1557
1630
                            throws DescriptorValidationException {
1558
1631
      // TODO(kenton):  This could be optimized in a number of ways.
1559
1632
 
1564
1637
      } else {
1565
1638
        // If "name" is a compound identifier, we want to search for the
1566
1639
        // first component of it, then search within it for the rest.
1567
 
        int firstPartLength = name.indexOf('.');
1568
 
        String firstPart;
 
1640
        final int firstPartLength = name.indexOf('.');
 
1641
        final String firstPart;
1569
1642
        if (firstPartLength == -1) {
1570
1643
          firstPart = name;
1571
1644
        } else {
1574
1647
 
1575
1648
        // We will search each parent scope of "relativeTo" looking for the
1576
1649
        // symbol.
1577
 
        StringBuilder scopeToTry = new StringBuilder(relativeTo.getFullName());
 
1650
        final StringBuilder scopeToTry =
 
1651
            new StringBuilder(relativeTo.getFullName());
1578
1652
 
1579
1653
        while (true) {
1580
1654
          // Chop off the last component of the scope.
1581
 
          int dotpos = scopeToTry.lastIndexOf(".");
 
1655
          final int dotpos = scopeToTry.lastIndexOf(".");
1582
1656
          if (dotpos == -1) {
1583
1657
            result = findSymbol(name);
1584
1658
            break;
1609
1683
 
1610
1684
      if (result == null) {
1611
1685
        throw new DescriptorValidationException(relativeTo,
1612
 
          "\"" + name + "\" is not defined.");
 
1686
            '\"' + name + "\" is not defined.");
1613
1687
      } else {
1614
1688
        return result;
1615
1689
      }
1619
1693
     * Adds a symbol to the symbol table.  If a symbol with the same name
1620
1694
     * already exists, throws an error.
1621
1695
     */
1622
 
    void addSymbol(GenericDescriptor descriptor)
 
1696
    void addSymbol(final GenericDescriptor descriptor)
1623
1697
            throws DescriptorValidationException {
1624
1698
      validateSymbolName(descriptor);
1625
1699
 
1626
 
      String fullName = descriptor.getFullName();
1627
 
      int dotpos = fullName.lastIndexOf('.');
 
1700
      final String fullName = descriptor.getFullName();
 
1701
      final int dotpos = fullName.lastIndexOf('.');
1628
1702
 
1629
 
      GenericDescriptor old = descriptorsByName.put(fullName, descriptor);
 
1703
      final GenericDescriptor old = descriptorsByName.put(fullName, descriptor);
1630
1704
      if (old != null) {
1631
1705
        descriptorsByName.put(fullName, old);
1632
1706
 
1633
1707
        if (descriptor.getFile() == old.getFile()) {
1634
1708
          if (dotpos == -1) {
1635
1709
            throw new DescriptorValidationException(descriptor,
1636
 
              "\"" + fullName + "\" is already defined.");
 
1710
                '\"' + fullName + "\" is already defined.");
1637
1711
          } else {
1638
1712
            throw new DescriptorValidationException(descriptor,
1639
 
              "\"" + fullName.substring(dotpos + 1) +
 
1713
                '\"' + fullName.substring(dotpos + 1) +
1640
1714
              "\" is already defined in \"" +
1641
1715
              fullName.substring(0, dotpos) + "\".");
1642
1716
          }
1643
1717
        } else {
1644
1718
          throw new DescriptorValidationException(descriptor,
1645
 
            "\"" + fullName + "\" is already defined in file \"" +
 
1719
              '\"' + fullName + "\" is already defined in file \"" +
1646
1720
            old.getFile().getName() + "\".");
1647
1721
        }
1648
1722
      }
1653
1727
     * just as placeholders so that someone cannot define, say, a message type
1654
1728
     * that has the same name as an existing package.
1655
1729
     */
1656
 
    static final class PackageDescriptor implements GenericDescriptor {
 
1730
    private static final class PackageDescriptor implements GenericDescriptor {
1657
1731
      public Message toProto()        { return file.toProto(); }
1658
1732
      public String getName()         { return name;           }
1659
1733
      public String getFullName()     { return fullName;       }
1660
1734
      public FileDescriptor getFile() { return file;           }
1661
1735
 
1662
 
      PackageDescriptor(String name, String fullName, FileDescriptor file) {
 
1736
      PackageDescriptor(final String name, final String fullName,
 
1737
                        final FileDescriptor file) {
1663
1738
        this.file = file;
1664
1739
        this.fullName = fullName;
1665
1740
        this.name = name;
1666
1741
      }
1667
1742
 
1668
 
      String name;
1669
 
      String fullName;
1670
 
      FileDescriptor file;
 
1743
      private final String name;
 
1744
      private final String fullName;
 
1745
      private final FileDescriptor file;
1671
1746
    }
1672
1747
 
1673
1748
    /**
1676
1751
     * under the same name, an exception is thrown.  If the package has
1677
1752
     * multiple components, this also adds the parent package(s).
1678
1753
     */
1679
 
    void addPackage(String fullName, FileDescriptor file)
 
1754
    void addPackage(final String fullName, final FileDescriptor file)
1680
1755
             throws DescriptorValidationException {
1681
 
      int dotpos = fullName.lastIndexOf('.');
1682
 
      String name;
1683
 
      if (dotpos != -1) {
 
1756
      final int dotpos = fullName.lastIndexOf('.');
 
1757
      final String name;
 
1758
      if (dotpos == -1) {
 
1759
        name = fullName;
 
1760
      } else {
1684
1761
        addPackage(fullName.substring(0, dotpos), file);
1685
1762
        name = fullName.substring(dotpos + 1);
1686
 
      } else {
1687
 
        name = fullName;
1688
1763
      }
1689
1764
 
1690
 
      GenericDescriptor old =
 
1765
      final GenericDescriptor old =
1691
1766
        descriptorsByName.put(fullName,
1692
1767
          new PackageDescriptor(name, fullName, file));
1693
1768
      if (old != null) {
1694
1769
        descriptorsByName.put(fullName, old);
1695
1770
        if (!(old instanceof PackageDescriptor)) {
1696
1771
          throw new DescriptorValidationException(file,
1697
 
            "\"" + name + "\" is already defined (as something other than a " +
1698
 
            "package) in file \"" + old.getFile().getName() + "\".");
 
1772
              '\"' + name + "\" is already defined (as something other than a "
 
1773
              + "package) in file \"" + old.getFile().getName() + "\".");
1699
1774
        }
1700
1775
      }
1701
1776
    }
1702
1777
 
1703
1778
    /** A (GenericDescriptor, int) pair, used as a map key. */
1704
 
    static final class DescriptorIntPair {
1705
 
      final GenericDescriptor descriptor;
1706
 
      final int number;
 
1779
    private static final class DescriptorIntPair {
 
1780
      private final GenericDescriptor descriptor;
 
1781
      private final int number;
1707
1782
 
1708
 
      DescriptorIntPair(GenericDescriptor descriptor, int number) {
 
1783
      DescriptorIntPair(final GenericDescriptor descriptor, final int number) {
1709
1784
        this.descriptor = descriptor;
1710
1785
        this.number = number;
1711
1786
      }
1712
1787
 
 
1788
      @Override
1713
1789
      public int hashCode() {
1714
1790
        return descriptor.hashCode() * ((1 << 16) - 1) + number;
1715
1791
      }
1716
 
      public boolean equals(Object obj) {
1717
 
        if (!(obj instanceof DescriptorIntPair)) return false;
1718
 
        DescriptorIntPair other = (DescriptorIntPair)obj;
 
1792
      @Override
 
1793
      public boolean equals(final Object obj) {
 
1794
        if (!(obj instanceof DescriptorIntPair)) {
 
1795
          return false;
 
1796
        }
 
1797
        final DescriptorIntPair other = (DescriptorIntPair)obj;
1719
1798
        return descriptor == other.descriptor && number == other.number;
1720
1799
      }
1721
1800
    }
1724
1803
     * Adds a field to the fieldsByNumber table.  Throws an exception if a
1725
1804
     * field with hte same containing type and number already exists.
1726
1805
     */
1727
 
    void addFieldByNumber(FieldDescriptor field)
 
1806
    void addFieldByNumber(final FieldDescriptor field)
1728
1807
                   throws DescriptorValidationException {
1729
 
      DescriptorIntPair key =
 
1808
      final DescriptorIntPair key =
1730
1809
        new DescriptorIntPair(field.getContainingType(), field.getNumber());
1731
 
      FieldDescriptor old = fieldsByNumber.put(key, field);
 
1810
      final FieldDescriptor old = fieldsByNumber.put(key, field);
1732
1811
      if (old != null) {
1733
1812
        fieldsByNumber.put(key, old);
1734
1813
        throw new DescriptorValidationException(field,
1744
1823
     * with the same type and number already exists, does nothing.  (This is
1745
1824
     * allowed; the first value define with the number takes precedence.)
1746
1825
     */
1747
 
    void addEnumValueByNumber(EnumValueDescriptor value) {
1748
 
      DescriptorIntPair key =
 
1826
    void addEnumValueByNumber(final EnumValueDescriptor value) {
 
1827
      final DescriptorIntPair key =
1749
1828
        new DescriptorIntPair(value.getType(), value.getNumber());
1750
 
      EnumValueDescriptor old = enumValuesByNumber.put(key, value);
 
1829
      final EnumValueDescriptor old = enumValuesByNumber.put(key, value);
1751
1830
      if (old != null) {
1752
1831
        enumValuesByNumber.put(key, old);
1753
1832
        // Not an error:  Multiple enum values may have the same number, but
1759
1838
     * Verifies that the descriptor's name is valid (i.e. it contains only
1760
1839
     * letters, digits, and underscores, and does not start with a digit).
1761
1840
     */
1762
 
    void validateSymbolName(GenericDescriptor descriptor)
1763
 
                     throws DescriptorValidationException {
1764
 
      String name = descriptor.getName();
 
1841
    static void validateSymbolName(final GenericDescriptor descriptor)
 
1842
                                   throws DescriptorValidationException {
 
1843
      final String name = descriptor.getName();
1765
1844
      if (name.length() == 0) {
1766
1845
        throw new DescriptorValidationException(descriptor, "Missing name.");
1767
1846
      } else {
1768
1847
        boolean valid = true;
1769
1848
        for (int i = 0; i < name.length(); i++) {
1770
 
          char c = name.charAt(i);
 
1849
          final char c = name.charAt(i);
1771
1850
          // Non-ASCII characters are not valid in protobuf identifiers, even
1772
1851
          // if they are letters or digits.
1773
1852
          if (c >= 128) {
1784
1863
        }
1785
1864
        if (!valid) {
1786
1865
          throw new DescriptorValidationException(descriptor,
1787
 
            "\"" + name + "\" is not a valid identifier.");
 
1866
              '\"' + name + "\" is not a valid identifier.");
1788
1867
        }
1789
1868
      }
1790
1869
    }