content: /* Copyright (C) 2016-2018 Alibaba Group Holding Limited
  
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  
      http://www.apache.org/licenses/LICENSE-2.0
  
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  ==============================================================================*/
  
  // Protocol Buffers - Google's data interchange format
  // Copyright 2008 Google Inc.  All rights reserved.
  // https://developers.google.com/protocol-buffers/
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
  //
  //     * Redistributions of source code must retain the above copyright
  // notice, this list of conditions and the following disclaimer.
  //     * Redistributions in binary form must reproduce the above
  // copyright notice, this list of conditions and the following disclaimer
  // in the documentation and/or other materials provided with the
  // distribution.
  //     * Neither the name of Google Inc. nor the names of its
  // contributors may be used to endorse or promote products derived from
  // this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  package com.google.protobuf;
  
  import com.google.protobuf.Descriptors.Descriptor;
  import com.google.protobuf.Descriptors.EnumDescriptor;
  import com.google.protobuf.Descriptors.EnumValueDescriptor;
  import com.google.protobuf.Descriptors.FieldDescriptor;
  import com.google.protobuf.Descriptors.FileDescriptor;
  import com.google.protobuf.Descriptors.OneofDescriptor;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.ObjectStreamException;
  import java.io.Serializable;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.TreeMap;
  
  /**
   * All generated protocol message classes extend this class.  This class
   * implements most of the Message and Builder interfaces using Java reflection.
   * Users can ignore this class and pretend that generated messages implement
   * the Message interface directly.
   *
   * @author kenton@google.com Kenton Varda
   */
  public abstract class GeneratedMessage extends AbstractMessage
      implements Serializable {
    private static final long serialVersionUID = 1L;
  
    /**
     * For testing. Allows a test to disable the optimization that avoids using
     * field builders for nested messages until they are requested. By disabling
     * this optimization, existing tests can be reused to test the field builders.
     */
    protected static boolean alwaysUseFieldBuilders = false;
  
    /** For use by generated code only.  */
    protected UnknownFieldSet unknownFields;
  
    protected GeneratedMessage() {
      unknownFields = UnknownFieldSet.getDefaultInstance();
    }
  
    protected GeneratedMessage(Builder<?> builder) {
      unknownFields = builder.getUnknownFields();
    }
  
    @Override
    public Parser<? extends GeneratedMessage> getParserForType() {
      throw new UnsupportedOperationException(
          "This is supposed to be overridden by subclasses.");
    }
  
   /**
    * For testing. Allows a test to disable the optimization that avoids using
    * field builders for nested messages until they are requested. By disabling
    * this optimization, existing tests can be reused to test the field builders.
    * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}.
    */
    static void enableAlwaysUseFieldBuildersForTesting() {
      alwaysUseFieldBuilders = true;
    }
  
    /**
     * Get the FieldAccessorTable for this type.  We can't have the message
     * class pass this in to the constructor because of bootstrapping trouble
     * with DescriptorProtos.
     */
    protected abstract FieldAccessorTable internalGetFieldAccessorTable();
  
    @Override
    public Descriptor getDescriptorForType() {
      return internalGetFieldAccessorTable().descriptor;
    }
  
    /**
     * Internal helper to return a modifiable map containing all the fields.
     * The returned Map is modifialbe so that the caller can add additional
     * extension fields to implement {@link #getAllFields()}.
     *
     * @param getBytesForString whether to generate ByteString for string fields
     */
    private Map<FieldDescriptor, Object> getAllFieldsMutable(
        boolean getBytesForString) {
      final TreeMap<FieldDescriptor, Object> result =
        new TreeMap<FieldDescriptor, Object>();
      final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
      final List<FieldDescriptor> fields = descriptor.getFields();
  
      for (int i = 0; i < fields.size(); i++) {
        FieldDescriptor field = fields.get(i);
        final OneofDescriptor oneofDescriptor = field.getContainingOneof();
  
        /*
         * If the field is part of a Oneof, then at maximum one field in the Oneof is set
         * and it is not repeated. There is no need to iterate through the others.
         */
        if (oneofDescriptor != null) {
          // Skip other fields in the Oneof we know are not set
          i += oneofDescriptor.getFieldCount() - 1;
          if (!hasOneof(oneofDescriptor)) {
            // If no field is set in the Oneof, skip all the fields in the Oneof
            continue;
          }
          // Get the pointer to the only field which is set in the Oneof
          field = getOneofFieldDescriptor(oneofDescriptor);
        } else {
          // If we are not in a Oneof, we need to check if the field is set and if it is repeated
          if (field.isRepeated()) {
            final List<?> value = (List<?>) getField(field);
            if (!value.isEmpty()) {
              result.put(field, value);
            }
            continue;
          }
          if (!hasField(field)) {
            continue;
          }
        }
        // Add the field to the map
        if (getBytesForString && field.getJavaType() == FieldDescriptor.JavaType.STRING) {
          result.put(field, getFieldRaw(field));
        } else {
          result.put(field, getField(field));
        }
      }
      return result;
    }
  
    @Override
    public boolean isInitialized() {
      for (final FieldDescriptor field : getDescriptorForType().getFields()) {
        // Check that all required fields are present.
        if (field.isRequired()) {
          if (!hasField(field)) {
            return false;
          }
        }
        // Check that embedded messages are initialized.
        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
          if (field.isRepeated()) {
            @SuppressWarnings("unchecked") final
            List<Message> messageList = (List<Message>) getField(field);
            for (final Message element : messageList) {
              if (!element.isInitialized()) {
                return false;
              }
            }
          } else {
            if (hasField(field) && !((Message) getField(field)).isInitialized()) {
              return false;
            }
          }
        }
      }
  
      return true;
    }
  
    @Override
    public Map<FieldDescriptor, Object> getAllFields() {
      return Collections.unmodifiableMap(
          getAllFieldsMutable(/* getBytesForString = */ false));
    }
  
    /**
     * Returns a collection of all the fields in this message which are set
     * and their corresponding values.  A singular ("required" or "optional")
     * field is set iff hasField() returns true for that field.  A "repeated"
     * field is set iff getRepeatedFieldCount() is greater than zero.  The
     * values are exactly what would be returned by calling
     * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field.  The map
     * is guaranteed to be a sorted map, so iterating over it will return fields
     * in order by field number.
     */
    Map<FieldDescriptor, Object> getAllFieldsRaw() {
      return Collections.unmodifiableMap(
          getAllFieldsMutable(/* getBytesForString = */ true));
    }
  
    @Override
    public boolean hasOneof(final OneofDescriptor oneof) {
      return internalGetFieldAccessorTable().getOneof(oneof).has(this);
    }
  
    @Override
    public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
      return internalGetFieldAccessorTable().getOneof(oneof).get(this);
    }
  
    @Override
    public boolean hasField(final FieldDescriptor field) {
      return internalGetFieldAccessorTable().getField(field).has(this);
    }
  
    @Override
    public Object getField(final FieldDescriptor field) {
      return internalGetFieldAccessorTable().getField(field).get(this);
    }
  
    /**
     * Obtains the value of the given field, or the default value if it is
     * not set.  For primitive fields, the boxed primitive value is returned.
     * For enum fields, the EnumValueDescriptor for the value is returned. For
     * embedded message fields, the sub-message is returned.  For repeated
     * fields, a java.util.List is returned. For present string fields, a
     * ByteString is returned representing the bytes that the field contains.
     */
    Object getFieldRaw(final FieldDescriptor field) {
      return internalGetFieldAccessorTable().getField(field).getRaw(this);
    }
  
    @Override
    public int getRepeatedFieldCount(final FieldDescriptor field) {
      return internalGetFieldAccessorTable().getField(field)
        .getRepeatedCount(this);
    }
  
    @Override
    public Object getRepeatedField(final FieldDescriptor field, final int index) {
      return internalGetFieldAccessorTable().getField(field)
        .getRepeated(this, index);
    }
  
    @Override
    public UnknownFieldSet getUnknownFields() {
      throw new UnsupportedOperationException(
          "This is supposed to be overridden by subclasses.");
    }
  
    /**
     * Called by subclasses to parse an unknown field.
     * @return {@code true} unless the tag is an end-group tag.
     */
    protected boolean parseUnknownField(
        CodedInputStream input,
        UnknownFieldSet.Builder unknownFields,
        ExtensionRegistryLite extensionRegistry,
        int tag) throws IOException {
      return unknownFields.mergeFieldFrom(tag, input);
    }
  
    protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input)
        throws IOException {
      try {
        return parser.parseFrom(input);
      } catch (InvalidProtocolBufferException e) {
        throw e.unwrapIOException();
      }
    }
  
    protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input,
        ExtensionRegistryLite extensions) throws IOException {
      try {
        return parser.parseFrom(input, extensions);
      } catch (InvalidProtocolBufferException e) {
        throw e.unwrapIOException();
      }
    }
  
    protected static <M extends Message> M parseWithIOException(Parser<M> parser,
        CodedInputStream input) throws IOException {
      try {
        return parser.parseFrom(input);
      } catch (InvalidProtocolBufferException e) {
        throw e.unwrapIOException();
      }
    }
  
    protected static <M extends Message> M parseWithIOException(Parser<M> parser,
        CodedInputStream input, ExtensionRegistryLite extensions) throws IOException {
      try {
        return parser.parseFrom(input, extensions);
      } catch (InvalidProtocolBufferException e) {
        throw e.unwrapIOException();
      }
    }
  
    protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
        InputStream input) throws IOException {
      try {
        return parser.parseDelimitedFrom(input);
      } catch (InvalidProtocolBufferException e) {
        throw e.unwrapIOException();
      }
    }
  
    protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
        InputStream input, ExtensionRegistryLite extensions) throws IOException {
      try {
        return parser.parseDelimitedFrom(input, extensions);
      } catch (InvalidProtocolBufferException e) {
        throw e.unwrapIOException();
      }
    }
  
    @Override
    public void writeTo(final CodedOutputStream output) throws IOException {
      MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false);
    }
  
    @Override
    public int getSerializedSize() {
      int size = memoizedSize;
      if (size != -1) {
        return size;
      }
  
      memoizedSize = MessageReflection.getSerializedSize(
          this, getAllFieldsRaw());
      return memoizedSize;
    }
  
  
  
    /**
     * Used by parsing constructors in generated classes.
     */
    protected void makeExtensionsImmutable() {
      // Noop for messages without extensions.
    }
  
    /**
     * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this
     * interface to AbstractMessage in order to versioning GeneratedMessage but
     * this move breaks binary compatibility for AppEngine. After AppEngine is
     * fixed we can exlude this from google3.
     */
    protected interface BuilderParent extends AbstractMessage.BuilderParent {}
  
    /**
     * TODO(xiaofeng): remove this together with GeneratedMessage.BuilderParent.
     */
    protected abstract Message.Builder newBuilderForType(BuilderParent parent);
  
    @Override
    protected Message.Builder newBuilderForType(final AbstractMessage.BuilderParent parent) {
      return newBuilderForType(new BuilderParent() {
        @Override
        public void markDirty() {
          parent.markDirty();
        }
      });
    }
  
  
    @SuppressWarnings("unchecked")
    public abstract static class Builder <BuilderType extends Builder<BuilderType>>
        extends AbstractMessage.Builder<BuilderType> {
  
      private BuilderParent builderParent;
  
      private BuilderParentImpl meAsParent;
  
      // Indicates that we've built a message and so we are now obligated
      // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
      private boolean isClean;
  
      private UnknownFieldSet unknownFields =
          UnknownFieldSet.getDefaultInstance();
  
      protected Builder() {
        this(null);
      }
  
      protected Builder(BuilderParent builderParent) {
        this.builderParent = builderParent;
      }
  
      @Override
      void dispose() {
        builderParent = null;
      }
  
      /**
       * Called by the subclass when a message is built.
       */
      protected void onBuilt() {
        if (builderParent != null) {
          markClean();
        }
      }
  
      /**
       * Called by the subclass or a builder to notify us that a message was
       * built and may be cached and therefore invalidations are needed.
       */
      @Override
      protected void markClean() {
        this.isClean = true;
      }
  
      /**
       * Gets whether invalidations are needed
       *
       * @return whether invalidations are needed
       */
      protected boolean isClean() {
        return isClean;
      }
  
      @Override
      public BuilderType clone() {
        BuilderType builder =
            (BuilderType) getDefaultInstanceForType().newBuilderForType();
        builder.mergeFrom(buildPartial());
        return builder;
      }
  
      /**
       * Called by the initialization and clear code paths to allow subclasses to
       * reset any of their builtin fields back to the initial values.
       */
      @Override
      public BuilderType clear() {
        unknownFields = UnknownFieldSet.getDefaultInstance();
        onChanged();
        return (BuilderType) this;
      }
  
      /**
       * Get the FieldAccessorTable for this type.  We can't have the message
       * class pass this in to the constructor because of bootstrapping trouble
       * with DescriptorProtos.
       */
      protected abstract FieldAccessorTable internalGetFieldAccessorTable();
  
      @Override
      public Descriptor getDescriptorForType() {
        return internalGetFieldAccessorTable().descriptor;
      }
  
      @Override
      public Map<FieldDescriptor, Object> getAllFields() {
        return Collections.unmodifiableMap(getAllFieldsMutable());
      }
  
      /** Internal helper which returns a mutable map. */
      private Map<FieldDescriptor, Object> getAllFieldsMutable() {
        final TreeMap<FieldDescriptor, Object> result =
          new TreeMap<FieldDescriptor, Object>();
        final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
        final List<FieldDescriptor> fields = descriptor.getFields();
  
        for (int i = 0; i < fields.size(); i++) {
          FieldDescriptor field = fields.get(i);
          final OneofDescriptor oneofDescriptor = field.getContainingOneof();
  
          /*
           * If the field is part of a Oneof, then at maximum one field in the Oneof is set
           * and it is not repeated. There is no need to iterate through the others.
           */
          if (oneofDescriptor != null) {
            // Skip other fields in the Oneof we know are not set
            i += oneofDescriptor.getFieldCount() - 1;
            if (!hasOneof(oneofDescriptor)) {
              // If no field is set in the Oneof, skip all the fields in the Oneof
              continue;
            }
            // Get the pointer to the only field which is set in the Oneof
            field = getOneofFieldDescriptor(oneofDescriptor);
          } else {
            // If we are not in a Oneof, we need to check if the field is set and if it is repeated
            if (field.isRepeated()) {
              final List<?> value = (List<?>) getField(field);
              if (!value.isEmpty()) {
                result.put(field, value);
              }
              continue;
            }
            if (!hasField(field)) {
              continue;
            }
          }
          // Add the field to the map
          result.put(field, getField(field));
        }
        return result;
      }
  
      @Override
      public Message.Builder newBuilderForField(final FieldDescriptor field) {
        return internalGetFieldAccessorTable().getField(field).newBuilder();
      }
  
      @Override
      public Message.Builder getFieldBuilder(final FieldDescriptor field) {
        return internalGetFieldAccessorTable().getField(field).getBuilder(this);
      }
  
      @Override
      public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
        return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(
            this, index);
      }
  
      @Override
      public boolean hasOneof(final OneofDescriptor oneof) {
        return internalGetFieldAccessorTable().getOneof(oneof).has(this);
      }
  
      @Override
      public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
        return internalGetFieldAccessorTable().getOneof(oneof).get(this);
      }
  
      @Override
      public boolean hasField(final FieldDescriptor field) {
        return internalGetFieldAccessorTable().getField(field).has(this);
      }
  
      @Override
      public Object getField(final FieldDescriptor field) {
        Object object = internalGetFieldAccessorTable().getField(field).get(this);
        if (field.isRepeated()) {
          // The underlying list object is still modifiable at this point.
          // Make sure not to expose the modifiable list to the caller.
          return Collections.unmodifiableList((List) object);
        } else {
          return object;
        }
      }
  
      @Override
      public BuilderType setField(final FieldDescriptor field, final Object value) {
        internalGetFieldAccessorTable().getField(field).set(this, value);
        return (BuilderType) this;
      }
  
      @Override
      public BuilderType clearField(final FieldDescriptor field) {
        internalGetFieldAccessorTable().getField(field).clear(this);
        return (BuilderType) this;
      }
  
      @Override
      public BuilderType clearOneof(final OneofDescriptor oneof) {
        internalGetFieldAccessorTable().getOneof(oneof).clear(this);
        return (BuilderType) this;
      }
  
      @Override
      public int getRepeatedFieldCount(final FieldDescriptor field) {
        return internalGetFieldAccessorTable().getField(field)
            .getRepeatedCount(this);
      }
  
      @Override
      public Object getRepeatedField(final FieldDescriptor field, final int index) {
        return internalGetFieldAccessorTable().getField(field)
            .getRepeated(this, index);
      }
  
      @Override
      public BuilderType setRepeatedField(
          final FieldDescriptor field, final int index, final Object value) {
        internalGetFieldAccessorTable().getField(field)
          .setRepeated(this, index, value);
        return (BuilderType) this;
      }
  
      @Override
      public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) {
        internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
        return (BuilderType) this;
      }
  
      @Override
      public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) {
        this.unknownFields = unknownFields;
        onChanged();
        return (BuilderType) this;
      }
  
      @Override
      public BuilderType mergeUnknownFields(
          final UnknownFieldSet unknownFields) {
        this.unknownFields =
          UnknownFieldSet.newBuilder(this.unknownFields)
                         .mergeFrom(unknownFields)
                         .build();
        onChanged();
        return (BuilderType) this;
      }
  
      @Override
      public boolean isInitialized() {
        for (final FieldDescriptor field : getDescriptorForType().getFields()) {
          // Check that all required fields are present.
          if (field.isRequired()) {
            if (!hasField(field)) {
              return false;
            }
          }
          // Check that embedded messages are initialized.
          if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
            if (field.isRepeated()) {
              @SuppressWarnings("unchecked") final
              List<Message> messageList = (List<Message>) getField(field);
              for (final Message element : messageList) {
                if (!element.isInitialized()) {
                  return false;
                }
              }
            } else {
              if (hasField(field) &&
                  !((Message) getField(field)).isInitialized()) {
                return false;
              }
            }
          }
        }
        return true;
      }
  
      @Override
      public final UnknownFieldSet getUnknownFields() {
        return unknownFields;
      }
  
      /**
       * Called by subclasses to parse an unknown field.
       * @return {@code true} unless the tag is an end-group tag.
       */
      protected boolean parseUnknownField(
          final CodedInputStream input,
          final UnknownFieldSet.Builder unknownFields,
          final ExtensionRegistryLite extensionRegistry,
          final int tag) throws IOException {
        return unknownFields.mergeFieldFrom(tag, input);
      }
  
      /**
       * Implementation of {@link BuilderParent} for giving to our children. This
       * small inner class makes it so we don't publicly expose the BuilderParent
       * methods.
       */
      private class BuilderParentImpl implements BuilderParent {
  
        @Override
        public void markDirty() {
          onChanged();
        }
      }
  
      /**
       * Gets the {@link BuilderParent} for giving to our children.
       * @return The builder parent for our children.
       */
      protected BuilderParent getParentForChildren() {
        if (meAsParent == null) {
          meAsParent = new BuilderParentImpl();
        }
        return meAsParent;
      }
  
      /**
       * Called when a the builder or one of its nested children has changed
       * and any parent should be notified of its invalidation.
       */
      protected final void onChanged() {
        if (isClean && builderParent != null) {
          builderParent.markDirty();
  
          // Don't keep dispatching invalidations until build is called again.
          isClean = false;
        }
      }
  
      /**
       * Gets the map field with the given field number. This method should be
       * overridden in the generated message class if the message contains map
       * fields.
       *
       * Unlike other field types, reflection support for map fields can't be
       * implemented based on generated public API because we need to access a
       * map field as a list in reflection API but the generated API only allows
       * us to access it as a map. This method returns the underlying map field
       * directly and thus enables us to access the map field as a list.
       */
      @SuppressWarnings({"unused", "rawtypes"})
      protected MapField internalGetMapField(int fieldNumber) {
        // Note that we can't use descriptor names here because this method will
        // be called when descriptor is being initialized.
        throw new RuntimeException(
            "No map fields found in " + getClass().getName());
      }
  
      /** Like {@link #internalGetMapField} but return a mutable version. */
      @SuppressWarnings({"unused", "rawtypes"})
      protected MapField internalGetMutableMapField(int fieldNumber) {
        // Note that we can't use descriptor names here because this method will
        // be called when descriptor is being initialized.
        throw new RuntimeException(
            "No map fields found in " + getClass().getName());
      }
    }
  
    // =================================================================
    // Extensions-related stuff
  
    public interface ExtendableMessageOrBuilder<
        MessageType extends ExtendableMessage> extends MessageOrBuilder {
      // Re-define for return type covariance.
      @Override
      Message getDefaultInstanceForType();
  
      /** Check if a singular extension is present. */
      <Type> boolean hasExtension(
          ExtensionLite<MessageType, Type> extension);
  
      /** Get the number of elements in a repeated extension. */
      <Type> int getExtensionCount(
          ExtensionLite<MessageType, List<Type>> extension);
  
      /** Get the value of an extension. */
      <Type> Type getExtension(
          ExtensionLite<MessageType, Type> extension);
  
      /** Get one element of a repeated extension. */
      <Type> Type getExtension(
          ExtensionLite<MessageType, List<Type>> extension,
          int index);
  
      /** Check if a singular extension is present. */
      <Type> boolean hasExtension(
          Extension<MessageType, Type> extension);
      /** Check if a singular extension is present. */
      <Type> boolean hasExtension(
          GeneratedExtension<MessageType, Type> extension);
      /** Get the number of elements in a repeated extension. */
      <Type> int getExtensionCount(
          Extension<MessageType, List<Type>> extension);
      /** Get the number of elements in a repeated extension. */
      <Type> int getExtensionCount(
          GeneratedExtension<MessageType, List<Type>> extension);
      /** Get the value of an extension. */
      <Type> Type getExtension(
          Extension<MessageType, Type> extension);
      /** Get the value of an extension. */
      <Type> Type getExtension(
          GeneratedExtension<MessageType, Type> extension);
      /** Get one element of a repeated extension. */
      <Type> Type getExtension(
          Extension<MessageType, List<Type>> extension,
          int index);
      /** Get one element of a repeated extension. */
      <Type> Type getExtension(
          GeneratedExtension<MessageType, List<Type>> extension,
          int index);
    }
  
    /**
     * Generated message classes for message types that contain extension ranges
     * subclass this.
     *
     * <p>This class implements type-safe accessors for extensions.  They
     * implement all the same operations that you can do with normal fields --
     * e.g. "has", "get", and "getCount" -- but for extensions.  The extensions
     * are identified using instances of the class {@link GeneratedExtension};
     * the protocol compiler generates a static instance of this class for every
     * extension in its input.  Through the magic of generics, all is made
     * type-safe.
     *
     * <p>For example, imagine you have the {@code .proto} file:
     *
     * <pre>
     * option java_class = "MyProto";
     *
     * message Foo {
     *   extensions 1000 to max;
     * }
     *
     * extend Foo {
     *   optional int32 bar;
     * }
     * </pre>
     *
     * <p>Then you might write code like:
     *
     * <pre>
     * MyProto.Foo foo = getFoo();
     * int i = foo.getExtension(MyProto.bar);
     * </pre>
     *
     * <p>See also {@link ExtendableBuilder}.
     */
    public abstract static class ExtendableMessage<
          MessageType extends ExtendableMessage>
        extends GeneratedMessage
        implements ExtendableMessageOrBuilder<MessageType> {
  
      private static final long serialVersionUID = 1L;
  
      private final FieldSet<FieldDescriptor> extensions;
  
      protected ExtendableMessage() {
        this.extensions = FieldSet.newFieldSet();
      }
  
      protected ExtendableMessage(
          ExtendableBuilder<MessageType, ?> builder) {
        super(builder);
        this.extensions = builder.buildExtensions();
      }
  
      private void verifyExtensionContainingType(
          final Extension<MessageType, ?> extension) {
        if (extension.getDescriptor().getContainingType() !=
            getDescriptorForType()) {
          // This can only happen if someone uses unchecked operations.
          throw new IllegalArgumentException(
            "Extension is for type \"" +
            extension.getDescriptor().getContainingType().getFullName() +
            "\" which does not match message type \"" +
            getDescriptorForType().getFullName() + "\".");
        }
      }
  
      /** Check if a singular extension is present. */
      @Override
      @SuppressWarnings("unchecked")
      public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
        Extension<MessageType, Type> extension = checkNotLite(extensionLite);
  
        verifyExtensionContainingType(extension);
        return extensions.hasField(extension.getDescriptor());
      }
  
      /** Get the number of elements in a repeated extension. */
      @Override
      @SuppressWarnings("unchecked")
      public final <Type> int getExtensionCount(
          final ExtensionLite<MessageType, List<Type>> extensionLite) {
        Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
  
        verifyExtensionContainingType(extension);
        final FieldDescriptor descriptor = extension.getDescriptor();
        return extensions.getRepeatedFieldCount(descriptor);
      }
  
      /** Get the value of an extension. */
      @Override
      @SuppressWarnings("unchecked")
      public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
        Extension<MessageType, Type> extension = checkNotLite(extensionLite);
  
        verifyExtensionContainingType(extension);
        FieldDescriptor descriptor = extension.getDescriptor();
        final Object value = extensions.getField(descriptor);
        if (value == null) {
          if (descriptor.isRepeated()) {
            return (Type) Collections.emptyList();
          } else if (descriptor.getJavaType() ==
                     FieldDescriptor.JavaType.MESSAGE) {
            return (Type) extension.getMessageDefaultInstance();
          } else {
            return (Type) extension.fromReflectionType(
                descriptor.getDefaultValue());
          }
        } else {
          return (Type) extension.fromReflectionType(value);
        }
      }
  
      /** Get one element of a repeated extension. */
      @Override
      @SuppressWarnings("unchecked")
      public final <Type> Type getExtension(
          final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
        Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
  
        verifyExtensionContainingType(extension);
        FieldDescriptor descriptor = extension.getDescriptor();
        return (Type) extension.singularFromReflectionType(
            extensions.getRepeatedField(descriptor, index));
      }
  
      /** Check if a singular extension is present. */
      @Override
      public final <Type> boolean hasExtension(final Extension<MessageType, Type> extension) {
        return hasExtension((ExtensionLite<MessageType, Type>) extension);
      }
      /** Check if a singular extension is present. */
      @Override
      public final <Type> boolean hasExtension(
          final GeneratedExtension<MessageType, Type> extension) {
        return hasExtension((ExtensionLite<MessageType, Type>) extension);
      }
      /** Get the number of elements in a repeated extension. */
      @Override
      public final <Type> int getExtensionCount(
          final Extension<MessageType, List<Type>> extension) {
        return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
      }
      /** Get the number of elements in a repeated extension. */
      @Override
      public final <Type> int getExtensionCount(
          final GeneratedExtension<MessageType, List<Type>> extension) {
        return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
      }
      /** Get the value of an extension. */
      @Override
      public final <Type> Type getExtension(final Extension<MessageType, Type> extension) {
        return getExtension((ExtensionLite<MessageType, Type>) extension);
      }
      /** Get the value of an extension. */
      @Override
      public final <Type> Type getExtension(
          final GeneratedExtension<MessageType, Type> extension) {
        return getExtension((ExtensionLite<MessageType, Type>) extension);
      }
      /** Get one element of a repeated extension. */
      @Override
      public final <Type> Type getExtension(
          final Extension<MessageType, List<Type>> extension, final int index) {
        return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
      }
      /** Get one element of a repeated extension. */
      @Override
      public final <Type> Type getExtension(
          final GeneratedExtension<MessageType, List<Type>> extension, final int index) {
        return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
      }
  
      /** Called by subclasses to check if all extensions are initialized. */
      protected boolean extensionsAreInitialized() {
        return extensions.isInitialized();
      }
  
      @Override
      public boolean isInitialized() {
        return super.isInitialized() && extensionsAreInitialized();
      }
  
      @Override
      protected boolean parseUnknownField(
          CodedInputStream input,
          UnknownFieldSet.Builder unknownFields,
          ExtensionRegistryLite extensionRegistry,
          int tag) throws IOException {
        return MessageReflection.mergeFieldFrom(
            input, unknownFields, extensionRegistry, getDescriptorForType(),
            new MessageReflection.ExtensionAdapter(extensions), tag);
      }
  
  
      /**
       * Used by parsing constructors in generated classes.
       */
      @Override
      protected void makeExtensionsImmutable() {
        extensions.makeImmutable();
      }
  
      /**
       * Used by subclasses to serialize extensions.  Extension ranges may be
       * interleaved with field numbers, but we must write them in canonical
       * (sorted by field number) order.  ExtensionWriter helps us write
       * individual ranges of extensions at once.
       */
      protected class ExtensionWriter {
        // Imagine how much simpler this code would be if Java iterators had
        // a way to get the next element without advancing the iterator.
  
        private final Iterator<Map.Entry<FieldDescriptor, Object>> iter =
          extensions.iterator();
        private Map.Entry<FieldDescriptor, Object> next;
        private final boolean messageSetWireFormat;
  
        private ExtensionWriter(final boolean messageSetWireFormat) {
          if (iter.hasNext()) {
            next = iter.next();
          }
          this.messageSetWireFormat = messageSetWireFormat;
        }
  
        public void writeUntil(final int end, final CodedOutputStream output)
                               throws IOException {
          while (next != null && next.getKey().getNumber() < end) {
            FieldDescriptor descriptor = next.getKey();
            if (messageSetWireFormat && descriptor.getLiteJavaType() ==
                    WireFormat.JavaType.MESSAGE &&
                !descriptor.isRepeated()) {
              if (next instanceof LazyField.LazyEntry<?>) {
                output.writeRawMessageSetExtension(descriptor.getNumber(),
                    ((LazyField.LazyEntry<?>) next).getField().toByteString());
              } else {
                output.writeMessageSetExtension(descriptor.getNumber(),
                                                (Message) next.getValue());
              }
            } else {
              // TODO(xiangl): Taken care of following code, it may cause
              // problem when we use LazyField for normal fields/extensions.
              // Due to the optional field can be duplicated at the end of
              // serialized bytes, which will make the serialized size change
              // after lazy field parsed. So when we use LazyField globally,
              // we need to change the following write method to write cached
              // bytes directly rather than write the parsed message.
              FieldSet.writeField(descriptor, next.getValue(), output);
            }
            if (iter.hasNext()) {
              next = iter.next();
            } else {
              next = null;
            }
          }
        }
      }
  
      protected ExtensionWriter newExtensionWriter() {
        return new ExtensionWriter(false);
      }
      protected ExtensionWriter newMessageSetExtensionWriter() {
        return new ExtensionWriter(true);
      }
  
      /** Called by subclasses to compute the size of extensions. */
      protected int extensionsSerializedSize() {
        return extensions.getSerializedSize();
      }
      protected int extensionsSerializedSizeAsMessageSet() {
        return extensions.getMessageSetSerializedSize();
      }
  
      // ---------------------------------------------------------------
      // Reflection
  
      protected Map<FieldDescriptor, Object> getExtensionFields() {
        return extensions.getAllFields();
      }
  
      @Override
      public Map<FieldDescriptor, Object> getAllFields() {
        final Map<FieldDescriptor, Object> result =
            super.getAllFieldsMutable(/* getBytesForString = */ false);
        result.putAll(getExtensionFields());
        return Collections.unmodifiableMap(result);
      }
  
      @Override
      public Map<FieldDescriptor, Object> getAllFieldsRaw() {
        final Map<FieldDescriptor, Object> result =
            super.getAllFieldsMutable(/* getBytesForString = */ false);
        result.putAll(getExtensionFields());
        return Collections.unmodifiableMap(result);
      }
  
      @Override
      public boolean hasField(final FieldDescriptor field) {
        if (field.isExtension()) {
          verifyContainingType(field);
          return extensions.hasField(field);
        } else {
          return super.hasField(field);
        }
      }
  
      @Override
      public Object getField(final FieldDescriptor field) {
        if (field.isExtension()) {
          verifyContainingType(field);
          final Object value = extensions.getField(field);
          if (value == null) {
            if (field.isRepeated()) {
              return Collections.emptyList();
            } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
              // Lacking an ExtensionRegistry, we have no way to determine the
              // extension's real type, so we return a DynamicMessage.
              return DynamicMessage.getDefaultInstance(field.getMessageType());
            } else {
              return field.getDefaultValue();
            }
          } else {
            return value;
          }
        } else {
          return super.getField(field);
        }
      }
  
      @Override
      public int getRepeatedFieldCount(final FieldDescriptor field) {
        if (field.isExtension()) {
          verifyContainingType(field);
          return extensions.getRepeatedFieldCount(field);
        } else {
          return super.getRepeatedFieldCount(field);
        }
      }
  
      @Override
      public Object getRepeatedField(final FieldDescriptor field,
                                     final int index) {
        if (field.isExtension()) {
          verifyContainingType(field);
          return extensions.getRepeatedField(field, index);
        } else {
          return super.getRepeatedField(field, index);
        }
      }
  
      private void verifyContainingType(final FieldDescriptor field) {
        if (field.getContainingType() != getDescriptorForType()) {
          throw new IllegalArgumentException(
            "FieldDescriptor does not match message type.");
        }
      }
    }
  
    /**
     * Generated message builders for message types that contain extension ranges
     * subclass this.
     *
     * <p>This class implements type-safe accessors for extensions.  They
     * implement all the same operations that you can do with normal fields --
     * e.g. "get", "set", and "add" -- but for extensions.  The extensions are
     * identified using instances of the class {@link GeneratedExtension}; the
     * protocol compiler generates a static instance of this class for every
     * extension in its input.  Through the magic of generics, all is made
     * type-safe.
     *
     * <p>For example, imagine you have the {@code .proto} file:
     *
     * <pre>
     * option java_class = "MyProto";
     *
     * message Foo {
     *   extensions 1000 to max;
     * }
     *
     * extend Foo {
     *   optional int32 bar;
     * }
     * </pre>
     *
     * <p>Then you might write code like:
     *
     * <pre>
     * MyProto.Foo foo =
     *   MyProto.Foo.newBuilder()
     *     .setExtension(MyProto.bar, 123)
     *     .build();
     * </pre>
     *
     * <p>See also {@link ExtendableMessage}.
     */
    @SuppressWarnings("unchecked")
    public abstract static class ExtendableBuilder<
          MessageType extends ExtendableMessage,
          BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
        extends Builder<BuilderType>
        implements ExtendableMessageOrBuilder<MessageType> {
  
      private FieldSet<FieldDescriptor> extensions = FieldSet.emptySet();
  
      protected ExtendableBuilder() {}
  
      protected ExtendableBuilder(
          BuilderParent parent) {
        super(parent);
      }
  
      // For immutable message conversion.
      void internalSetExtensionSet(FieldSet<FieldDescriptor> extensions) {
        this.extensions = extensions;
      }
  
      @Override
      public BuilderType clear() {
        extensions = FieldSet.emptySet();
        return super.clear();
      }
  
      // This is implemented here only to work around an apparent bug in the
      // Java compiler and/or build system.  See bug #1898463.  The mere presence
      // of this clone() implementation makes it go away.
      @Override
      public BuilderType clone() {
        return super.clone();
      }
  
      private void ensureExtensionsIsMutable() {
        if (extensions.isImmutable()) {
          extensions = extensions.clone();
        }
      }
  
      private void verifyExtensionContainingType(
          final Extension<MessageType, ?> extension) {
        if (extension.getDescriptor().getContainingType() !=
            getDescriptorForType()) {
          // This can only happen if someone uses unchecked operations.
          throw new IllegalArgumentException(
            "Extension is for type \"" +
            extension.getDescriptor().getContainingType().getFullName() +
            "\" which does not match message type \"" +
            getDescriptorForType().getFullName() + "\".");
        }
      }
  
      /** Check if a singular extension is present. */
      @Override
      public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
        Extension<MessageType, Type> extension = checkNotLite(extensionLite);
  
        verifyExtensionContainingType(extension);
        return extensions.hasField(extension.getDescriptor());
      }
  
      /** Get the number of elements in a repeated extension. */
      @Override
      public final <Type> int getExtensionCount(
          final ExtensionLite<MessageType, List<Type>> extensionLite) {
        Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
  
        verifyExtensionContainingType(extension);
        final FieldDescriptor descriptor = extension.getDescriptor();
        return extensions.getRepeatedFieldCount(descriptor);
      }
  
      /** Get the value of an extension. */
      @Override
      public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
        Extension<MessageType, Type> extension = checkNotLite(extensionLite);
  
        verifyExtensionContainingType(extension);
        FieldDescriptor descriptor = extension.getDescriptor();
        final Object value = extensions.getField(descriptor);
        if (value == null) {
          if (descriptor.isRepeated()) {
            return (Type) Collections.emptyList();
          } else if (descriptor.getJavaType() ==
                     FieldDescriptor.JavaType.MESSAGE) {
            return (Type) extension.getMessageDefaultInstance();
          } else {
            return (Type) extension.fromReflectionType(
                descriptor.getDefaultValue());
          }
        } else {
          return (Type) extension.fromReflectionType(value);
        }
      }
  
      /** Get one element of a repeated extension. */
      @Override
      public final <Type> Type getExtension(
          final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
        Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
  
        verifyExtensionContainingType(extension);
        FieldDescriptor descriptor = extension.getDescriptor();
        return (Type) extension.singularFromReflectionType(
            extensions.getRepeatedField(descriptor, index));
      }
  
      /** Set the value of an extension. */
      public final <Type> BuilderType setExtension(
          final ExtensionLite<MessageType, Type> extensionLite,
          final Type value) {
        Extension<MessageType, Type> extension = checkNotLite(extensionLite);
  
        verifyExtensionContainingType(extension);
        ensureExtensionsIsMutable();
        final FieldDescriptor descriptor = extension.getDescriptor();
        extensions.setField(descriptor, extension.toReflectionType(value));
        onChanged();
        return (BuilderType) this;
      }
  
      /** Set the value of one element of a repeated extension. */
      public final <Type> BuilderType setExtension(
          final ExtensionLite<MessageType, List<Type>> extensionLite,
          final int index, final Type value) {
        Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
  
        verifyExtensionContainingType(extension);
        ensureExtensionsIsMutable();
        final FieldDescriptor descriptor = extension.getDescriptor();
        extensions.setRepeatedField(
          descriptor, index,
          extension.singularToReflectionType(value));
        onChanged();
        return (BuilderType) this;
      }
  
      /** Append a value to a repeated extension. */
      public final <Type> BuilderType addExtension(
          final ExtensionLite<MessageType, List<Type>> extensionLite,
          final Type value) {
        Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
  
        verifyExtensionContainingType(extension);
        ensureExtensionsIsMutable();
        final FieldDescriptor descriptor = extension.getDescriptor();
        extensions.addRepeatedField(
            descriptor, extension.singularToReflectionType(value));
        onChanged();
        return (BuilderType) this;
      }
  
      /** Clear an extension. */
      public final <Type> BuilderType clearExtension(
          final ExtensionLite<MessageType, ?> extensionLite) {
        Extension<MessageType, ?> extension = checkNotLite(extensionLite);
  
        verifyExtensionContainingType(extension);
        ensureExtensionsIsMutable();
        extensions.clearField(extension.getDescriptor());
        onChanged();
        return (BuilderType) this;
      }
  
      /** Check if a singular extension is present. */
      @Override
      public final <Type> boolean hasExtension(final Extension<MessageType, Type> extension) {
        return hasExtension((ExtensionLite<MessageType, Type>) extension);
      }
      /** Check if a singular extension is present. */
      @Override
      public final <Type> boolean hasExtension(
          final GeneratedExtension<MessageType, Type> extension) {
        return hasExtension((ExtensionLite<MessageType, Type>) extension);
      }
      /** Get the number of elements in a repeated extension. */
      @Override
      public final <Type> int getExtensionCount(
          final Extension<MessageType, List<Type>> extension) {
        return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
      }
      /** Get the number of elements in a repeated extension. */
      @Override
      public final <Type> int getExtensionCount(
          final GeneratedExtension<MessageType, List<Type>> extension) {
        return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
      }
      /** Get the value of an extension. */
      @Override
      public final <Type> Type getExtension(final Extension<MessageType, Type> extension) {
        return getExtension((ExtensionLite<MessageType, Type>) extension);
      }
      /** Get the value of an extension. */
      @Override
      public final <Type> Type getExtension(
          final GeneratedExtension<MessageType, Type> extension) {
        return getExtension((ExtensionLite<MessageType, Type>) extension);
      }
      /** Get the value of an extension. */
      @Override
      public final <Type> Type getExtension(
          final Extension<MessageType, List<Type>> extension, final int index) {
        return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
      }
      /** Get the value of an extension. */
      @Override
      public final <Type> Type getExtension(
          final GeneratedExtension<MessageType, List<Type>> extension, final int index) {
        return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
      }
      /** Set the value of an extension. */
      public final <Type> BuilderType setExtension(
          final Extension<MessageType, Type> extension, final Type value) {
        return setExtension((ExtensionLite<MessageType, Type>) extension, value);
      }
      /** Set the value of an extension. */
      public <Type> BuilderType setExtension(
          final GeneratedExtension<MessageType, Type> extension, final Type value) {
        return setExtension((ExtensionLite<MessageType, Type>) extension, value);
      }
      /** Set the value of one element of a repeated extension. */
      public final <Type> BuilderType setExtension(
          final Extension<MessageType, List<Type>> extension,
          final int index, final Type value) {
        return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
      }
      /** Set the value of one element of a repeated extension. */
      public <Type> BuilderType setExtension(
          final GeneratedExtension<MessageType, List<Type>> extension,
          final int index, final Type value) {
        return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
      }
      /** Append a value to a repeated extension. */
      public final <Type> BuilderType addExtension(
          final Extension<MessageType, List<Type>> extension, final Type value) {
        return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
      }
      /** Append a value to a repeated extension. */
      public <Type> BuilderType addExtension(
          final GeneratedExtension<MessageType, List<Type>> extension, final Type value) {
        return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
      }
      /** Clear an extension. */
      public final <Type> BuilderType clearExtension(
          final Extension<MessageType, ?> extension) {
        return clearExtension((ExtensionLite<MessageType, ?>) extension);
      }
      /** Clear an extension. */
      public <Type> BuilderType clearExtension(
          final GeneratedExtension<MessageType, ?> extension) {
        return clearExtension((ExtensionLite<MessageType, ?>) extension);
      }
  
      /** Called by subclasses to check if all extensions are initialized. */
      protected boolean extensionsAreInitialized() {
        return extensions.isInitialized();
      }
  
      /**
       * Called by the build code path to create a copy of the extensions for
       * building the message.
       */
      private FieldSet<FieldDescriptor> buildExtensions() {
        extensions.makeImmutable();
        return extensions;
      }
  
      @Override
      public boolean isInitialized() {
        return super.isInitialized() && extensionsAreInitialized();
      }
  
      /**
       * Called by subclasses to parse an unknown field or an extension.
       * @return {@code true} unless the tag is an end-group tag.
       */
      @Override
      protected boolean parseUnknownField(
          final CodedInputStream input,
          final UnknownFieldSet.Builder unknownFields,
          final ExtensionRegistryLite extensionRegistry,
          final int tag) throws IOException {
        return MessageReflection.mergeFieldFrom(
            input, unknownFields, extensionRegistry, getDescriptorForType(),
            new MessageReflection.BuilderAdapter(this), tag);
      }
  
      // ---------------------------------------------------------------
      // Reflection
  
      @Override
      public Map<FieldDescriptor, Object> getAllFields() {
        final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
        result.putAll(extensions.getAllFields());
        return Collections.unmodifiableMap(result);
      }
  
      @Override
      public Object getField(final FieldDescriptor field) {
        if (field.isExtension()) {
          verifyContainingType(field);
          final Object value = extensions.getField(field);
          if (value == null) {
            if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
              // Lacking an ExtensionRegistry, we have no way to determine the
              // extension's real type, so we return a DynamicMessage.
              return DynamicMessage.getDefaultInstance(field.getMessageType());
            } else {
              return field.getDefaultValue();
            }
          } else {
            return value;
          }
        } else {
          return super.getField(field);
        }
      }
  
      @Override
      public int getRepeatedFieldCount(final FieldDescriptor field) {
        if (field.isExtension()) {
          verifyContainingType(field);
          return extensions.getRepeatedFieldCount(field);
        } else {
          return super.getRepeatedFieldCount(field);
        }
      }
  
      @Override
      public Object getRepeatedField(final FieldDescriptor field,
                                     final int index) {
        if (field.isExtension()) {
          verifyContainingType(field);
          return extensions.getRepeatedField(field, index);
        } else {
          return super.getRepeatedField(field, index);
        }
      }
  
      @Override
      public boolean hasField(final FieldDescriptor field) {
        if (field.isExtension()) {
          verifyContainingType(field);
          return extensions.hasField(field);
        } else {
          return super.hasField(field);
        }
      }
  
      @Override
      public BuilderType setField(final FieldDescriptor field,
                                  final Object value) {
        if (field.isExtension()) {
          verifyContainingType(field);
          ensureExtensionsIsMutable();
          extensions.setField(field, value);
          onChanged();
          return (BuilderType) this;
        } else {
          return super.setField(field, value);
        }
      }
  
      @Override
      public BuilderType clearField(final FieldDescriptor field) {
        if (field.isExtension()) {
          verifyContainingType(field);
          ensureExtensionsIsMutable();
          extensions.clearField(field);
          onChanged();
          return (BuilderType) this;
        } else {
          return super.clearField(field);
        }
      }
  
      @Override
      public BuilderType setRepeatedField(final FieldDescriptor field,
                                          final int index, final Object value) {
        if (field.isExtension()) {
          verifyContainingType(field);
          ensureExtensionsIsMutable();
          extensions.setRepeatedField(field, index, value);
          onChanged();
          return (BuilderType) this;
        } else {
          return super.setRepeatedField(field, index, value);
        }
      }
  
      @Override
      public BuilderType addRepeatedField(final FieldDescriptor field,
                                          final Object value) {
        if (field.isExtension()) {
          verifyContainingType(field);
          ensureExtensionsIsMutable();
          extensions.addRepeatedField(field, value);
          onChanged();
          return (BuilderType) this;
        } else {
          return super.addRepeatedField(field, value);
        }
      }
  
      protected final void mergeExtensionFields(final ExtendableMessage other) {
        ensureExtensionsIsMutable();
        extensions.mergeFrom(other.extensions);
        onChanged();
      }
  
      private void verifyContainingType(final FieldDescriptor field) {
        if (field.getContainingType() != getDescriptorForType()) {
          throw new IllegalArgumentException(
            "FieldDescriptor does not match message type.");
        }
      }
    }
  
    // -----------------------------------------------------------------
  
    /**
     * Gets the descriptor for an extension. The implementation depends on whether
     * the extension is scoped in the top level of a file or scoped in a Message.
     */
    static interface ExtensionDescriptorRetriever {
      FieldDescriptor getDescriptor();
    }
  
    /** For use by generated code only. */
    public static <ContainingType extends Message, Type>
        GeneratedExtension<ContainingType, Type>
        newMessageScopedGeneratedExtension(final Message scope,
                                           final int descriptorIndex,
                                           final Class singularType,
                                           final Message defaultInstance) {
      // For extensions scoped within a Message, we use the Message to resolve
      // the outer class's descriptor, from which the extension descriptor is
      // obtained.
      return new GeneratedExtension<ContainingType, Type>(
          new CachedDescriptorRetriever() {
            @Override
            public FieldDescriptor loadDescriptor() {
              return scope.getDescriptorForType().getExtensions().get(descriptorIndex);
            }
          },
          singularType,
          defaultInstance,
          Extension.ExtensionType.IMMUTABLE);
    }
  
    /** For use by generated code only. */
    public static <ContainingType extends Message, Type>
       GeneratedExtension<ContainingType, Type>
       newFileScopedGeneratedExtension(final Class singularType,
                                       final Message defaultInstance) {
      // For extensions scoped within a file, we rely on the outer class's
      // static initializer to call internalInit() on the extension when the
      // descriptor is available.
      return new GeneratedExtension<ContainingType, Type>(
          null,  // ExtensionDescriptorRetriever is initialized in internalInit();
          singularType,
          defaultInstance,
          Extension.ExtensionType.IMMUTABLE);
    }
  
    private abstract static class CachedDescriptorRetriever
        implements ExtensionDescriptorRetriever {
      private volatile FieldDescriptor descriptor;
      protected abstract FieldDescriptor loadDescriptor();
  
      @Override
      public FieldDescriptor getDescriptor() {
        if (descriptor == null) {
          synchronized (this) {
            if (descriptor == null) {
              descriptor = loadDescriptor();
            }
          }
        }
        return descriptor;
      }
    }
  
    /**
     * Used in proto1 generated code only.
     *
     * After enabling bridge, we can define proto2 extensions (the extended type
     * is a proto2 mutable message) in a proto1 .proto file. For these extensions
     * we should generate proto2 GeneratedExtensions.
     */
    public static <ContainingType extends Message, Type>
        GeneratedExtension<ContainingType, Type>
        newMessageScopedGeneratedExtension(
            final Message scope, final String name,
            final Class singularType, final Message defaultInstance) {
      // For extensions scoped within a Message, we use the Message to resolve
      // the outer class's descriptor, from which the extension descriptor is
      // obtained.
      return new GeneratedExtension<ContainingType, Type>(
          new CachedDescriptorRetriever() {
            @Override
            protected FieldDescriptor loadDescriptor() {
              return scope.getDescriptorForType().findFieldByName(name);
            }
          },
          singularType,
          defaultInstance,
          Extension.ExtensionType.MUTABLE);
    }
  
    /**
     * Used in proto1 generated code only.
     *
     * After enabling bridge, we can define proto2 extensions (the extended type
     * is a proto2 mutable message) in a proto1 .proto file. For these extensions
     * we should generate proto2 GeneratedExtensions.
     */
    public static <ContainingType extends Message, Type>
       GeneratedExtension<ContainingType, Type>
       newFileScopedGeneratedExtension(
           final Class singularType, final Message defaultInstance,
           final String descriptorOuterClass, final String extensionName) {
      // For extensions scoped within a file, we load the descriptor outer
      // class and rely on it to get the FileDescriptor which then can be
      // used to obtain the extension's FieldDescriptor.
      return new GeneratedExtension<ContainingType, Type>(
          new CachedDescriptorRetriever() {
            @Override
            protected FieldDescriptor loadDescriptor() {
              try {
                Class clazz = singularType.getClassLoader().loadClass(descriptorOuterClass);
                FileDescriptor file = (FileDescriptor) clazz.getField("descriptor").get(null);
                return file.findExtensionByName(extensionName);
              } catch (Exception e) {
                throw new RuntimeException(
                    "Cannot load descriptors: "
                        + descriptorOuterClass
                        + " is not a valid descriptor class name",
                    e);
              }
            }
          },
          singularType,
          defaultInstance,
          Extension.ExtensionType.MUTABLE);
    }
  
    /**
     * Type used to represent generated extensions.  The protocol compiler
     * generates a static singleton instance of this class for each extension.
     *
     * <p>For example, imagine you have the {@code .proto} file:
     *
     * <pre>
     * option java_class = "MyProto";
     *
     * message Foo {
     *   extensions 1000 to max;
     * }
     *
     * extend Foo {
     *   optional int32 bar;
     * }
     * </pre>
     *
     * <p>Then, {@code MyProto.Foo.bar} has type
     * {@code GeneratedExtension<MyProto.Foo, Integer>}.
     *
     * <p>In general, users should ignore the details of this type, and simply use
     * these static singletons as parameters to the extension accessors defined
     * in {@link ExtendableMessage} and {@link ExtendableBuilder}.
     */
    public static class GeneratedExtension<
        ContainingType extends Message, Type> extends
        Extension<ContainingType, Type> {
      // TODO(kenton):  Find ways to avoid using Java reflection within this
      //   class.  Also try to avoid suppressing unchecked warnings.
  
      // We can't always initialize the descriptor of a GeneratedExtension when
      // we first construct it due to initialization order difficulties (namely,
      // the descriptor may not have been constructed yet, since it is often
      // constructed by the initializer of a separate module).
      //
      // In the case of nested extensions, we initialize the
      // ExtensionDescriptorRetriever with an instance that uses the scoping
      // Message's default instance to retrieve the extension's descriptor.
      //
      // In the case of non-nested extensions, we initialize the
      // ExtensionDescriptorRetriever to null and rely on the outer class's static
      // initializer to call internalInit() after the descriptor has been parsed.
      GeneratedExtension(ExtensionDescriptorRetriever descriptorRetriever,
          Class singularType,
          Message messageDefaultInstance,
          ExtensionType extensionType) {
        if (Message.class.isAssignableFrom(singularType) &&
            !singularType.isInstance(messageDefaultInstance)) {
          throw new IllegalArgumentException(
              "Bad messageDefaultInstance for " + singularType.getName());
        }
        this.descriptorRetriever = descriptorRetriever;
        this.singularType = singularType;
        this.messageDefaultInstance = messageDefaultInstance;
  
        if (ProtocolMessageEnum.class.isAssignableFrom(singularType)) {
          this.enumValueOf = getMethodOrDie(singularType, "valueOf",
                                            EnumValueDescriptor.class);
          this.enumGetValueDescriptor =
              getMethodOrDie(singularType, "getValueDescriptor");
        } else {
          this.enumValueOf = null;
          this.enumGetValueDescriptor = null;
        }
        this.extensionType = extensionType;
      }
  
      /** For use by generated code only. */
      public void internalInit(final FieldDescriptor descriptor) {
        if (descriptorRetriever != null) {
          throw new IllegalStateException("Already initialized.");
        }
        descriptorRetriever =
            new ExtensionDescriptorRetriever() {
              @Override
              public FieldDescriptor getDescriptor() {
                return descriptor;
              }
            };
      }
  
      private ExtensionDescriptorRetriever descriptorRetriever;
      private final Class singularType;
      private final Message messageDefaultInstance;
      private final Method enumValueOf;
      private final Method enumGetValueDescriptor;
      private final ExtensionType extensionType;
  
      @Override
      public FieldDescriptor getDescriptor() {
        if (descriptorRetriever == null) {
          throw new IllegalStateException(
              "getDescriptor() called before internalInit()");
        }
        return descriptorRetriever.getDescriptor();
      }
  
      /**
       * If the extension is an embedded message or group, returns the default
       * instance of the message.
       */
      @Override
      public Message getMessageDefaultInstance() {
        return messageDefaultInstance;
      }
  
      @Override
      protected ExtensionType getExtensionType() {
        return extensionType;
      }
  
      /**
       * Convert from the type used by the reflection accessors to the type used
       * by native accessors.  E.g., for enums, the reflection accessors use
       * EnumValueDescriptors but the native accessors use the generated enum
       * type.
       */
      @Override
      @SuppressWarnings("unchecked")
      protected Object fromReflectionType(final Object value) {
        FieldDescriptor descriptor = getDescriptor();
        if (descriptor.isRepeated()) {
          if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE ||
              descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
            // Must convert the whole list.
            final List result = new ArrayList();
            for (final Object element : (List) value) {
              result.add(singularFromReflectionType(element));
            }
            return result;
          } else {
            return value;
          }
        } else {
          return singularFromReflectionType(value);
        }
      }
  
      /**
       * Like {@link #fromReflectionType(Object)}, but if the type is a repeated
       * type, this converts a single element.
       */
      @Override
      protected Object singularFromReflectionType(final Object value) {
        FieldDescriptor descriptor = getDescriptor();
        switch (descriptor.getJavaType()) {
          case MESSAGE:
            if (singularType.isInstance(value)) {
              return value;
            } else {
              return messageDefaultInstance.newBuilderForType()
                  .mergeFrom((Message) value).build();
            }
          case ENUM:
            return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value);
          default:
            return value;
        }
      }
  
      /**
       * Convert from the type used by the native accessors to the type used
       * by reflection accessors.  E.g., for enums, the reflection accessors use
       * EnumValueDescriptors but the native accessors use the generated enum
       * type.
       */
      @Override
      @SuppressWarnings("unchecked")
      protected Object toReflectionType(final Object value) {
        FieldDescriptor descriptor = getDescriptor();
        if (descriptor.isRepeated()) {
          if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
            // Must convert the whole list.
            final List result = new ArrayList();
            for (final Object element : (List) value) {
              result.add(singularToReflectionType(element));
            }
            return result;
          } else {
            return value;
          }
        } else {
          return singularToReflectionType(value);
        }
      }
  
      /**
       * Like {@link #toReflectionType(Object)}, but if the type is a repeated
       * type, this converts a single element.
       */
      @Override
      protected Object singularToReflectionType(final Object value) {
        FieldDescriptor descriptor = getDescriptor();
        switch (descriptor.getJavaType()) {
          case ENUM:
            return invokeOrDie(enumGetValueDescriptor, value);
          default:
            return value;
        }
      }
  
      @Override
      public int getNumber() {
        return getDescriptor().getNumber();
      }
  
      @Override
      public WireFormat.FieldType getLiteType() {
        return getDescriptor().getLiteType();
      }
  
      @Override
      public boolean isRepeated() {
        return getDescriptor().isRepeated();
      }
  
      @Override
      @SuppressWarnings("unchecked")
      public Type getDefaultValue() {
        if (isRepeated()) {
          return (Type) Collections.emptyList();
        }
        if (getDescriptor().getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
          return (Type) messageDefaultInstance;
        }
        return (Type) singularFromReflectionType(
            getDescriptor().getDefaultValue());
      }
    }
  
    // =================================================================
  
    /** Calls Class.getMethod and throws a RuntimeException if it fails. */
    @SuppressWarnings("unchecked")
    private static Method getMethodOrDie(
        final Class clazz, final String name, final Class... params) {
      try {
        return clazz.getMethod(name, params);
      } catch (NoSuchMethodException e) {
        throw new RuntimeException(
          "Generated message class \"" + clazz.getName() +
          "\" missing method \"" + name + "\".", e);
      }
    }
  
    /** Calls invoke and throws a RuntimeException if it fails. */
    private static Object invokeOrDie(
        final Method method, final Object object, final Object... params) {
      try {
        return method.invoke(object, params);
      } catch (IllegalAccessException e) {
        throw new RuntimeException(
          "Couldn't use Java reflection to implement protocol message " +
          "reflection.", e);
      } catch (InvocationTargetException e) {
        final Throwable cause = e.getCause();
        if (cause instanceof RuntimeException) {
          throw (RuntimeException) cause;
        } else if (cause instanceof Error) {
          throw (Error) cause;
        } else {
          throw new RuntimeException(
            "Unexpected exception thrown by generated accessor method.", cause);
        }
      }
    }
  
    /**
     * Gets the map field with the given field number. This method should be
     * overridden in the generated message class if the message contains map
     * fields.
     *
     * Unlike other field types, reflection support for map fields can't be
     * implemented based on generated public API because we need to access a
     * map field as a list in reflection API but the generated API only allows
     * us to access it as a map. This method returns the underlying map field
     * directly and thus enables us to access the map field as a list.
     */
    @SuppressWarnings({"rawtypes", "unused"})
    protected MapField internalGetMapField(int fieldNumber) {
      // Note that we can't use descriptor names here because this method will
      // be called when descriptor is being initialized.
      throw new RuntimeException(
          "No map fields found in " + getClass().getName());
    }
  
    /**
     * Users should ignore this class.  This class provides the implementation
     * with access to the fields of a message object using Java reflection.
     */
    public static final class FieldAccessorTable {
  
      /**
       * Construct a FieldAccessorTable for a particular message class.  Only
       * one FieldAccessorTable should ever be constructed per class.
       *
       * @param descriptor     The type's descriptor.
       * @param camelCaseNames The camelcase names of all fields in the message.
       *                       These are used to derive the accessor method names.
       * @param messageClass   The message type.
       * @param builderClass   The builder type.
       */
      public FieldAccessorTable(
          final Descriptor descriptor,
          final String[] camelCaseNames,
          final Class<? extends GeneratedMessage> messageClass,
          final Class<? extends Builder> builderClass) {
        this(descriptor, camelCaseNames);
        ensureFieldAccessorsInitialized(messageClass, builderClass);
      }
  
      /**
       * Construct a FieldAccessorTable for a particular message class without
       * initializing FieldAccessors.
       */
      public FieldAccessorTable(
          final Descriptor descriptor,
          final String[] camelCaseNames) {
        this.descriptor = descriptor;
        this.camelCaseNames = camelCaseNames;
        fields = new FieldAccessor[descriptor.getFields().size()];
        oneofs = new OneofAccessor[descriptor.getOneofs().size()];
        initialized = false;
      }
  
      private boolean isMapFieldEnabled(FieldDescriptor field) {
        boolean result = true;
        return result;
      }
  
      /**
       * Ensures the field accessors are initialized. This method is thread-safe.
       *
       * @param messageClass   The message type.
       * @param builderClass   The builder type.
       * @return this
       */
      public FieldAccessorTable ensureFieldAccessorsInitialized(
          Class<? extends GeneratedMessage> messageClass,
          Class<? extends Builder> builderClass) {
        if (initialized) { return this; }
        synchronized (this) {
          if (initialized) { return this; }
          int fieldsSize = fields.length;
          for (int i = 0; i < fieldsSize; i++) {
            FieldDescriptor field = descriptor.getFields().get(i);
            String containingOneofCamelCaseName = null;
            if (field.getContainingOneof() != null) {
              containingOneofCamelCaseName =
                  camelCaseNames[fieldsSize + field.getContainingOneof().getIndex()];
            }
            if (field.isRepeated()) {
              if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
                if (field.isMapField() && isMapFieldEnabled(field)) {
                  fields[i] = new MapFieldAccessor(
                      field, camelCaseNames[i], messageClass, builderClass);
                } else {
                  fields[i] = new RepeatedMessageFieldAccessor(
                      field, camelCaseNames[i], messageClass, builderClass);
                }
              } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
                fields[i] = new RepeatedEnumFieldAccessor(
                    field, camelCaseNames[i], messageClass, builderClass);
              } else {
                fields[i] = new RepeatedFieldAccessor(
                    field, camelCaseNames[i], messageClass, builderClass);
              }
            } else {
              if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
                fields[i] = new SingularMessageFieldAccessor(
                    field, camelCaseNames[i], messageClass, builderClass,
                    containingOneofCamelCaseName);
              } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
                fields[i] = new SingularEnumFieldAccessor(
                    field, camelCaseNames[i], messageClass, builderClass,
                    containingOneofCamelCaseName);
              } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) {
                fields[i] = new SingularStringFieldAccessor(
                    field, camelCaseNames[i], messageClass, builderClass,
                    containingOneofCamelCaseName);
              } else {
                fields[i] = new SingularFieldAccessor(
                    field, camelCaseNames[i], messageClass, builderClass,
                    containingOneofCamelCaseName);
              }
            }
          }
  
          int oneofsSize = oneofs.length;
          for (int i = 0; i < oneofsSize; i++) {
            oneofs[i] = new OneofAccessor(
                descriptor, camelCaseNames[i + fieldsSize],
                messageClass, builderClass);
          }
          initialized = true;
          camelCaseNames = null;
          return this;
        }
      }
  
      private final Descriptor descriptor;
      private final FieldAccessor[] fields;
      private String[] camelCaseNames;
      private final OneofAccessor[] oneofs;
      private volatile boolean initialized;
  
      /** Get the FieldAccessor for a particular field. */
      private FieldAccessor getField(final FieldDescriptor field) {
        if (field.getContainingType() != descriptor) {
          throw new IllegalArgumentException(
            "FieldDescriptor does not match message type.");
        } else if (field.isExtension()) {
          // If this type had extensions, it would subclass ExtendableMessage,
          // which overrides the reflection interface to handle extensions.
          throw new IllegalArgumentException(
            "This type does not have extensions.");
        }
        return fields[field.getIndex()];
      }
  
      /** Get the OneofAccessor for a particular oneof. */
      private OneofAccessor getOneof(final OneofDescriptor oneof) {
        if (oneof.getContainingType() != descriptor) {
          throw new IllegalArgumentException(
            "OneofDescriptor does not match message type.");
        }
        return oneofs[oneof.getIndex()];
      }
  
      /**
       * Abstract interface that provides access to a single field.  This is
       * implemented differently depending on the field type and cardinality.
       */
      private interface FieldAccessor {
        Object get(GeneratedMessage message);
        Object get(GeneratedMessage.Builder builder);
        Object getRaw(GeneratedMessage message);
        Object getRaw(GeneratedMessage.Builder builder);
        void set(Builder builder, Object value);
        Object getRepeated(GeneratedMessage message, int index);
        Object getRepeated(GeneratedMessage.Builder builder, int index);
        Object getRepeatedRaw(GeneratedMessage message, int index);
        Object getRepeatedRaw(GeneratedMessage.Builder builder, int index);
        void setRepeated(Builder builder,
                         int index, Object value);
        void addRepeated(Builder builder, Object value);
        boolean has(GeneratedMessage message);
        boolean has(GeneratedMessage.Builder builder);
        int getRepeatedCount(GeneratedMessage message);
        int getRepeatedCount(GeneratedMessage.Builder builder);
        void clear(Builder builder);
        Message.Builder newBuilder();
        Message.Builder getBuilder(GeneratedMessage.Builder builder);
        Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder,
                                           int index);
      }
  
      /** OneofAccessor provides access to a single oneof. */
      private static class OneofAccessor {
        OneofAccessor(
            final Descriptor descriptor, final String camelCaseName,
            final Class<? extends GeneratedMessage> messageClass,
            final Class<? extends Builder> builderClass) {
          this.descriptor = descriptor;
          caseMethod =
              getMethodOrDie(messageClass, "get" + camelCaseName + "Case");
          caseMethodBuilder =
              getMethodOrDie(builderClass, "get" + camelCaseName + "Case");
          clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
        }
  
        private final Descriptor descriptor;
        private final Method caseMethod;
        private final Method caseMethodBuilder;
        private final Method clearMethod;
  
        public boolean has(final GeneratedMessage message) {
          if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) {
            return false;
          }
          return true;
        }
  
        public boolean has(GeneratedMessage.Builder builder) {
          if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) {
            return false;
          }
          return true;
        }
  
        public FieldDescriptor get(final GeneratedMessage message) {
          int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
          if (fieldNumber > 0) {
            return descriptor.findFieldByNumber(fieldNumber);
          }
          return null;
        }
  
        public FieldDescriptor get(GeneratedMessage.Builder builder) {
          int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
          if (fieldNumber > 0) {
            return descriptor.findFieldByNumber(fieldNumber);
          }
          return null;
        }
  
        public void clear(final Builder builder) {
          invokeOrDie(clearMethod, builder);
        }
      }
  
      private static boolean supportFieldPresence(FileDescriptor file) {
        return file.getSyntax() == FileDescriptor.Syntax.PROTO2;
      }
  
      // ---------------------------------------------------------------
  
      private static class SingularFieldAccessor implements FieldAccessor {
        SingularFieldAccessor(
            final FieldDescriptor descriptor, final String camelCaseName,
            final Class<? extends GeneratedMessage> messageClass,
            final Class<? extends Builder> builderClass,
            final String containingOneofCamelCaseName) {
          field = descriptor;
          isOneofField = descriptor.getContainingOneof() != null;
          hasHasMethod = supportFieldPresence(descriptor.getFile())
              || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE);
          getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
          getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName);
          type = getMethod.getReturnType();
          setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
          hasMethod =
              hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null;
          hasMethodBuilder =
              hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null;
          clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
          caseMethod = isOneofField ? getMethodOrDie(
              messageClass, "get" + containingOneofCamelCaseName + "Case") : null;
          caseMethodBuilder = isOneofField ? getMethodOrDie(
              builderClass, "get" + containingOneofCamelCaseName + "Case") : null;
        }
  
        // Note:  We use Java reflection to call public methods rather than
        //   access private fields directly as this avoids runtime security
        //   checks.
        protected final Class<?> type;
        protected final Method getMethod;
        protected final Method getMethodBuilder;
        protected final Method setMethod;
        protected final Method hasMethod;
        protected final Method hasMethodBuilder;
        protected final Method clearMethod;
        protected final Method caseMethod;
        protected final Method caseMethodBuilder;
        protected final FieldDescriptor field;
        protected final boolean isOneofField;
        protected final boolean hasHasMethod;
  
        private int getOneofFieldNumber(final GeneratedMessage message) {
          return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
        }
  
        private int getOneofFieldNumber(final GeneratedMessage.Builder builder) {
          return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
        }
  
        @Override
        public Object get(final GeneratedMessage message) {
          return invokeOrDie(getMethod, message);
        }
        @Override
        public Object get(GeneratedMessage.Builder builder) {
          return invokeOrDie(getMethodBuilder, builder);
        }
        @Override
        public Object getRaw(final GeneratedMessage message) {
          return get(message);
        }
        @Override
        public Object getRaw(GeneratedMessage.Builder builder) {
          return get(builder);
        }
        @Override
        public void set(final Builder builder, final Object value) {
          invokeOrDie(setMethod, builder, value);
        }
        @Override
        public Object getRepeated(final GeneratedMessage message, final int index) {
          throw new UnsupportedOperationException(
            "getRepeatedField() called on a singular field.");
        }
        @Override
        public Object getRepeatedRaw(final GeneratedMessage message, final int index) {
          throw new UnsupportedOperationException(
            "getRepeatedFieldRaw() called on a singular field.");
        }
        @Override
        public Object getRepeated(GeneratedMessage.Builder builder, int index) {
          throw new UnsupportedOperationException(
            "getRepeatedField() called on a singular field.");
        }
        @Override
        public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) {
          throw new UnsupportedOperationException(
            "getRepeatedFieldRaw() called on a singular field.");
        }
        @Override
        public void setRepeated(final Builder builder, final int index, final Object value) {
          throw new UnsupportedOperationException(
            "setRepeatedField() called on a singular field.");
        }
        @Override
        public void addRepeated(final Builder builder, final Object value) {
          throw new UnsupportedOperationException(
            "addRepeatedField() called on a singular field.");
        }
        @Override
        public boolean has(final GeneratedMessage message) {
          if (!hasHasMethod) {
            if (isOneofField) {
              return getOneofFieldNumber(message) == field.getNumber();
            }
            return !get(message).equals(field.getDefaultValue());
          }
          return (Boolean) invokeOrDie(hasMethod, message);
        }
        @Override
        public boolean has(GeneratedMessage.Builder builder) {
          if (!hasHasMethod) {
            if (isOneofField) {
              return getOneofFieldNumber(builder) == field.getNumber();
            }
            return !get(builder).equals(field.getDefaultValue());
          }
          return (Boolean) invokeOrDie(hasMethodBuilder, builder);
        }
        @Override
        public int getRepeatedCount(final GeneratedMessage message) {
          throw new UnsupportedOperationException(
            "getRepeatedFieldSize() called on a singular field.");
        }
        @Override
        public int getRepeatedCount(GeneratedMessage.Builder builder) {
          throw new UnsupportedOperationException(
            "getRepeatedFieldSize() called on a singular field.");
        }
        @Override
        public void clear(final Builder builder) {
          invokeOrDie(clearMethod, builder);
        }
        @Override
        public Message.Builder newBuilder() {
          throw new UnsupportedOperationException(
            "newBuilderForField() called on a non-Message type.");
        }
        @Override
        public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
          throw new UnsupportedOperationException(
            "getFieldBuilder() called on a non-Message type.");
        }
        @Override
        public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) {
          throw new UnsupportedOperationException(
            "getRepeatedFieldBuilder() called on a non-Message type.");
        }
      }
  
      private static class RepeatedFieldAccessor implements FieldAccessor {
        protected final Class type;
        protected final Method getMethod;
        protected final Method getMethodBuilder;
        protected final Method getRepeatedMethod;
        protected final Method getRepeatedMethodBuilder;
        protected final Method setRepeatedMethod;
        protected final Method addRepeatedMethod;
        protected final Method getCountMethod;
        protected final Method getCountMethodBuilder;
        protected final Method clearMethod;
  
        RepeatedFieldAccessor(
            final FieldDescriptor descriptor, final String camelCaseName,
            final Class<? extends GeneratedMessage> messageClass,
            final Class<? extends Builder> builderClass) {
          getMethod = getMethodOrDie(messageClass,
                                     "get" + camelCaseName + "List");
          getMethodBuilder = getMethodOrDie(builderClass,
                                     "get" + camelCaseName + "List");
          getRepeatedMethod =
              getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
          getRepeatedMethodBuilder =
              getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE);
          type = getRepeatedMethod.getReturnType();
          setRepeatedMethod =
              getMethodOrDie(builderClass, "set" + camelCaseName,
                             Integer.TYPE, type);
          addRepeatedMethod =
              getMethodOrDie(builderClass, "add" + camelCaseName, type);
          getCountMethod =
              getMethodOrDie(messageClass, "get" + camelCaseName + "Count");
          getCountMethodBuilder =
              getMethodOrDie(builderClass, "get" + camelCaseName + "Count");
  
          clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
        }
  
        @Override
        public Object get(final GeneratedMessage message) {
          return invokeOrDie(getMethod, message);
        }
        @Override
        public Object get(GeneratedMessage.Builder builder) {
          return invokeOrDie(getMethodBuilder, builder);
        }
        @Override
        public Object getRaw(final GeneratedMessage message) {
          return get(message);
        }
        @Override
        public Object getRaw(GeneratedMessage.Builder builder) {
          return get(builder);
        }
        @Override
        public void set(final Builder builder, final Object value) {
          // Add all the elements individually.  This serves two purposes:
          // 1) Verifies that each element has the correct type.
          // 2) Insures that the caller cannot modify the list later on and
          //    have the modifications be reflected in the message.
          clear(builder);
          for (final Object element : (List<?>) value) {
            addRepeated(builder, element);
          }
        }
        @Override
        public Object getRepeated(final GeneratedMessage message, final int index) {
          return invokeOrDie(getRepeatedMethod, message, index);
        }
        @Override
        public Object getRepeated(GeneratedMessage.Builder builder, int index) {
          return invokeOrDie(getRepeatedMethodBuilder, builder, index);
        }
        @Override
        public Object getRepeatedRaw(GeneratedMessage message, int index) {
          return getRepeated(message, index);
        }
        @Override
        public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) {
          return getRepeated(builder, index);
        }
        @Override
        public void setRepeated(final Builder builder, final int index, final Object value) {
          invokeOrDie(setRepeatedMethod, builder, index, value);
        }
        @Override
        public void addRepeated(final Builder builder, final Object value) {
          invokeOrDie(addRepeatedMethod, builder, value);
        }
        @Override
        public boolean has(final GeneratedMessage message) {
          throw new UnsupportedOperationException(
            "hasField() called on a repeated field.");
        }
        @Override
        public boolean has(GeneratedMessage.Builder builder) {
          throw new UnsupportedOperationException(
            "hasField() called on a repeated field.");
        }
        @Override
        public int getRepeatedCount(final GeneratedMessage message) {
          return (Integer) invokeOrDie(getCountMethod, message);
        }
        @Override
        public int getRepeatedCount(GeneratedMessage.Builder builder) {
          return (Integer) invokeOrDie(getCountMethodBuilder, builder);
        }
        @Override
        public void clear(final Builder builder) {
          invokeOrDie(clearMethod, builder);
        }
        @Override
        public Message.Builder newBuilder() {
          throw new UnsupportedOperationException(
            "newBuilderForField() called on a non-Message type.");
        }
        @Override
        public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
          throw new UnsupportedOperationException(
            "getFieldBuilder() called on a non-Message type.");
        }
        @Override
        public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) {
          throw new UnsupportedOperationException(
            "getRepeatedFieldBuilder() called on a non-Message type.");
        }
      }
  
      private static class MapFieldAccessor implements FieldAccessor {
        MapFieldAccessor(
            final FieldDescriptor descriptor, final String camelCaseName,
            final Class<? extends GeneratedMessage> messageClass,
            final Class<? extends Builder> builderClass) {
          field = descriptor;
          Method getDefaultInstanceMethod =
              getMethodOrDie(messageClass, "getDefaultInstance");
          MapField defaultMapField = getMapField(
              (GeneratedMessage) invokeOrDie(getDefaultInstanceMethod, null));
          mapEntryMessageDefaultInstance =
              defaultMapField.getMapEntryMessageDefaultInstance();
        }
  
        private final FieldDescriptor field;
        private final Message mapEntryMessageDefaultInstance;
  
        private MapField<?, ?> getMapField(GeneratedMessage message) {
          return (MapField<?, ?>) message.internalGetMapField(field.getNumber());
        }
  
        private MapField<?, ?> getMapField(GeneratedMessage.Builder builder) {
          return (MapField<?, ?>) builder.internalGetMapField(field.getNumber());
        }
  
        private MapField<?, ?> getMutableMapField(
            GeneratedMessage.Builder builder) {
          return (MapField<?, ?>) builder.internalGetMutableMapField(
              field.getNumber());
        }
  
        @Override
        @SuppressWarnings("unchecked")
        public Object get(GeneratedMessage message) {
          List result = new ArrayList();
          for (int i = 0; i < getRepeatedCount(message); i++) {
            result.add(getRepeated(message, i));
          }
          return Collections.unmodifiableList(result);
        }
  
        @Override
        @SuppressWarnings("unchecked")
        public Object get(Builder builder) {
          List result = new ArrayList();
          for (int i = 0; i < getRepeatedCount(builder); i++) {
            result.add(getRepeated(builder, i));
          }
          return Collections.unmodifiableList(result);
        }
  
        @Override
        public Object getRaw(GeneratedMessage message) {
          return get(message);
        }
  
        @Override
        public Object getRaw(GeneratedMessage.Builder builder) {
          return get(builder);
        }
  
        @Override
        public void set(Builder builder, Object value) {
          clear(builder);
          for (Object entry : (List) value) {
            addRepeated(builder, entry);
          }
        }
  
        @Override
        public Object getRepeated(GeneratedMessage message, int index) {
          return getMapField(message).getList().get(index);
        }
  
        @Override
        public Object getRepeated(Builder builder, int index) {
          return getMapField(builder).getList().get(index);
        }
  
        @Override
        public Object getRepeatedRaw(GeneratedMessage message, int index) {
          return getRepeated(message, index);
        }
  
        @Override
        public Object getRepeatedRaw(Builder builder, int index) {
          return getRepeated(builder, index);
        }
  
        @Override
        public void setRepeated(Builder builder, int index, Object value) {
          getMutableMapField(builder).getMutableList().set(index, (Message) value);
        }
  
        @Override
        public void addRepeated(Builder builder, Object value) {
          getMutableMapField(builder).getMutableList().add((Message) value);
        }
  
        @Override
        public boolean has(GeneratedMessage message) {
          throw new UnsupportedOperationException(
              "hasField() is not supported for repeated fields.");
        }
  
        @Override
        public boolean has(Builder builder) {
          throw new UnsupportedOperationException(
              "hasField() is not supported for repeated fields.");
        }
  
        @Override
        public int getRepeatedCount(GeneratedMessage message) {
          return getMapField(message).getList().size();
        }
  
        @Override
        public int getRepeatedCount(Builder builder) {
          return getMapField(builder).getList().size();
        }
  
        @Override
        public void clear(Builder builder) {
          getMutableMapField(builder).getMutableList().clear();
        }
  
        @Override
        public com.google.protobuf.Message.Builder newBuilder() {
          return mapEntryMessageDefaultInstance.newBuilderForType();
        }
  
        @Override
        public com.google.protobuf.Message.Builder getBuilder(Builder builder) {
          throw new UnsupportedOperationException(
              "Nested builder not supported for map fields.");
        }
  
        @Override
        public com.google.protobuf.Message.Builder getRepeatedBuilder(Builder builder, int index) {
          throw new UnsupportedOperationException(
              "Nested builder not supported for map fields.");
        }
      }
  
      // ---------------------------------------------------------------
  
      private static final class SingularEnumFieldAccessor
          extends SingularFieldAccessor {
        SingularEnumFieldAccessor(
            final FieldDescriptor descriptor, final String camelCaseName,
            final Class<? extends GeneratedMessage> messageClass,
            final Class<? extends Builder> builderClass,
            final String containingOneofCamelCaseName) {
          super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
  
          enumDescriptor = descriptor.getEnumType();
  
          valueOfMethod = getMethodOrDie(type, "valueOf",
                                         EnumValueDescriptor.class);
          getValueDescriptorMethod =
            getMethodOrDie(type, "getValueDescriptor");
  
          supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
          if (supportUnknownEnumValue) {
            getValueMethod =
                getMethodOrDie(messageClass, "get" + camelCaseName + "Value");
            getValueMethodBuilder =
                getMethodOrDie(builderClass, "get" + camelCaseName + "Value");
            setValueMethod =
                getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
          }
        }
  
        private EnumDescriptor enumDescriptor;
  
        private Method valueOfMethod;
        private Method getValueDescriptorMethod;
  
        private boolean supportUnknownEnumValue;
        private Method getValueMethod;
        private Method getValueMethodBuilder;
        private Method setValueMethod;
  
        @Override
        public Object get(final GeneratedMessage message) {
          if (supportUnknownEnumValue) {
            int value = (Integer) invokeOrDie(getValueMethod, message);
            return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
          }
          return invokeOrDie(getValueDescriptorMethod, super.get(message));
        }
  
        @Override
        public Object get(final GeneratedMessage.Builder builder) {
          if (supportUnknownEnumValue) {
            int value = (Integer) invokeOrDie(getValueMethodBuilder, builder);
            return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
          }
          return invokeOrDie(getValueDescriptorMethod, super.get(builder));
        }
  
        @Override
        public void set(final Builder builder, final Object value) {
          if (supportUnknownEnumValue) {
            invokeOrDie(setValueMethod, builder,
                ((EnumValueDescriptor) value).getNumber());
            return;
          }
          super.set(builder, invokeOrDie(valueOfMethod, null, value));
        }
      }
  
      private static final class RepeatedEnumFieldAccessor
          extends RepeatedFieldAccessor {
        RepeatedEnumFieldAccessor(
            final FieldDescriptor descriptor, final String camelCaseName,
            final Class<? extends GeneratedMessage> messageClass,
            final Class<? extends Builder> builderClass) {
          super(descriptor, camelCaseName, messageClass, builderClass);
  
          enumDescriptor = descriptor.getEnumType();
  
          valueOfMethod = getMethodOrDie(type, "valueOf",
                                         EnumValueDescriptor.class);
          getValueDescriptorMethod =
            getMethodOrDie(type, "getValueDescriptor");
  
          supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
          if (supportUnknownEnumValue) {
            getRepeatedValueMethod =
                getMethodOrDie(messageClass, "get" + camelCaseName + "Value", int.class);
            getRepeatedValueMethodBuilder =
                getMethodOrDie(builderClass, "get" + camelCaseName + "Value", int.class);
            setRepeatedValueMethod =
                getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class, int.class);
            addRepeatedValueMethod =
                getMethodOrDie(builderClass, "add" + camelCaseName + "Value", int.class);
          }
        }
        private EnumDescriptor enumDescriptor;
  
        private final Method valueOfMethod;
        private final Method getValueDescriptorMethod;
  
        private boolean supportUnknownEnumValue;
        private Method getRepeatedValueMethod;
        private Method getRepeatedValueMethodBuilder;
        private Method setRepeatedValueMethod;
        private Method addRepeatedValueMethod;
  
        @Override
        @SuppressWarnings("unchecked")
        public Object get(final GeneratedMessage message) {
          final List newList = new ArrayList();
          final int size = getRepeatedCount(message);
          for (int i = 0; i < size; i++) {
            newList.add(getRepeated(message, i));
          }
          return Collections.unmodifiableList(newList);
        }
  
        @Override
        @SuppressWarnings("unchecked")
        public Object get(final GeneratedMessage.Builder builder) {
          final List newList = new ArrayList();
          final int size = getRepeatedCount(builder);
          for (int i = 0; i < size; i++) {
            newList.add(getRepeated(builder, i));
          }
          return Collections.unmodifiableList(newList);
        }
  
        @Override
        public Object getRepeated(final GeneratedMessage message,
                                  final int index) {
          if (supportUnknownEnumValue) {
            int value = (Integer) invokeOrDie(getRepeatedValueMethod, message, index);
            return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
          }
          return invokeOrDie(getValueDescriptorMethod,
            super.getRepeated(message, index));
        }
        @Override
        public Object getRepeated(final GeneratedMessage.Builder builder,
                                  final int index) {
          if (supportUnknownEnumValue) {
            int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index);
            return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
          }
          return invokeOrDie(getValueDescriptorMethod,
            super.getRepeated(builder, index));
        }
        @Override
        public void setRepeated(final Builder builder,
                                final int index, final Object value) {
          if (supportUnknownEnumValue) {
            invokeOrDie(setRepeatedValueMethod, builder, index,
                ((EnumValueDescriptor) value).getNumber());
            return;
          }
          super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null,
                            value));
        }
        @Override
        public void addRepeated(final Builder builder, final Object value) {
          if (supportUnknownEnumValue) {
            invokeOrDie(addRepeatedValueMethod, builder,
                ((EnumValueDescriptor) value).getNumber());
            return;
          }
          super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value));
        }
      }
  
      // ---------------------------------------------------------------
  
      /**
       * Field accessor for string fields.
       *
       * <p>This class makes getFooBytes() and setFooBytes() available for
       * reflection API so that reflection based serialize/parse functions can
       * access the raw bytes of the field to preserve non-UTF8 bytes in the
       * string.
       *
       * <p>This ensures the serialize/parse round-trip safety, which is important
       * for servers which forward messages.
       */
      private static final class SingularStringFieldAccessor
          extends SingularFieldAccessor {
        SingularStringFieldAccessor(
            final FieldDescriptor descriptor, final String camelCaseName,
            final Class<? extends GeneratedMessage> messageClass,
            final Class<? extends Builder> builderClass,
            final String containingOneofCamelCaseName) {
          super(descriptor, camelCaseName, messageClass, builderClass,
              containingOneofCamelCaseName);
          getBytesMethod = getMethodOrDie(messageClass,
              "get" + camelCaseName + "Bytes");
          getBytesMethodBuilder = getMethodOrDie(builderClass,
              "get" + camelCaseName + "Bytes");
          setBytesMethodBuilder = getMethodOrDie(builderClass,
              "set" + camelCaseName + "Bytes", ByteString.class);
        }
  
        private final Method getBytesMethod;
        private final Method getBytesMethodBuilder;
        private final Method setBytesMethodBuilder;
  
        @Override
        public Object getRaw(final GeneratedMessage message) {
          return invokeOrDie(getBytesMethod, message);
        }
  
        @Override
        public Object getRaw(GeneratedMessage.Builder builder) {
          return invokeOrDie(getBytesMethodBuilder, builder);
        }
  
        @Override
        public void set(GeneratedMessage.Builder builder, Object value) {
          if (value instanceof ByteString) {
            invokeOrDie(setBytesMethodBuilder, builder, value);
          } else {
            super.set(builder, value);
          }
        }
      }
  
      // ---------------------------------------------------------------
  
      private static final class SingularMessageFieldAccessor
          extends SingularFieldAccessor {
        SingularMessageFieldAccessor(
            final FieldDescriptor descriptor, final String camelCaseName,
            final Class<? extends GeneratedMessage> messageClass,
            final Class<? extends Builder> builderClass,
            final String containingOneofCamelCaseName) {
          super(descriptor, camelCaseName, messageClass, builderClass,
              containingOneofCamelCaseName);
  
          newBuilderMethod = getMethodOrDie(type, "newBuilder");
          getBuilderMethodBuilder =
              getMethodOrDie(builderClass, "get" + camelCaseName + "Builder");
        }
  
        private final Method newBuilderMethod;
        private final Method getBuilderMethodBuilder;
  
        private Object coerceType(final Object value) {
          if (type.isInstance(value)) {
            return value;
          } else {
            // The value is not the exact right message type.  However, if it
            // is an alternative implementation of the same type -- e.g. a
            // DynamicMessage -- we should accept it.  In this case we can make
            // a copy of the message.
            return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
                    .mergeFrom((Message) value).buildPartial();
          }
        }
  
        @Override
        public void set(final Builder builder, final Object value) {
          super.set(builder, coerceType(value));
        }
        @Override
        public Message.Builder newBuilder() {
          return (Message.Builder) invokeOrDie(newBuilderMethod, null);
        }
        @Override
        public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
          return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder);
        }
      }
  
      private static final class RepeatedMessageFieldAccessor
          extends RepeatedFieldAccessor {
        RepeatedMessageFieldAccessor(
            final FieldDescriptor descriptor, final String camelCaseName,
            final Class<? extends GeneratedMessage> messageClass,
            final Class<? extends Builder> builderClass) {
          super(descriptor, camelCaseName, messageClass, builderClass);
  
          newBuilderMethod = getMethodOrDie(type, "newBuilder");
          getBuilderMethodBuilder = getMethodOrDie(builderClass,
              "get" + camelCaseName + "Builder", Integer.TYPE);
        }
  
        private final Method newBuilderMethod;
        private final Method getBuilderMethodBuilder;
  
        private Object coerceType(final Object value) {
          if (type.isInstance(value)) {
            return value;
          } else {
            // The value is not the exact right message type.  However, if it
            // is an alternative implementation of the same type -- e.g. a
            // DynamicMessage -- we should accept it.  In this case we can make
            // a copy of the message.
            return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
                    .mergeFrom((Message) value).build();
          }
        }
  
        @Override
        public void setRepeated(final Builder builder,
                                final int index, final Object value) {
          super.setRepeated(builder, index, coerceType(value));
        }
        @Override
        public void addRepeated(final Builder builder, final Object value) {
          super.addRepeated(builder, coerceType(value));
        }
        @Override
        public Message.Builder newBuilder() {
          return (Message.Builder) invokeOrDie(newBuilderMethod, null);
        }
        @Override
        public Message.Builder getRepeatedBuilder(
            final GeneratedMessage.Builder builder, final int index) {
          return (Message.Builder) invokeOrDie(
              getBuilderMethodBuilder, builder, index);
        }
      }
    }
  
    /**
     * Replaces this object in the output stream with a serialized form.
     * Part of Java's serialization magic.  Generated sub-classes must override
     * this method by calling {@code return super.writeReplace();}
     * @return a SerializedForm of this message
     */
    protected Object writeReplace() throws ObjectStreamException {
      return new GeneratedMessageLite.SerializedForm(this);
    }
  
    /**
     * Checks that the {@link Extension} is non-Lite and returns it as a
     * {@link GeneratedExtension}.
     */
    private static <MessageType extends ExtendableMessage<MessageType>, T>
      Extension<MessageType, T> checkNotLite(
          ExtensionLite<MessageType, T> extension) {
      if (extension.isLite()) {
        throw new IllegalArgumentException("Expected non-lite extension.");
      }
  
      return (Extension<MessageType, T>) extension;
    }
    
    protected static int computeStringSize(final int fieldNumber, final Object value) {
      if (value instanceof String) {
        return CodedOutputStream.computeStringSize(fieldNumber, (String) value);
      } else {
        return CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) value);
      }
    }
    
    protected static int computeStringSizeNoTag(final Object value) {
      if (value instanceof String) {
        return CodedOutputStream.computeStringSizeNoTag((String) value);
      } else {
        return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
      }
    }
    
    protected static void writeString(
        CodedOutputStream output, final int fieldNumber, final Object value) throws IOException {
      if (value instanceof String) {
        output.writeString(fieldNumber, (String) value);
      } else {
        output.writeBytes(fieldNumber, (ByteString) value);
      }
    }
    
    protected static void writeStringNoTag(
        CodedOutputStream output, final Object value) throws IOException {
      if (value instanceof String) {
        output.writeStringNoTag((String) value);
      } else {
        output.writeBytesNoTag((ByteString) value);
      }
    }
  }
  