// 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 static com.google.protobuf.Internal.checkNotNull;

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 com.google.protobuf.Internal.BooleanList;
import com.google.protobuf.Internal.DoubleList;
import com.google.protobuf.Internal.FloatList;
import com.google.protobuf.Internal.IntList;
import com.google.protobuf.Internal.LongList;
// In opensource protobuf, we have versioned this GeneratedMessageV3 class to GeneratedMessageV3V3 and
// in the future may have GeneratedMessageV3V4 etc. This allows us to change some aspects of this
// class without breaking binary compatibility with old generated code that still subclasses
// the old GeneratedMessageV3 class. To allow these different GeneratedMessageV3V? classes to
// interoperate (e.g., a GeneratedMessageV3V3 object has a message extension field whose class
// type is GeneratedMessageV3V4), these classes still share a common parent class AbstractMessage
// and are using the same GeneratedMessage.GeneratedExtension class for extension definitions.
// Since this class becomes GeneratedMessageV3V? in opensource, we have to add an import here
// to be able to use GeneratedMessage.GeneratedExtension. The GeneratedExtension definition in
// this file is also excluded from opensource to avoid conflict.
import com.google.protobuf.GeneratedMessage.GeneratedExtension;
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.Arrays;
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 GeneratedMessageV3 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 GeneratedMessageV3() {
    unknownFields = UnknownFieldSet.getDefaultInstance();
  }

  protected GeneratedMessageV3(Builder<?> builder) {
    unknownFields = builder.getUnknownFields();
  }

  @Override
  public Parser<? extends GeneratedMessageV3> 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 {
    if (input.shouldDiscardUnknownFields()) {
      return input.skipField(tag);
    }
    return unknownFields.mergeFieldFrom(tag, input);
  }

  /**
   * Delegates to parseUnknownField. This method is obsolete, but we must retain it for
   * compatibility with older generated code.
   */
  protected boolean parseUnknownFieldProto3(
      CodedInputStream input,
      UnknownFieldSet.Builder unknownFields,
      ExtensionRegistryLite extensionRegistry,
      int tag)
      throws IOException {
    return parseUnknownField(input, unknownFields, extensionRegistry, tag);
  }

  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();
    }
  }

  protected static boolean canUseUnsafe() {
    return UnsafeUtil.hasUnsafeArrayOperations() && UnsafeUtil.hasUnsafeByteBufferOperations();
  }

  protected static IntList emptyIntList() {
    return IntArrayList.emptyList();
  }

  protected static IntList newIntList() {
    return new IntArrayList();
  }

  protected static IntList mutableCopy(IntList list) {
    int size = list.size();
    return list.mutableCopyWithCapacity(
        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
  }

  protected static LongList emptyLongList() {
    return LongArrayList.emptyList();
  }

  protected static LongList newLongList() {
    return new LongArrayList();
  }

  protected static LongList mutableCopy(LongList list) {
    int size = list.size();
    return list.mutableCopyWithCapacity(
        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
  }

  protected static FloatList emptyFloatList() {
    return FloatArrayList.emptyList();
  }

  protected static FloatList newFloatList() {
    return new FloatArrayList();
  }

  protected static FloatList mutableCopy(FloatList list) {
    int size = list.size();
    return list.mutableCopyWithCapacity(
        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
  }

  protected static DoubleList emptyDoubleList() {
    return DoubleArrayList.emptyList();
  }

  protected static DoubleList newDoubleList() {
    return new DoubleArrayList();
  }

  protected static DoubleList mutableCopy(DoubleList list) {
    int size = list.size();
    return list.mutableCopyWithCapacity(
        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
  }

  protected static BooleanList emptyBooleanList() {
    return BooleanArrayList.emptyList();
  }

  protected static BooleanList newBooleanList() {
    return new BooleanArrayList();
  }

  protected static BooleanList mutableCopy(BooleanList list) {
    int size = list.size();
    return list.mutableCopyWithCapacity(
        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
  }

  @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;
  }



  /**
   * This class is used to make a generated protected method inaccessible from user's code (e.g.,
   * the {@link #newInstance} method below). When this class is used as a parameter's type in a
   * generated protected method, the method is visible to user's code in the same package, but
   * since the constructor of this class is private to protobuf runtime, user's code can't obtain
   * an instance of this class and as such can't actually make a method call on the protected
   * method.
   */
  protected static final class UnusedPrivateParameter {
    static final UnusedPrivateParameter INSTANCE = new UnusedPrivateParameter();

    private UnusedPrivateParameter() {
    }
  }

  /**
   * Creates a new instance of this message type. Overridden in the generated code.
   */
  @SuppressWarnings({"unused"})
  protected Object newInstance(UnusedPrivateParameter unused) {
    throw new UnsupportedOperationException("This method must be overridden by the subclass.");
  }

  /**
   * 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 GeneratedMessageV3 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 GeneratedMessageV3.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 GeneratedMessageV3.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;
    }

    private BuilderType setUnknownFieldsInternal(final UnknownFieldSet unknownFields) {
      this.unknownFields = unknownFields;
      onChanged();
      return (BuilderType) this;
    }

    @Override
    public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) {
      return setUnknownFieldsInternal(unknownFields);
    }

    /**
     * This method is obsolete, but we must retain it for compatibility with
     * older generated code.
     */
    protected BuilderType setUnknownFieldsProto3(final UnknownFieldSet unknownFields) {
      return setUnknownFieldsInternal(unknownFields);
    }

    @Override
    public BuilderType mergeUnknownFields(
        final UnknownFieldSet unknownFields) {
      return setUnknownFields(
        UnknownFieldSet.newBuilder(this.unknownFields)
                       .mergeFrom(unknownFields)
                       .build());
    }


    @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;
    }

    /**
     * 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 GeneratedMessageV3
      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, input.shouldDiscardUnknownFields() ? null : unknownFields, extensionRegistry,
          getDescriptorForType(), new MessageReflection.ExtensionAdapter(extensions), tag);
    }

    /**
     * Delegates to parseUnknownField. This method is obsolete, but we must retain it for
     * compatibility with older generated code.
     */
    @Override
    protected boolean parseUnknownFieldProto3(
        CodedInputStream input,
        UnknownFieldSet.Builder unknownFields,
        ExtensionRegistryLite extensionRegistry,
        int tag) throws IOException {
      return parseUnknownField(input, unknownFields, extensionRegistry, 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();
    }

    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();
    }

    // ---------------------------------------------------------------
    // 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);
      }
    }

    @Override
    public Message.Builder newBuilderForField(final FieldDescriptor field) {
      if (field.isExtension()) {
        return DynamicMessage.newBuilder(field.getMessageType());
      } else {
        return super.newBuilderForField(field);
      }
    }

    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();
  }


  // =================================================================

  /** 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 GeneratedMessageV3> 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;
    }

    /**
     * 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 GeneratedMessageV3> 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()) {
                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(GeneratedMessageV3 message);
      Object get(GeneratedMessageV3.Builder builder);
      Object getRaw(GeneratedMessageV3 message);
      Object getRaw(GeneratedMessageV3.Builder builder);
      void set(Builder builder, Object value);
      Object getRepeated(GeneratedMessageV3 message, int index);
      Object getRepeated(GeneratedMessageV3.Builder builder, int index);
      Object getRepeatedRaw(GeneratedMessageV3 message, int index);
      Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index);
      void setRepeated(Builder builder,
                       int index, Object value);
      void addRepeated(Builder builder, Object value);
      boolean has(GeneratedMessageV3 message);
      boolean has(GeneratedMessageV3.Builder builder);
      int getRepeatedCount(GeneratedMessageV3 message);
      int getRepeatedCount(GeneratedMessageV3.Builder builder);
      void clear(Builder builder);
      Message.Builder newBuilder();
      Message.Builder getBuilder(GeneratedMessageV3.Builder builder);
      Message.Builder getRepeatedBuilder(GeneratedMessageV3.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 GeneratedMessageV3> 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 GeneratedMessageV3 message) {
        if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) {
          return false;
        }
        return true;
      }

      public boolean has(GeneratedMessageV3.Builder builder) {
        if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) {
          return false;
        }
        return true;
      }

      public FieldDescriptor get(final GeneratedMessageV3 message) {
        int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
        if (fieldNumber > 0) {
          return descriptor.findFieldByNumber(fieldNumber);
        }
        return null;
      }

      public FieldDescriptor get(GeneratedMessageV3.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 GeneratedMessageV3> 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 GeneratedMessageV3 message) {
        return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
      }

      private int getOneofFieldNumber(final GeneratedMessageV3.Builder builder) {
        return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
      }

      @Override
      public Object get(final GeneratedMessageV3 message) {
        return invokeOrDie(getMethod, message);
      }
      @Override
      public Object get(GeneratedMessageV3.Builder builder) {
        return invokeOrDie(getMethodBuilder, builder);
      }
      @Override
      public Object getRaw(final GeneratedMessageV3 message) {
        return get(message);
      }
      @Override
      public Object getRaw(GeneratedMessageV3.Builder builder) {
        return get(builder);
      }
      @Override
      public void set(final Builder builder, final Object value) {
        invokeOrDie(setMethod, builder, value);
      }
      @Override
      public Object getRepeated(final GeneratedMessageV3 message, final int index) {
        throw new UnsupportedOperationException(
          "getRepeatedField() called on a singular field.");
      }
      @Override
      public Object getRepeatedRaw(final GeneratedMessageV3 message, final int index) {
        throw new UnsupportedOperationException(
          "getRepeatedFieldRaw() called on a singular field.");
      }
      @Override
      public Object getRepeated(GeneratedMessageV3.Builder builder, int index) {
        throw new UnsupportedOperationException(
          "getRepeatedField() called on a singular field.");
      }
      @Override
      public Object getRepeatedRaw(GeneratedMessageV3.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 GeneratedMessageV3 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(GeneratedMessageV3.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 GeneratedMessageV3 message) {
        throw new UnsupportedOperationException(
          "getRepeatedFieldSize() called on a singular field.");
      }
      @Override
      public int getRepeatedCount(GeneratedMessageV3.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(GeneratedMessageV3.Builder builder) {
        throw new UnsupportedOperationException(
          "getFieldBuilder() called on a non-Message type.");
      }
      @Override
      public Message.Builder getRepeatedBuilder(GeneratedMessageV3.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 GeneratedMessageV3> 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 GeneratedMessageV3 message) {
        return invokeOrDie(getMethod, message);
      }
      @Override
      public Object get(GeneratedMessageV3.Builder builder) {
        return invokeOrDie(getMethodBuilder, builder);
      }
      @Override
      public Object getRaw(final GeneratedMessageV3 message) {
        return get(message);
      }
      @Override
      public Object getRaw(GeneratedMessageV3.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 GeneratedMessageV3 message, final int index) {
        return invokeOrDie(getRepeatedMethod, message, index);
      }
      @Override
      public Object getRepeated(GeneratedMessageV3.Builder builder, int index) {
        return invokeOrDie(getRepeatedMethodBuilder, builder, index);
      }
      @Override
      public Object getRepeatedRaw(GeneratedMessageV3 message, int index) {
        return getRepeated(message, index);
      }
      @Override
      public Object getRepeatedRaw(GeneratedMessageV3.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 GeneratedMessageV3 message) {
        throw new UnsupportedOperationException(
          "hasField() called on a repeated field.");
      }
      @Override
      public boolean has(GeneratedMessageV3.Builder builder) {
        throw new UnsupportedOperationException(
          "hasField() called on a repeated field.");
      }
      @Override
      public int getRepeatedCount(final GeneratedMessageV3 message) {
        return (Integer) invokeOrDie(getCountMethod, message);
      }
      @Override
      public int getRepeatedCount(GeneratedMessageV3.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(GeneratedMessageV3.Builder builder) {
        throw new UnsupportedOperationException(
          "getFieldBuilder() called on a non-Message type.");
      }
      @Override
      public Message.Builder getRepeatedBuilder(GeneratedMessageV3.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 GeneratedMessageV3> messageClass,
          final Class<? extends Builder> builderClass) {
        field = descriptor;
        Method getDefaultInstanceMethod =
            getMethodOrDie(messageClass, "getDefaultInstance");
        MapField defaultMapField = getMapField(
            (GeneratedMessageV3) invokeOrDie(getDefaultInstanceMethod, null));
        mapEntryMessageDefaultInstance =
            defaultMapField.getMapEntryMessageDefaultInstance();
      }

      private final FieldDescriptor field;
      private final Message mapEntryMessageDefaultInstance;

      private MapField<?, ?> getMapField(GeneratedMessageV3 message) {
        return (MapField<?, ?>) message.internalGetMapField(field.getNumber());
      }

      private MapField<?, ?> getMapField(GeneratedMessageV3.Builder builder) {
        return (MapField<?, ?>) builder.internalGetMapField(field.getNumber());
      }

      private MapField<?, ?> getMutableMapField(
          GeneratedMessageV3.Builder builder) {
        return (MapField<?, ?>) builder.internalGetMutableMapField(
            field.getNumber());
      }

      private Message coerceType(Message value) {
        if (value == null) {
          return null;
        }
        if (mapEntryMessageDefaultInstance.getClass().isInstance(value)) {
          return value;
        }
        // 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 mapEntryMessageDefaultInstance.toBuilder().mergeFrom(value).build();
      }

      @Override
      @SuppressWarnings("unchecked")
      public Object get(GeneratedMessageV3 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(GeneratedMessageV3 message) {
        return get(message);
      }

      @Override
      public Object getRaw(GeneratedMessageV3.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(GeneratedMessageV3 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(GeneratedMessageV3 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, coerceType((Message) value));
      }

      @Override
      public void addRepeated(Builder builder, Object value) {
        getMutableMapField(builder).getMutableList().add(coerceType((Message) value));
      }

      @Override
      public boolean has(GeneratedMessageV3 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(GeneratedMessageV3 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 GeneratedMessageV3> 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 GeneratedMessageV3 message) {
        if (supportUnknownEnumValue) {
          int value = (Integer) invokeOrDie(getValueMethod, message);
          return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
        }
        return invokeOrDie(getValueDescriptorMethod, super.get(message));
      }

      @Override
      public Object get(final GeneratedMessageV3.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 GeneratedMessageV3> 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 GeneratedMessageV3 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 GeneratedMessageV3.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 GeneratedMessageV3 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 GeneratedMessageV3.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 GeneratedMessageV3> 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 GeneratedMessageV3 message) {
        return invokeOrDie(getBytesMethod, message);
      }

      @Override
      public Object getRaw(GeneratedMessageV3.Builder builder) {
        return invokeOrDie(getBytesMethodBuilder, builder);
      }

      @Override
      public void set(GeneratedMessageV3.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 GeneratedMessageV3> 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(GeneratedMessageV3.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 GeneratedMessageV3> 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 GeneratedMessageV3.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);
    }
  }

  protected static <V> void serializeIntegerMapTo(
      CodedOutputStream out,
      MapField<Integer, V> field,
      MapEntry<Integer, V> defaultEntry,
      int fieldNumber) throws IOException {
    Map<Integer, V> m = field.getMap();
    if (!out.isSerializationDeterministic()) {
      serializeMapTo(out, m, defaultEntry, fieldNumber);
      return;
    }
    // Sorting the unboxed keys and then look up the values during serialziation is 2x faster
    // than sorting map entries with a custom comparator directly.
    int[] keys = new int[m.size()];
    int index = 0;
    for (int k : m.keySet()) {
      keys[index++] = k;
    }
    Arrays.sort(keys);
    for (int key : keys) {
      out.writeMessage(fieldNumber,
          defaultEntry.newBuilderForType()
              .setKey(key)
              .setValue(m.get(key))
              .build());
    }
  }

  protected static <V> void serializeLongMapTo(
      CodedOutputStream out,
      MapField<Long, V> field,
      MapEntry<Long, V> defaultEntry,
      int fieldNumber)
      throws IOException {
    Map<Long, V> m = field.getMap();
    if (!out.isSerializationDeterministic()) {
      serializeMapTo(out, m, defaultEntry, fieldNumber);
      return;
    }

    long[] keys = new long[m.size()];
    int index = 0;
    for (long k : m.keySet()) {
      keys[index++] = k;
    }
    Arrays.sort(keys);
    for (long key : keys) {
      out.writeMessage(fieldNumber,
          defaultEntry.newBuilderForType()
              .setKey(key)
              .setValue(m.get(key))
              .build());
    }
  }

  protected static <V> void serializeStringMapTo(
      CodedOutputStream out,
      MapField<String, V> field,
      MapEntry<String, V> defaultEntry,
      int fieldNumber)
      throws IOException {
    Map<String, V> m = field.getMap();
    if (!out.isSerializationDeterministic()) {
      serializeMapTo(out, m, defaultEntry, fieldNumber);
      return;
    }

    // Sorting the String keys and then look up the values during serialziation is 25% faster than
    // sorting map entries with a custom comparator directly.
    String[] keys = new String[m.size()];
    keys = m.keySet().toArray(keys);
    Arrays.sort(keys);
    for (String key : keys) {
      out.writeMessage(fieldNumber,
          defaultEntry.newBuilderForType()
              .setKey(key)
              .setValue(m.get(key))
              .build());
    }
  }

  protected static <V> void serializeBooleanMapTo(
      CodedOutputStream out,
      MapField<Boolean, V> field,
      MapEntry<Boolean, V> defaultEntry,
      int fieldNumber)
      throws IOException {
    Map<Boolean, V> m = field.getMap();
    if (!out.isSerializationDeterministic()) {
      serializeMapTo(out, m, defaultEntry, fieldNumber);
      return;
    }
    maybeSerializeBooleanEntryTo(out, m, defaultEntry, fieldNumber, false);
    maybeSerializeBooleanEntryTo(out, m, defaultEntry, fieldNumber, true);
  }

  private static <V> void maybeSerializeBooleanEntryTo(
      CodedOutputStream out,
      Map<Boolean, V> m,
      MapEntry<Boolean, V> defaultEntry,
      int fieldNumber,
      boolean key)
      throws IOException {
    if (m.containsKey(key)) {
      out.writeMessage(fieldNumber,
          defaultEntry.newBuilderForType()
              .setKey(key)
              .setValue(m.get(key))
              .build());
    }
  }

  /** Serialize the map using the iteration order. */
  private static <K, V> void serializeMapTo(
      CodedOutputStream out,
      Map<K, V> m,
      MapEntry<K, V> defaultEntry,
      int fieldNumber)
      throws IOException {
    for (Map.Entry<K, V> entry : m.entrySet()) {
      out.writeMessage(fieldNumber,
          defaultEntry.newBuilderForType()
              .setKey(entry.getKey())
              .setValue(entry.getValue())
              .build());
    }
  }
}

