// 
// Decompiled by Procyon v0.6.0
// 

package com.google.protobuf;

import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.Arrays;
import java.io.ObjectStreamException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.io.InputStream;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;
import java.util.Map;
import java.io.IOException;
import java.util.Set;
import java.util.logging.Logger;
import java.io.Serializable;

public abstract class GeneratedMessage extends AbstractMessage implements Serializable
{
    private static final long serialVersionUID = 1L;
    private static final Logger logger;
    protected static boolean alwaysUseFieldBuilders;
    protected UnknownFieldSet unknownFields;
    static final String PRE22_GENCODE_SILENCE_PROPERTY = "com.google.protobuf.use_unsafe_pre22_gencode";
    static final String PRE22_GENCODE_ERROR_PROPERTY = "com.google.protobuf.error_on_unsafe_pre22_gencode";
    static final String PRE22_GENCODE_VULNERABILITY_MESSAGE = "As of 2022/09/29 (release 21.7) makeExtensionsImmutable should not be called from protobuf gencode. If you are seeing this message, your gencode is vulnerable to a denial of service attack. You should regenerate your code using protobuf 25.6 or later. Use the latest version that meets your needs. However, if you understand the risks and wish to continue with vulnerable gencode, you can set the system property `-Dcom.google.protobuf.use_unsafe_pre22_gencode` on the command line to silence this warning. You also can set `-Dcom.google.protobuf.error_on_unsafe_pre22_gencode` to throw an error instead. See security vulnerability: https://github.com/protocolbuffers/protobuf/security/advisories/GHSA-h4h5-3hr4-j3g2";
    protected static final Set<String> loggedPre22TypeNames;
    
    protected GeneratedMessage() {
        this.unknownFields = UnknownFieldSet.getDefaultInstance();
    }
    
    protected GeneratedMessage(final Builder<?> builder) {
        this.unknownFields = builder.getUnknownFields();
    }
    
    @Override
    public Parser<? extends GeneratedMessage> getParserForType() {
        throw new UnsupportedOperationException("This is supposed to be overridden by subclasses.");
    }
    
    static void enableAlwaysUseFieldBuildersForTesting() {
        setAlwaysUseFieldBuildersForTesting(true);
    }
    
    static void setAlwaysUseFieldBuildersForTesting(final boolean useBuilders) {
        GeneratedMessage.alwaysUseFieldBuilders = useBuilders;
    }
    
    protected abstract FieldAccessorTable internalGetFieldAccessorTable();
    
    @Override
    public Descriptors.Descriptor getDescriptorForType() {
        return this.internalGetFieldAccessorTable().descriptor;
    }
    
    @Deprecated
    protected void mergeFromAndMakeImmutableInternal(final CodedInputStream input, final ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException {
        final Schema<GeneratedMessage> schema = Protobuf.getInstance().schemaFor(this);
        try {
            schema.mergeFrom(this, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
        }
        catch (final InvalidProtocolBufferException e) {
            throw e.setUnfinishedMessage(this);
        }
        catch (final IOException e2) {
            throw new InvalidProtocolBufferException(e2).setUnfinishedMessage(this);
        }
        schema.makeImmutable(this);
    }
    
    private Map<Descriptors.FieldDescriptor, Object> getAllFieldsMutable(final boolean getBytesForString) {
        final TreeMap<Descriptors.FieldDescriptor, Object> result = new TreeMap<Descriptors.FieldDescriptor, Object>();
        final FieldAccessorTable fieldAccessorTable = this.internalGetFieldAccessorTable();
        final Descriptors.Descriptor descriptor = fieldAccessorTable.descriptor;
        final List<Descriptors.FieldDescriptor> fields = descriptor.getFields();
        for (int i = 0; i < fields.size(); ++i) {
            Descriptors.FieldDescriptor field = fields.get(i);
            final Descriptors.OneofDescriptor oneofDescriptor = field.getContainingOneof();
            if (oneofDescriptor != null) {
                i += oneofDescriptor.getFieldCount() - 1;
                if (!this.hasOneof(oneofDescriptor)) {
                    continue;
                }
                field = this.getOneofFieldDescriptor(oneofDescriptor);
            }
            else if (field.isRepeated()) {
                final List<?> value = (List<?>)this.getField(field);
                if (!value.isEmpty()) {
                    result.put(field, value);
                }
                continue;
            }
            else if (!this.hasField(field)) {
                continue;
            }
            if (getBytesForString && field.getJavaType() == Descriptors.FieldDescriptor.JavaType.STRING) {
                result.put(field, this.getFieldRaw(field));
            }
            else {
                result.put(field, this.getField(field));
            }
        }
        return result;
    }
    
    @Override
    public boolean isInitialized() {
        for (final Descriptors.FieldDescriptor field : this.getDescriptorForType().getFields()) {
            if (field.isRequired() && !this.hasField(field)) {
                return false;
            }
            if (field.getJavaType() != Descriptors.FieldDescriptor.JavaType.MESSAGE) {
                continue;
            }
            if (field.isRepeated()) {
                final List<Message> messageList = (List<Message>)this.getField(field);
                for (final Message element : messageList) {
                    if (!element.isInitialized()) {
                        return false;
                    }
                }
            }
            else {
                if (this.hasField(field) && !((Message)this.getField(field)).isInitialized()) {
                    return false;
                }
                continue;
            }
        }
        return true;
    }
    
    @Override
    public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
        return Collections.unmodifiableMap((Map<? extends Descriptors.FieldDescriptor, ?>)this.getAllFieldsMutable(false));
    }
    
    Map<Descriptors.FieldDescriptor, Object> getAllFieldsRaw() {
        return Collections.unmodifiableMap((Map<? extends Descriptors.FieldDescriptor, ?>)this.getAllFieldsMutable(true));
    }
    
    @Override
    public boolean hasOneof(final Descriptors.OneofDescriptor oneof) {
        return this.internalGetFieldAccessorTable().getOneof(oneof).has(this);
    }
    
    @Override
    public Descriptors.FieldDescriptor getOneofFieldDescriptor(final Descriptors.OneofDescriptor oneof) {
        return this.internalGetFieldAccessorTable().getOneof(oneof).get(this);
    }
    
    @Override
    public boolean hasField(final Descriptors.FieldDescriptor field) {
        return this.internalGetFieldAccessorTable().getField(field).has(this);
    }
    
    @Override
    public Object getField(final Descriptors.FieldDescriptor field) {
        return this.internalGetFieldAccessorTable().getField(field).get(this);
    }
    
    Object getFieldRaw(final Descriptors.FieldDescriptor field) {
        return this.internalGetFieldAccessorTable().getField(field).getRaw(this);
    }
    
    @Override
    public int getRepeatedFieldCount(final Descriptors.FieldDescriptor field) {
        return this.internalGetFieldAccessorTable().getField(field).getRepeatedCount(this);
    }
    
    @Override
    public Object getRepeatedField(final Descriptors.FieldDescriptor field, final int index) {
        return this.internalGetFieldAccessorTable().getField(field).getRepeated(this, index);
    }
    
    @Override
    public UnknownFieldSet getUnknownFields() {
        return this.unknownFields;
    }
    
    void setUnknownFields(final UnknownFieldSet unknownFields) {
        this.unknownFields = unknownFields;
    }
    
    protected boolean parseUnknownField(final CodedInputStream input, final UnknownFieldSet.Builder unknownFields, final ExtensionRegistryLite extensionRegistry, final int tag) throws IOException {
        if (input.shouldDiscardUnknownFields()) {
            return input.skipField(tag);
        }
        return unknownFields.mergeFieldFrom(tag, input);
    }
    
    protected boolean parseUnknownFieldProto3(final CodedInputStream input, final UnknownFieldSet.Builder unknownFields, final ExtensionRegistryLite extensionRegistry, final int tag) throws IOException {
        return this.parseUnknownField(input, unknownFields, extensionRegistry, tag);
    }
    
    protected static <M extends Message> M parseWithIOException(final Parser<M> parser, final InputStream input) throws IOException {
        try {
            return parser.parseFrom(input);
        }
        catch (final InvalidProtocolBufferException e) {
            throw e.unwrapIOException();
        }
    }
    
    protected static <M extends Message> M parseWithIOException(final Parser<M> parser, final InputStream input, final ExtensionRegistryLite extensions) throws IOException {
        try {
            return parser.parseFrom(input, extensions);
        }
        catch (final InvalidProtocolBufferException e) {
            throw e.unwrapIOException();
        }
    }
    
    protected static <M extends Message> M parseWithIOException(final Parser<M> parser, final CodedInputStream input) throws IOException {
        try {
            return parser.parseFrom(input);
        }
        catch (final InvalidProtocolBufferException e) {
            throw e.unwrapIOException();
        }
    }
    
    protected static <M extends Message> M parseWithIOException(final Parser<M> parser, final CodedInputStream input, final ExtensionRegistryLite extensions) throws IOException {
        try {
            return parser.parseFrom(input, extensions);
        }
        catch (final InvalidProtocolBufferException e) {
            throw e.unwrapIOException();
        }
    }
    
    protected static <M extends Message> M parseDelimitedWithIOException(final Parser<M> parser, final InputStream input) throws IOException {
        try {
            return parser.parseDelimitedFrom(input);
        }
        catch (final InvalidProtocolBufferException e) {
            throw e.unwrapIOException();
        }
    }
    
    protected static <M extends Message> M parseDelimitedWithIOException(final Parser<M> parser, final InputStream input, final ExtensionRegistryLite extensions) throws IOException {
        try {
            return parser.parseDelimitedFrom(input, extensions);
        }
        catch (final InvalidProtocolBufferException e) {
            throw e.unwrapIOException();
        }
    }
    
    protected static boolean canUseUnsafe() {
        return UnsafeUtil.hasUnsafeArrayOperations() && UnsafeUtil.hasUnsafeByteBufferOperations();
    }
    
    protected static Internal.IntList emptyIntList() {
        return IntArrayList.emptyList();
    }
    
    static void warnPre22Gencode(final Class<?> messageClass) {
        if (System.getProperty("com.google.protobuf.use_unsafe_pre22_gencode") != null) {
            return;
        }
        final String messageName = messageClass.getName();
        final String vulnerabilityMessage = "Vulnerable protobuf generated type in use: " + messageName + "\n" + "As of 2022/09/29 (release 21.7) makeExtensionsImmutable should not be called from protobuf gencode. If you are seeing this message, your gencode is vulnerable to a denial of service attack. You should regenerate your code using protobuf 25.6 or later. Use the latest version that meets your needs. However, if you understand the risks and wish to continue with vulnerable gencode, you can set the system property `-Dcom.google.protobuf.use_unsafe_pre22_gencode` on the command line to silence this warning. You also can set `-Dcom.google.protobuf.error_on_unsafe_pre22_gencode` to throw an error instead. See security vulnerability: https://github.com/protocolbuffers/protobuf/security/advisories/GHSA-h4h5-3hr4-j3g2";
        if (System.getProperty("com.google.protobuf.error_on_unsafe_pre22_gencode") != null) {
            throw new UnsupportedOperationException(vulnerabilityMessage);
        }
        if (!GeneratedMessage.loggedPre22TypeNames.add(messageName)) {
            return;
        }
        GeneratedMessage.logger.warning(vulnerabilityMessage);
    }
    
    protected void makeExtensionsImmutable() {
        warnPre22Gencode(this.getClass());
    }
    
    protected static Internal.LongList emptyLongList() {
        return LongArrayList.emptyList();
    }
    
    protected static Internal.FloatList emptyFloatList() {
        return FloatArrayList.emptyList();
    }
    
    protected static Internal.DoubleList emptyDoubleList() {
        return DoubleArrayList.emptyList();
    }
    
    protected static Internal.BooleanList emptyBooleanList() {
        return BooleanArrayList.emptyList();
    }
    
    protected static <ListT extends Internal.ProtobufList<?>> ListT makeMutableCopy(final ListT list) {
        return makeMutableCopy(list, 0);
    }
    
    protected static <ListT extends Internal.ProtobufList<?>> ListT makeMutableCopy(final ListT list, int minCapacity) {
        final int size = list.size();
        if (minCapacity <= size) {
            minCapacity = size * 2;
        }
        if (minCapacity <= 0) {
            minCapacity = 10;
        }
        return (ListT)list.mutableCopyWithCapacity(minCapacity);
    }
    
    protected static <T> Internal.ProtobufList<T> emptyList(final Class<T> elementType) {
        return (Internal.ProtobufList<T>)ProtobufArrayList.emptyList();
    }
    
    @Override
    public void writeTo(final CodedOutputStream output) throws IOException {
        MessageReflection.writeMessageTo(this, this.getAllFieldsRaw(), output, false);
    }
    
    @Override
    public int getSerializedSize() {
        final int size = this.memoizedSize;
        if (size != -1) {
            return size;
        }
        return this.memoizedSize = MessageReflection.getSerializedSize(this, this.getAllFieldsRaw());
    }
    
    protected Object newInstance(final UnusedPrivateParameter unused) {
        throw new UnsupportedOperationException("This method must be overridden by the subclass.");
    }
    
    public static <ContainingT extends Message, T> GeneratedExtension<ContainingT, T> newMessageScopedGeneratedExtension(final Message scope, final int descriptorIndex, final Class<?> singularType, final Message defaultInstance) {
        return new GeneratedExtension<ContainingT, T>(new CachedDescriptorRetriever() {
            public Descriptors.FieldDescriptor loadDescriptor() {
                return scope.getDescriptorForType().getExtension(descriptorIndex);
            }
        }, singularType, defaultInstance, Extension.ExtensionType.IMMUTABLE);
    }
    
    public static <ContainingT extends Message, T> GeneratedExtension<ContainingT, T> newFileScopedGeneratedExtension(final Class<?> singularType, final Message defaultInstance) {
        return new GeneratedExtension<ContainingT, T>(null, singularType, defaultInstance, Extension.ExtensionType.IMMUTABLE);
    }
    
    private static Method getMethodOrDie(final Class<?> clazz, final String name, final Class<?>... params) {
        try {
            return clazz.getMethod(name, params);
        }
        catch (final NoSuchMethodException e) {
            throw new IllegalStateException("Generated message class \"" + clazz.getName() + "\" missing method \"" + name + "\".", e);
        }
    }
    
    @CanIgnoreReturnValue
    private static Object invokeOrDie(final Method method, final Object object, final Object... params) {
        try {
            return method.invoke(object, params);
        }
        catch (final IllegalAccessException e) {
            throw new IllegalStateException("Couldn't use Java reflection to implement protocol message reflection.", e);
        }
        catch (final InvocationTargetException e2) {
            final Throwable cause = e2.getCause();
            if (cause instanceof RuntimeException) {
                throw (RuntimeException)cause;
            }
            if (cause instanceof Error) {
                throw (Error)cause;
            }
            throw new IllegalStateException("Unexpected exception thrown by generated accessor method.", cause);
        }
    }
    
    protected MapFieldReflectionAccessor internalGetMapFieldReflection(final int fieldNumber) {
        return this.internalGetMapField(fieldNumber);
    }
    
    @Deprecated
    protected MapField internalGetMapField(final int fieldNumber) {
        throw new IllegalArgumentException("No map fields found in " + this.getClass().getName());
    }
    
    protected Object writeReplace() throws ObjectStreamException {
        return new GeneratedMessageLite.SerializedForm(this);
    }
    
    private static <MessageT extends ExtendableMessage<MessageT>, T> Extension<MessageT, T> checkNotLite(final ExtensionLite<? extends MessageT, T> extension) {
        if (extension.isLite()) {
            throw new IllegalArgumentException("Expected non-lite extension.");
        }
        return (Extension)extension;
    }
    
    protected static boolean isStringEmpty(final Object value) {
        if (value instanceof String) {
            return ((String)value).isEmpty();
        }
        return ((ByteString)value).isEmpty();
    }
    
    protected static int computeStringSize(final int fieldNumber, final Object value) {
        if (value instanceof String) {
            return CodedOutputStream.computeStringSize(fieldNumber, (String)value);
        }
        return CodedOutputStream.computeBytesSize(fieldNumber, (ByteString)value);
    }
    
    protected static int computeStringSizeNoTag(final Object value) {
        if (value instanceof String) {
            return CodedOutputStream.computeStringSizeNoTag((String)value);
        }
        return CodedOutputStream.computeBytesSizeNoTag((ByteString)value);
    }
    
    protected static void writeString(final 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(final 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(final CodedOutputStream out, final MapField<Integer, V> field, final MapEntry<Integer, V> defaultEntry, final int fieldNumber) throws IOException {
        final Map<Integer, V> m = field.getMap();
        if (!out.isSerializationDeterministic()) {
            serializeMapTo(out, m, defaultEntry, fieldNumber);
            return;
        }
        final int[] keys = new int[m.size()];
        int index = 0;
        for (final int k : m.keySet()) {
            keys[index++] = k;
        }
        Arrays.sort(keys);
        for (final int key : keys) {
            out.writeMessage(fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build());
        }
    }
    
    protected static <V> void serializeLongMapTo(final CodedOutputStream out, final MapField<Long, V> field, final MapEntry<Long, V> defaultEntry, final int fieldNumber) throws IOException {
        final Map<Long, V> m = field.getMap();
        if (!out.isSerializationDeterministic()) {
            serializeMapTo(out, m, defaultEntry, fieldNumber);
            return;
        }
        final long[] keys = new long[m.size()];
        int index = 0;
        for (final long k : m.keySet()) {
            keys[index++] = k;
        }
        Arrays.sort(keys);
        for (final long key : keys) {
            out.writeMessage(fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build());
        }
    }
    
    protected static <V> void serializeStringMapTo(final CodedOutputStream out, final MapField<String, V> field, final MapEntry<String, V> defaultEntry, final int fieldNumber) throws IOException {
        final Map<String, V> m = field.getMap();
        if (!out.isSerializationDeterministic()) {
            serializeMapTo(out, m, defaultEntry, fieldNumber);
            return;
        }
        String[] keys = new String[m.size()];
        keys = m.keySet().toArray(keys);
        Arrays.sort(keys);
        for (final String key : keys) {
            out.writeMessage(fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build());
        }
    }
    
    protected static <V> void serializeBooleanMapTo(final CodedOutputStream out, final MapField<Boolean, V> field, final MapEntry<Boolean, V> defaultEntry, final int fieldNumber) throws IOException {
        final 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(final CodedOutputStream out, final Map<Boolean, V> m, final MapEntry<Boolean, V> defaultEntry, final int fieldNumber, final boolean key) throws IOException {
        if (m.containsKey(key)) {
            out.writeMessage(fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build());
        }
    }
    
    private static <K, V> void serializeMapTo(final CodedOutputStream out, final Map<K, V> m, final MapEntry<K, V> defaultEntry, final int fieldNumber) throws IOException {
        for (final Map.Entry<K, V> entry : m.entrySet()) {
            out.writeMessage(fieldNumber, defaultEntry.newBuilderForType().setKey(entry.getKey()).setValue(entry.getValue()).build());
        }
    }
    
    static {
        logger = Logger.getLogger(GeneratedMessage.class.getName());
        GeneratedMessage.alwaysUseFieldBuilders = false;
        loggedPre22TypeNames = new CopyOnWriteArraySet<String>();
    }
    
    protected static final class UnusedPrivateParameter
    {
        static final UnusedPrivateParameter INSTANCE;
        
        private UnusedPrivateParameter() {
        }
        
        static {
            INSTANCE = new UnusedPrivateParameter();
        }
    }
    
    public abstract static class Builder<BuilderT extends Builder<BuilderT>> extends AbstractMessage.Builder<BuilderT>
    {
        private BuilderParent builderParent;
        private BuilderParentImpl meAsParent;
        private boolean isClean;
        private Object unknownFieldsOrBuilder;
        
        protected Builder() {
            this.unknownFieldsOrBuilder = UnknownFieldSet.getDefaultInstance();
        }
        
        protected Builder(final BuilderParent builderParent) {
            this.unknownFieldsOrBuilder = UnknownFieldSet.getDefaultInstance();
            this.builderParent = builderParent;
        }
        
        @Override
        void dispose() {
            this.builderParent = null;
        }
        
        protected void onBuilt() {
            if (this.builderParent != null) {
                this.markClean();
            }
        }
        
        protected void markClean() {
            this.isClean = true;
        }
        
        protected boolean isClean() {
            return this.isClean;
        }
        
        @Override
        public BuilderT clone() {
            final BuilderT builder = (BuilderT)this.getDefaultInstanceForType().newBuilderForType();
            return builder.mergeFrom(this.buildPartial());
        }
        
        @Override
        public BuilderT clear() {
            this.unknownFieldsOrBuilder = UnknownFieldSet.getDefaultInstance();
            this.onChanged();
            return (BuilderT)this;
        }
        
        protected abstract FieldAccessorTable internalGetFieldAccessorTable();
        
        @Override
        public Descriptors.Descriptor getDescriptorForType() {
            return this.internalGetFieldAccessorTable().descriptor;
        }
        
        @Override
        public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
            return Collections.unmodifiableMap((Map<? extends Descriptors.FieldDescriptor, ?>)this.getAllFieldsMutable());
        }
        
        private Map<Descriptors.FieldDescriptor, Object> getAllFieldsMutable() {
            final TreeMap<Descriptors.FieldDescriptor, Object> result = new TreeMap<Descriptors.FieldDescriptor, Object>();
            final FieldAccessorTable fieldAccessorTable = this.internalGetFieldAccessorTable();
            final Descriptors.Descriptor descriptor = fieldAccessorTable.descriptor;
            final List<Descriptors.FieldDescriptor> fields = descriptor.getFields();
            for (int i = 0; i < fields.size(); ++i) {
                Descriptors.FieldDescriptor field = fields.get(i);
                final Descriptors.OneofDescriptor oneofDescriptor = field.getContainingOneof();
                if (oneofDescriptor != null) {
                    i += oneofDescriptor.getFieldCount() - 1;
                    if (!this.hasOneof(oneofDescriptor)) {
                        continue;
                    }
                    field = this.getOneofFieldDescriptor(oneofDescriptor);
                }
                else if (field.isRepeated()) {
                    final List<?> value = (List<?>)this.getField(field);
                    if (!value.isEmpty()) {
                        result.put(field, value);
                    }
                    continue;
                }
                else if (!this.hasField(field)) {
                    continue;
                }
                result.put(field, this.getField(field));
            }
            return result;
        }
        
        @Override
        public Message.Builder newBuilderForField(final Descriptors.FieldDescriptor field) {
            return this.internalGetFieldAccessorTable().getField(field).newBuilder();
        }
        
        @Override
        public Message.Builder getFieldBuilder(final Descriptors.FieldDescriptor field) {
            return this.internalGetFieldAccessorTable().getField(field).getBuilder(this);
        }
        
        @Override
        public Message.Builder getRepeatedFieldBuilder(final Descriptors.FieldDescriptor field, final int index) {
            return this.internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(this, index);
        }
        
        @Override
        public boolean hasOneof(final Descriptors.OneofDescriptor oneof) {
            return this.internalGetFieldAccessorTable().getOneof(oneof).has(this);
        }
        
        @Override
        public Descriptors.FieldDescriptor getOneofFieldDescriptor(final Descriptors.OneofDescriptor oneof) {
            return this.internalGetFieldAccessorTable().getOneof(oneof).get(this);
        }
        
        @Override
        public boolean hasField(final Descriptors.FieldDescriptor field) {
            return this.internalGetFieldAccessorTable().getField(field).has(this);
        }
        
        @Override
        public Object getField(final Descriptors.FieldDescriptor field) {
            final Object object = this.internalGetFieldAccessorTable().getField(field).get(this);
            if (field.isRepeated()) {
                return Collections.unmodifiableList((List<?>)object);
            }
            return object;
        }
        
        @Override
        public BuilderT setField(final Descriptors.FieldDescriptor field, final Object value) {
            this.internalGetFieldAccessorTable().getField(field).set(this, value);
            return (BuilderT)this;
        }
        
        @Override
        public BuilderT clearField(final Descriptors.FieldDescriptor field) {
            this.internalGetFieldAccessorTable().getField(field).clear(this);
            return (BuilderT)this;
        }
        
        @Override
        public BuilderT clearOneof(final Descriptors.OneofDescriptor oneof) {
            this.internalGetFieldAccessorTable().getOneof(oneof).clear(this);
            return (BuilderT)this;
        }
        
        @Override
        public int getRepeatedFieldCount(final Descriptors.FieldDescriptor field) {
            return this.internalGetFieldAccessorTable().getField(field).getRepeatedCount(this);
        }
        
        @Override
        public Object getRepeatedField(final Descriptors.FieldDescriptor field, final int index) {
            return this.internalGetFieldAccessorTable().getField(field).getRepeated(this, index);
        }
        
        @Override
        public BuilderT setRepeatedField(final Descriptors.FieldDescriptor field, final int index, final Object value) {
            this.internalGetFieldAccessorTable().getField(field).setRepeated(this, index, value);
            return (BuilderT)this;
        }
        
        @Override
        public BuilderT addRepeatedField(final Descriptors.FieldDescriptor field, final Object value) {
            this.internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
            return (BuilderT)this;
        }
        
        private BuilderT setUnknownFieldsInternal(final UnknownFieldSet unknownFields) {
            this.unknownFieldsOrBuilder = unknownFields;
            this.onChanged();
            return (BuilderT)this;
        }
        
        @Override
        public BuilderT setUnknownFields(final UnknownFieldSet unknownFields) {
            return this.setUnknownFieldsInternal(unknownFields);
        }
        
        protected BuilderT setUnknownFieldsProto3(final UnknownFieldSet unknownFields) {
            return this.setUnknownFieldsInternal(unknownFields);
        }
        
        @Override
        public BuilderT mergeUnknownFields(final UnknownFieldSet unknownFields) {
            if (UnknownFieldSet.getDefaultInstance().equals(unknownFields)) {
                return (BuilderT)this;
            }
            if (UnknownFieldSet.getDefaultInstance().equals(this.unknownFieldsOrBuilder)) {
                this.unknownFieldsOrBuilder = unknownFields;
                this.onChanged();
                return (BuilderT)this;
            }
            this.getUnknownFieldSetBuilder().mergeFrom(unknownFields);
            this.onChanged();
            return (BuilderT)this;
        }
        
        @Override
        public boolean isInitialized() {
            for (final Descriptors.FieldDescriptor field : this.getDescriptorForType().getFields()) {
                if (field.isRequired() && !this.hasField(field)) {
                    return false;
                }
                if (field.getJavaType() != Descriptors.FieldDescriptor.JavaType.MESSAGE) {
                    continue;
                }
                if (field.isRepeated()) {
                    final List<Message> messageList = (List<Message>)this.getField(field);
                    for (final Message element : messageList) {
                        if (!element.isInitialized()) {
                            return false;
                        }
                    }
                }
                else {
                    if (this.hasField(field) && !((Message)this.getField(field)).isInitialized()) {
                        return false;
                    }
                    continue;
                }
            }
            return true;
        }
        
        @Override
        public final UnknownFieldSet getUnknownFields() {
            if (this.unknownFieldsOrBuilder instanceof UnknownFieldSet) {
                return (UnknownFieldSet)this.unknownFieldsOrBuilder;
            }
            return ((UnknownFieldSet.Builder)this.unknownFieldsOrBuilder).buildPartial();
        }
        
        protected boolean parseUnknownField(final CodedInputStream input, final ExtensionRegistryLite extensionRegistry, final int tag) throws IOException {
            if (input.shouldDiscardUnknownFields()) {
                return input.skipField(tag);
            }
            return this.getUnknownFieldSetBuilder().mergeFieldFrom(tag, input);
        }
        
        protected final void mergeUnknownLengthDelimitedField(final int number, final ByteString bytes) {
            this.getUnknownFieldSetBuilder().mergeLengthDelimitedField(number, bytes);
        }
        
        protected final void mergeUnknownVarintField(final int number, final int value) {
            this.getUnknownFieldSetBuilder().mergeVarintField(number, value);
        }
        
        @Override
        protected UnknownFieldSet.Builder getUnknownFieldSetBuilder() {
            if (this.unknownFieldsOrBuilder instanceof UnknownFieldSet) {
                this.unknownFieldsOrBuilder = ((UnknownFieldSet)this.unknownFieldsOrBuilder).toBuilder();
            }
            this.onChanged();
            return (UnknownFieldSet.Builder)this.unknownFieldsOrBuilder;
        }
        
        @Override
        protected void setUnknownFieldSetBuilder(final UnknownFieldSet.Builder builder) {
            this.unknownFieldsOrBuilder = builder;
            this.onChanged();
        }
        
        protected BuilderParent getParentForChildren() {
            if (this.meAsParent == null) {
                this.meAsParent = new BuilderParentImpl();
            }
            return this.meAsParent;
        }
        
        protected final void onChanged() {
            if (this.isClean && this.builderParent != null) {
                this.builderParent.markDirty();
                this.isClean = false;
            }
        }
        
        protected MapFieldReflectionAccessor internalGetMapFieldReflection(final int fieldNumber) {
            return this.internalGetMapField(fieldNumber);
        }
        
        @Deprecated
        protected MapField internalGetMapField(final int fieldNumber) {
            throw new IllegalArgumentException("No map fields found in " + this.getClass().getName());
        }
        
        protected MapFieldReflectionAccessor internalGetMutableMapFieldReflection(final int fieldNumber) {
            return this.internalGetMutableMapField(fieldNumber);
        }
        
        @Deprecated
        protected MapField internalGetMutableMapField(final int fieldNumber) {
            throw new IllegalArgumentException("No map fields found in " + this.getClass().getName());
        }
        
        private class BuilderParentImpl implements BuilderParent
        {
            @Override
            public void markDirty() {
                GeneratedMessage.Builder.this.onChanged();
            }
        }
    }
    
    public interface ExtendableMessageOrBuilder<MessageT extends ExtendableMessage<MessageT>> extends MessageOrBuilder
    {
        Message getDefaultInstanceForType();
        
         <T> boolean hasExtension(final ExtensionLite<? extends MessageT, T> extension);
        
        default <T> boolean hasExtension(final Extension<? extends MessageT, T> extension) {
            return this.hasExtension((ExtensionLite<? extends MessageT, T>)extension);
        }
        
        default <T> boolean hasExtension(final GeneratedExtension<? extends MessageT, T> extension) {
            return this.hasExtension((ExtensionLite<? extends MessageT, T>)extension);
        }
        
         <T> int getExtensionCount(final ExtensionLite<? extends MessageT, List<T>> extension);
        
        default <T> int getExtensionCount(final Extension<? extends MessageT, List<T>> extension) {
            return this.getExtensionCount((ExtensionLite<? extends MessageT, List<T>>)extension);
        }
        
        default <T> int getExtensionCount(final GeneratedExtension<MessageT, List<T>> extension) {
            return this.getExtensionCount((ExtensionLite<? extends MessageT, List<T>>)extension);
        }
        
         <T> T getExtension(final ExtensionLite<? extends MessageT, T> extension);
        
        default <T> T getExtension(final Extension<? extends MessageT, T> extension) {
            return this.getExtension((ExtensionLite<? extends MessageT, T>)extension);
        }
        
        default <T> T getExtension(final GeneratedExtension<MessageT, T> extension) {
            return this.getExtension((ExtensionLite<? extends MessageT, T>)extension);
        }
        
         <T> T getExtension(final ExtensionLite<? extends MessageT, List<T>> extension, final int index);
        
        default <T> T getExtension(final Extension<? extends MessageT, List<T>> extension, final int index) {
            return this.getExtension((ExtensionLite<? extends MessageT, List<T>>)extension, index);
        }
        
        default <T> T getExtension(final GeneratedExtension<MessageT, List<T>> extension, final int index) {
            return this.getExtension((ExtensionLite<? extends MessageT, List<T>>)extension, index);
        }
    }
    
    public abstract static class ExtendableMessage<MessageT extends ExtendableMessage<MessageT>> extends GeneratedMessage implements ExtendableMessageOrBuilder<MessageT>
    {
        private static final long serialVersionUID = 1L;
        private final FieldSet<Descriptors.FieldDescriptor> extensions;
        
        protected ExtendableMessage() {
            this.extensions = FieldSet.newFieldSet();
        }
        
        protected ExtendableMessage(final ExtendableBuilder<MessageT, ?> builder) {
            super(builder);
            this.extensions = ((ExtendableBuilder<ExtendableMessage, ExtendableBuilder>)builder).buildExtensions();
        }
        
        public final Iterator<FieldEntry> extensionsIterator() {
            return new FieldEntryIterator(this.extensions);
        }
        
        private void verifyExtensionContainingType(final Descriptors.FieldDescriptor descriptor) {
            if (descriptor.getContainingType() != this.getDescriptorForType()) {
                throw new IllegalArgumentException("Extension is for type \"" + descriptor.getContainingType().getFullName() + "\" which does not match message type \"" + this.getDescriptorForType().getFullName() + "\".");
            }
        }
        
        @Override
        public final <T> boolean hasExtension(final ExtensionLite<? extends MessageT, T> extensionLite) {
            final Extension<MessageT, T> extension = (Extension<MessageT, T>)checkNotLite((ExtensionLite<? extends ExtendableMessage, Object>)extensionLite);
            final Descriptors.FieldDescriptor descriptor = extension.getDescriptor();
            this.verifyExtensionContainingType(descriptor);
            return this.extensions.hasField(descriptor);
        }
        
        @Override
        public final <T> int getExtensionCount(final ExtensionLite<? extends MessageT, List<T>> extensionLite) {
            final Extension<MessageT, List<T>> extension = (Extension<MessageT, List<T>>)checkNotLite((ExtensionLite<? extends ExtendableMessage, Object>)extensionLite);
            final Descriptors.FieldDescriptor descriptor = extension.getDescriptor();
            this.verifyExtensionContainingType(descriptor);
            return this.extensions.getRepeatedFieldCount(descriptor);
        }
        
        @Override
        public final <T> T getExtension(final ExtensionLite<? extends MessageT, T> extensionLite) {
            final Extension<MessageT, T> extension = (Extension<MessageT, T>)checkNotLite((ExtensionLite<? extends ExtendableMessage, Object>)extensionLite);
            final Descriptors.FieldDescriptor descriptor = extension.getDescriptor();
            this.verifyExtensionContainingType(descriptor);
            final Object value = this.extensions.getField(descriptor);
            T result = null;
            if (value == null) {
                if (descriptor.isRepeated()) {
                    result = (T)ProtobufArrayList.emptyList();
                }
                else if (descriptor.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
                    result = (T)extension.getMessageDefaultInstance();
                }
                else {
                    result = (T)extension.fromReflectionType(descriptor.getDefaultValue());
                }
            }
            else {
                result = (T)extension.fromReflectionType(value);
            }
            if (this.extensions.lazyFieldCorrupted(descriptor)) {
                this.setMemoizedSerializedSize(-1);
            }
            return result;
        }
        
        @Override
        public final <T> T getExtension(final ExtensionLite<? extends MessageT, List<T>> extensionLite, final int index) {
            final Extension<MessageT, List<T>> extension = (Extension<MessageT, List<T>>)checkNotLite((ExtensionLite<? extends ExtendableMessage, Object>)extensionLite);
            final Descriptors.FieldDescriptor descriptor = extension.getDescriptor();
            this.verifyExtensionContainingType(descriptor);
            return (T)extension.singularFromReflectionType(this.extensions.getRepeatedField(descriptor, index));
        }
        
        protected boolean extensionsAreInitialized() {
            return this.extensions.isInitialized();
        }
        
        @Override
        public boolean isInitialized() {
            return super.isInitialized() && this.extensionsAreInitialized();
        }
        
        @Override
        protected void makeExtensionsImmutable() {
            GeneratedMessage.warnPre22Gencode(this.getClass());
            this.extensions.makeImmutable();
        }
        
        @Deprecated
        protected ExtensionWriter newExtensionWriter() {
            return new ExtensionWriter(false);
        }
        
        protected ExtensionSerializer newExtensionSerializer() {
            if (this.extensions.isEmpty()) {
                return NoOpExtensionSerializer.INSTANCE;
            }
            return new ExtensionWriter(false);
        }
        
        protected ExtensionWriter newMessageSetExtensionWriter() {
            return new ExtensionWriter(true);
        }
        
        protected ExtensionSerializer newMessageSetExtensionSerializer() {
            if (this.extensions.isEmpty()) {
                return NoOpExtensionSerializer.INSTANCE;
            }
            return new ExtensionWriter(true);
        }
        
        protected int extensionsSerializedSize() {
            return this.extensions.getSerializedSize();
        }
        
        protected int extensionsSerializedSizeAsMessageSet() {
            return this.extensions.getMessageSetSerializedSize();
        }
        
        protected Map<Descriptors.FieldDescriptor, Object> getExtensionFields() {
            return this.extensions.getAllFields();
        }
        
        @Override
        public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
            final Map<Descriptors.FieldDescriptor, Object> result = GeneratedMessage.this.getAllFieldsMutable(false);
            result.putAll(this.getExtensionFields());
            return Collections.unmodifiableMap((Map<? extends Descriptors.FieldDescriptor, ?>)result);
        }
        
        public Map<Descriptors.FieldDescriptor, Object> getAllFieldsRaw() {
            final Map<Descriptors.FieldDescriptor, Object> result = GeneratedMessage.this.getAllFieldsMutable(false);
            result.putAll(this.getExtensionFields());
            return Collections.unmodifiableMap((Map<? extends Descriptors.FieldDescriptor, ?>)result);
        }
        
        @Override
        public boolean hasField(final Descriptors.FieldDescriptor field) {
            if (field.isExtension()) {
                this.verifyContainingType(field);
                return this.extensions.hasField(field);
            }
            return super.hasField(field);
        }
        
        @Override
        public Object getField(final Descriptors.FieldDescriptor field) {
            if (!field.isExtension()) {
                return super.getField(field);
            }
            this.verifyContainingType(field);
            final Object value = this.extensions.getField(field);
            if (value != null) {
                return value;
            }
            if (field.isRepeated()) {
                return Collections.emptyList();
            }
            if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
                return DynamicMessage.getDefaultInstance(field.getMessageType());
            }
            return field.getDefaultValue();
        }
        
        @Override
        public int getRepeatedFieldCount(final Descriptors.FieldDescriptor field) {
            if (field.isExtension()) {
                this.verifyContainingType(field);
                return this.extensions.getRepeatedFieldCount(field);
            }
            return super.getRepeatedFieldCount(field);
        }
        
        @Override
        public Object getRepeatedField(final Descriptors.FieldDescriptor field, final int index) {
            if (field.isExtension()) {
                this.verifyContainingType(field);
                return this.extensions.getRepeatedField(field, index);
            }
            return super.getRepeatedField(field, index);
        }
        
        private void verifyContainingType(final Descriptors.FieldDescriptor field) {
            if (field.getContainingType() != this.getDescriptorForType()) {
                throw new IllegalArgumentException("FieldDescriptor does not match message type.");
            }
        }
        
        private static final class NoOpExtensionSerializer implements ExtensionSerializer
        {
            private static final NoOpExtensionSerializer INSTANCE;
            
            @Override
            public void writeUntil(final int end, final CodedOutputStream output) {
            }
            
            static {
                INSTANCE = new NoOpExtensionSerializer();
            }
        }
        
        protected class ExtensionWriter implements ExtensionSerializer
        {
            private final Iterator<Map.Entry<Descriptors.FieldDescriptor, Object>> iter;
            private Map.Entry<Descriptors.FieldDescriptor, Object> next;
            private final boolean messageSetWireFormat;
            
            protected ExtensionWriter(final boolean messageSetWireFormat) {
                this.iter = ExtendableMessage.this.extensions.iterator();
                if (this.iter.hasNext()) {
                    this.next = this.iter.next();
                }
                this.messageSetWireFormat = messageSetWireFormat;
            }
            
            @Override
            public void writeUntil(final int end, final CodedOutputStream output) throws IOException {
                while (this.next != null && this.next.getKey().getNumber() < end) {
                    final Descriptors.FieldDescriptor descriptor = this.next.getKey();
                    if (this.messageSetWireFormat && descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE && !descriptor.isRepeated()) {
                        if (this.next instanceof LazyField.LazyEntry) {
                            output.writeRawMessageSetExtension(descriptor.getNumber(), ((LazyField.LazyEntry)this.next).getField().toByteString());
                        }
                        else {
                            output.writeMessageSetExtension(descriptor.getNumber(), this.next.getValue());
                        }
                    }
                    else {
                        FieldSet.writeField(descriptor, this.next.getValue(), output);
                    }
                    if (this.iter.hasNext()) {
                        this.next = this.iter.next();
                    }
                    else {
                        this.next = null;
                    }
                }
            }
        }
        
        public static final class FieldEntry
        {
            private final Descriptors.FieldDescriptor descriptor;
            private final Object value;
            
            public Descriptors.FieldDescriptor getDescriptor() {
                return this.descriptor;
            }
            
            public Object getValue() {
                return this.value;
            }
            
            FieldEntry(final Descriptors.FieldDescriptor descriptor, final Object value) {
                this.descriptor = descriptor;
                this.value = value;
            }
        }
        
        private static final class FieldEntryIterator implements Iterator<FieldEntry>
        {
            private final Iterator<Map.Entry<Descriptors.FieldDescriptor, Object>> iter;
            
            FieldEntryIterator(final FieldSet<Descriptors.FieldDescriptor> fieldSet) {
                this.iter = fieldSet.iterator();
            }
            
            @Override
            public final boolean hasNext() {
                return this.iter.hasNext();
            }
            
            @Override
            public final FieldEntry next() {
                final Map.Entry<Descriptors.FieldDescriptor, Object> entry = this.iter.next();
                return new FieldEntry(entry.getKey(), entry.getValue());
            }
        }
        
        protected interface ExtensionSerializer
        {
            void writeUntil(final int end, final CodedOutputStream output) throws IOException;
        }
    }
    
    public abstract static class ExtendableBuilder<MessageT extends ExtendableMessage<MessageT>, BuilderT extends ExtendableBuilder<MessageT, BuilderT>> extends Builder<BuilderT> implements ExtendableMessageOrBuilder<MessageT>
    {
        private FieldSet.Builder<Descriptors.FieldDescriptor> extensions;
        
        protected ExtendableBuilder() {
        }
        
        protected ExtendableBuilder(final BuilderParent parent) {
            super(parent);
        }
        
        void internalSetExtensionSet(final FieldSet<Descriptors.FieldDescriptor> extensions) {
            this.extensions = FieldSet.Builder.fromFieldSet(extensions);
        }
        
        @Override
        public BuilderT clear() {
            this.extensions = null;
            return super.clear();
        }
        
        private void ensureExtensionsIsMutable() {
            if (this.extensions == null) {
                this.extensions = FieldSet.newBuilder();
            }
        }
        
        private void verifyExtensionContainingType(final Extension<MessageT, ?> extension) {
            if (extension.getDescriptor().getContainingType() != this.getDescriptorForType()) {
                throw new IllegalArgumentException("Extension is for type \"" + extension.getDescriptor().getContainingType().getFullName() + "\" which does not match message type \"" + this.getDescriptorForType().getFullName() + "\".");
            }
        }
        
        @Override
        public final <T> boolean hasExtension(final ExtensionLite<? extends MessageT, T> extensionLite) {
            final Extension<MessageT, T> extension = (Extension<MessageT, T>)checkNotLite((ExtensionLite<? extends ExtendableMessage, Object>)extensionLite);
            this.verifyExtensionContainingType(extension);
            return this.extensions != null && this.extensions.hasField(extension.getDescriptor());
        }
        
        @Override
        public final <T> int getExtensionCount(final ExtensionLite<? extends MessageT, List<T>> extensionLite) {
            final Extension<MessageT, List<T>> extension = (Extension<MessageT, List<T>>)checkNotLite((ExtensionLite<? extends ExtendableMessage, Object>)extensionLite);
            this.verifyExtensionContainingType(extension);
            final Descriptors.FieldDescriptor descriptor = extension.getDescriptor();
            return (this.extensions == null) ? 0 : this.extensions.getRepeatedFieldCount(descriptor);
        }
        
        @Override
        public final <T> T getExtension(final ExtensionLite<? extends MessageT, T> extensionLite) {
            final Extension<MessageT, T> extension = (Extension<MessageT, T>)checkNotLite((ExtensionLite<? extends ExtendableMessage, Object>)extensionLite);
            this.verifyExtensionContainingType(extension);
            final Descriptors.FieldDescriptor descriptor = extension.getDescriptor();
            final Object value = (this.extensions == null) ? null : this.extensions.getField(descriptor);
            if (value != null) {
                return (T)extension.fromReflectionType(value);
            }
            if (descriptor.isRepeated()) {
                return (T)Collections.emptyList();
            }
            if (descriptor.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
                return (T)extension.getMessageDefaultInstance();
            }
            return (T)extension.fromReflectionType(descriptor.getDefaultValue());
        }
        
        @Override
        public final <T> T getExtension(final ExtensionLite<? extends MessageT, List<T>> extensionLite, final int index) {
            final Extension<MessageT, List<T>> extension = (Extension<MessageT, List<T>>)checkNotLite((ExtensionLite<? extends ExtendableMessage, Object>)extensionLite);
            this.verifyExtensionContainingType(extension);
            final Descriptors.FieldDescriptor descriptor = extension.getDescriptor();
            if (this.extensions == null) {
                throw new IndexOutOfBoundsException();
            }
            return (T)extension.singularFromReflectionType(this.extensions.getRepeatedField(descriptor, index));
        }
        
        public final <T> BuilderT setExtension(final Extension<? extends MessageT, T> extension, final T value) {
            return this.setExtension((ExtensionLite<? extends MessageT, T>)extension, value);
        }
        
        public final <T> BuilderT setExtension(final ExtensionLite<? extends MessageT, T> extensionLite, final T value) {
            final Extension<MessageT, T> extension = (Extension<MessageT, T>)checkNotLite((ExtensionLite<? extends ExtendableMessage, Object>)extensionLite);
            this.verifyExtensionContainingType(extension);
            this.ensureExtensionsIsMutable();
            final Descriptors.FieldDescriptor descriptor = extension.getDescriptor();
            this.extensions.setField(descriptor, extension.toReflectionType(value));
            this.onChanged();
            return (BuilderT)this;
        }
        
        public final <T> BuilderT setExtension(final Extension<? extends MessageT, List<T>> extension, final int index, final T value) {
            return this.setExtension((ExtensionLite<? extends MessageT, List<T>>)extension, index, value);
        }
        
        public final <T> BuilderT setExtension(final ExtensionLite<? extends MessageT, List<T>> extensionLite, final int index, final T value) {
            final Extension<MessageT, List<T>> extension = (Extension<MessageT, List<T>>)checkNotLite((ExtensionLite<? extends ExtendableMessage, Object>)extensionLite);
            this.verifyExtensionContainingType(extension);
            this.ensureExtensionsIsMutable();
            final Descriptors.FieldDescriptor descriptor = extension.getDescriptor();
            this.extensions.setRepeatedField(descriptor, index, extension.singularToReflectionType(value));
            this.onChanged();
            return (BuilderT)this;
        }
        
        public final <T> BuilderT addExtension(final Extension<? extends MessageT, List<T>> extension, final T value) {
            return this.addExtension((ExtensionLite<? extends MessageT, List<T>>)extension, value);
        }
        
        public final <T> BuilderT addExtension(final ExtensionLite<? extends MessageT, List<T>> extensionLite, final T value) {
            final Extension<MessageT, List<T>> extension = (Extension<MessageT, List<T>>)checkNotLite((ExtensionLite<? extends ExtendableMessage, Object>)extensionLite);
            this.verifyExtensionContainingType(extension);
            this.ensureExtensionsIsMutable();
            final Descriptors.FieldDescriptor descriptor = extension.getDescriptor();
            this.extensions.addRepeatedField(descriptor, extension.singularToReflectionType(value));
            this.onChanged();
            return (BuilderT)this;
        }
        
        public final <T> BuilderT clearExtension(final Extension<? extends MessageT, T> extension) {
            return this.clearExtension((ExtensionLite<? extends MessageT, T>)extension);
        }
        
        public final <T> BuilderT clearExtension(final ExtensionLite<? extends MessageT, T> extensionLite) {
            final Extension<MessageT, T> extension = (Extension<MessageT, T>)checkNotLite((ExtensionLite<? extends ExtendableMessage, Object>)extensionLite);
            this.verifyExtensionContainingType(extension);
            this.ensureExtensionsIsMutable();
            this.extensions.clearField(extension.getDescriptor());
            this.onChanged();
            return (BuilderT)this;
        }
        
        protected boolean extensionsAreInitialized() {
            return this.extensions == null || this.extensions.isInitialized();
        }
        
        private FieldSet<Descriptors.FieldDescriptor> buildExtensions() {
            return (this.extensions == null) ? FieldSet.emptySet() : this.extensions.buildPartial();
        }
        
        @Override
        public boolean isInitialized() {
            return super.isInitialized() && this.extensionsAreInitialized();
        }
        
        @Override
        public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
            final Map<Descriptors.FieldDescriptor, Object> result = ((Builder<Builder>)this).getAllFieldsMutable();
            if (this.extensions != null) {
                result.putAll(this.extensions.getAllFields());
            }
            return Collections.unmodifiableMap((Map<? extends Descriptors.FieldDescriptor, ?>)result);
        }
        
        @Override
        public Object getField(final Descriptors.FieldDescriptor field) {
            if (!field.isExtension()) {
                return super.getField(field);
            }
            this.verifyContainingType(field);
            final Object value = (this.extensions == null) ? null : this.extensions.getField(field);
            if (value != null) {
                return value;
            }
            if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
                return DynamicMessage.getDefaultInstance(field.getMessageType());
            }
            return field.getDefaultValue();
        }
        
        @Override
        public Message.Builder getFieldBuilder(final Descriptors.FieldDescriptor field) {
            if (!field.isExtension()) {
                return super.getFieldBuilder(field);
            }
            this.verifyContainingType(field);
            if (field.getJavaType() != Descriptors.FieldDescriptor.JavaType.MESSAGE) {
                throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type.");
            }
            this.ensureExtensionsIsMutable();
            final Object value = this.extensions.getFieldAllowBuilders(field);
            if (value == null) {
                final Message.Builder builder = DynamicMessage.newBuilder(field.getMessageType());
                this.extensions.setField(field, builder);
                this.onChanged();
                return builder;
            }
            if (value instanceof Message.Builder) {
                return (Message.Builder)value;
            }
            if (value instanceof Message) {
                final Message.Builder builder = ((Message)value).toBuilder();
                this.extensions.setField(field, builder);
                this.onChanged();
                return builder;
            }
            throw new UnsupportedOperationException("getRepeatedFieldBuilder() called on a non-Message type.");
        }
        
        @Override
        public int getRepeatedFieldCount(final Descriptors.FieldDescriptor field) {
            if (field.isExtension()) {
                this.verifyContainingType(field);
                return (this.extensions == null) ? 0 : this.extensions.getRepeatedFieldCount(field);
            }
            return super.getRepeatedFieldCount(field);
        }
        
        @Override
        public Object getRepeatedField(final Descriptors.FieldDescriptor field, final int index) {
            if (!field.isExtension()) {
                return super.getRepeatedField(field, index);
            }
            this.verifyContainingType(field);
            if (this.extensions == null) {
                throw new IndexOutOfBoundsException();
            }
            return this.extensions.getRepeatedField(field, index);
        }
        
        @Override
        public Message.Builder getRepeatedFieldBuilder(final Descriptors.FieldDescriptor field, final int index) {
            if (!field.isExtension()) {
                return super.getRepeatedFieldBuilder(field, index);
            }
            this.verifyContainingType(field);
            this.ensureExtensionsIsMutable();
            if (field.getJavaType() != Descriptors.FieldDescriptor.JavaType.MESSAGE) {
                throw new UnsupportedOperationException("getRepeatedFieldBuilder() called on a non-Message type.");
            }
            final Object value = this.extensions.getRepeatedFieldAllowBuilders(field, index);
            if (value instanceof Message.Builder) {
                return (Message.Builder)value;
            }
            if (value instanceof Message) {
                final Message.Builder builder = ((Message)value).toBuilder();
                this.extensions.setRepeatedField(field, index, builder);
                this.onChanged();
                return builder;
            }
            throw new UnsupportedOperationException("getRepeatedFieldBuilder() called on a non-Message type.");
        }
        
        @Override
        public boolean hasField(final Descriptors.FieldDescriptor field) {
            if (field.isExtension()) {
                this.verifyContainingType(field);
                return this.extensions != null && this.extensions.hasField(field);
            }
            return super.hasField(field);
        }
        
        @Override
        public BuilderT setField(final Descriptors.FieldDescriptor field, final Object value) {
            if (field.isExtension()) {
                this.verifyContainingType(field);
                this.ensureExtensionsIsMutable();
                this.extensions.setField(field, value);
                this.onChanged();
                return (BuilderT)this;
            }
            return super.setField(field, value);
        }
        
        @Override
        public BuilderT clearField(final Descriptors.FieldDescriptor field) {
            if (field.isExtension()) {
                this.verifyContainingType(field);
                this.ensureExtensionsIsMutable();
                this.extensions.clearField(field);
                this.onChanged();
                return (BuilderT)this;
            }
            return super.clearField(field);
        }
        
        @Override
        public BuilderT setRepeatedField(final Descriptors.FieldDescriptor field, final int index, final Object value) {
            if (field.isExtension()) {
                this.verifyContainingType(field);
                this.ensureExtensionsIsMutable();
                this.extensions.setRepeatedField(field, index, value);
                this.onChanged();
                return (BuilderT)this;
            }
            return super.setRepeatedField(field, index, value);
        }
        
        @Override
        public BuilderT addRepeatedField(final Descriptors.FieldDescriptor field, final Object value) {
            if (field.isExtension()) {
                this.verifyContainingType(field);
                this.ensureExtensionsIsMutable();
                this.extensions.addRepeatedField(field, value);
                this.onChanged();
                return (BuilderT)this;
            }
            return super.addRepeatedField(field, value);
        }
        
        @Override
        public Message.Builder newBuilderForField(final Descriptors.FieldDescriptor field) {
            if (field.isExtension()) {
                return DynamicMessage.newBuilder(field.getMessageType());
            }
            return super.newBuilderForField(field);
        }
        
        protected void mergeExtensionFields(final ExtendableMessage<?> other) {
            if (((ExtendableMessage<ExtendableMessage>)other).extensions != null) {
                this.ensureExtensionsIsMutable();
                this.extensions.mergeFrom(((ExtendableMessage<ExtendableMessage>)other).extensions);
                this.onChanged();
            }
        }
        
        @Override
        protected boolean parseUnknownField(final CodedInputStream input, final ExtensionRegistryLite extensionRegistry, final int tag) throws IOException {
            this.ensureExtensionsIsMutable();
            return MessageReflection.mergeFieldFrom(input, input.shouldDiscardUnknownFields() ? null : this.getUnknownFieldSetBuilder(), extensionRegistry, this.getDescriptorForType(), new MessageReflection.ExtensionBuilderAdapter(this.extensions), tag);
        }
        
        private void verifyContainingType(final Descriptors.FieldDescriptor field) {
            if (field.getContainingType() != this.getDescriptorForType()) {
                throw new IllegalArgumentException("FieldDescriptor does not match message type.");
            }
        }
    }
    
    private abstract static class CachedDescriptorRetriever implements ExtensionDescriptorRetriever
    {
        private volatile Descriptors.FieldDescriptor descriptor;
        
        protected abstract Descriptors.FieldDescriptor loadDescriptor();
        
        @Override
        public Descriptors.FieldDescriptor getDescriptor() {
            if (this.descriptor == null) {
                final Descriptors.FieldDescriptor tmpDescriptor = this.loadDescriptor();
                synchronized (this) {
                    if (this.descriptor == null) {
                        this.descriptor = tmpDescriptor;
                    }
                }
            }
            return this.descriptor;
        }
    }
    
    public static class GeneratedExtension<ContainingT extends Message, T> extends Extension<ContainingT, T>
    {
        private ExtensionDescriptorRetriever descriptorRetriever;
        private final Class<?> singularType;
        private final Message messageDefaultInstance;
        private final Method enumValueOf;
        private final Method enumGetValueDescriptor;
        private final ExtensionType extensionType;
        
        GeneratedExtension(final ExtensionDescriptorRetriever descriptorRetriever, final Class<?> singularType, final Message messageDefaultInstance, final ExtensionType extensionType) {
            if (Message.class.isAssignableFrom(singularType) && !singularType.isInstance(messageDefaultInstance)) {
                throw new IllegalArgumentException("Bad messageDefaultInstance for " + singularType.getName());
            }
            this.descriptorRetriever = descriptorRetriever;
            this.singularType = singularType;
            this.messageDefaultInstance = messageDefaultInstance;
            if (ProtocolMessageEnum.class.isAssignableFrom(singularType)) {
                this.enumValueOf = getMethodOrDie(singularType, "valueOf", (Class<?>[])new Class[] { Descriptors.EnumValueDescriptor.class });
                this.enumGetValueDescriptor = getMethodOrDie(singularType, "getValueDescriptor", (Class<?>[])new Class[0]);
            }
            else {
                this.enumValueOf = null;
                this.enumGetValueDescriptor = null;
            }
            this.extensionType = extensionType;
        }
        
        public void internalInit(final Descriptors.FieldDescriptor descriptor) {
            if (this.descriptorRetriever != null) {
                throw new IllegalStateException("Already initialized.");
            }
            this.descriptorRetriever = new ExtensionDescriptorRetriever() {
                @Override
                public Descriptors.FieldDescriptor getDescriptor() {
                    return descriptor;
                }
            };
        }
        
        @Override
        public Descriptors.FieldDescriptor getDescriptor() {
            if (this.descriptorRetriever == null) {
                throw new IllegalStateException("getDescriptor() called before internalInit()");
            }
            return this.descriptorRetriever.getDescriptor();
        }
        
        @Override
        public Message getMessageDefaultInstance() {
            return this.messageDefaultInstance;
        }
        
        @Override
        protected ExtensionType getExtensionType() {
            return this.extensionType;
        }
        
        @Override
        protected Object fromReflectionType(final Object value) {
            final Descriptors.FieldDescriptor descriptor = this.getDescriptor();
            if (!descriptor.isRepeated()) {
                return this.singularFromReflectionType(value);
            }
            if (descriptor.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE || descriptor.getJavaType() == Descriptors.FieldDescriptor.JavaType.ENUM) {
                final ProtobufArrayList<Object> result = new ProtobufArrayList<Object>();
                result.ensureCapacity(((List)value).size());
                for (final Object element : (List)value) {
                    result.add(this.singularFromReflectionType(element));
                }
                result.makeImmutable();
                return result;
            }
            return value;
        }
        
        @Override
        protected Object singularFromReflectionType(final Object value) {
            final Descriptors.FieldDescriptor descriptor = this.getDescriptor();
            switch (descriptor.getJavaType()) {
                case MESSAGE: {
                    if (this.singularType.isInstance(value)) {
                        return value;
                    }
                    return this.messageDefaultInstance.newBuilderForType().mergeFrom((Message)value).build();
                }
                case ENUM: {
                    return invokeOrDie(this.enumValueOf, null, new Object[] { value });
                }
                default: {
                    return value;
                }
            }
        }
        
        @Override
        protected Object toReflectionType(final Object value) {
            final Descriptors.FieldDescriptor descriptor = this.getDescriptor();
            if (!descriptor.isRepeated()) {
                return this.singularToReflectionType(value);
            }
            if (descriptor.getJavaType() == Descriptors.FieldDescriptor.JavaType.ENUM) {
                final List<Object> result = new ArrayList<Object>();
                for (final Object element : (List)value) {
                    result.add(this.singularToReflectionType(element));
                }
                return result;
            }
            return value;
        }
        
        @Override
        protected Object singularToReflectionType(final Object value) {
            final Descriptors.FieldDescriptor descriptor = this.getDescriptor();
            switch (descriptor.getJavaType()) {
                case ENUM: {
                    return invokeOrDie(this.enumGetValueDescriptor, value, new Object[0]);
                }
                default: {
                    return value;
                }
            }
        }
        
        @Override
        public int getNumber() {
            return this.getDescriptor().getNumber();
        }
        
        @Override
        public WireFormat.FieldType getLiteType() {
            return this.getDescriptor().getLiteType();
        }
        
        @Override
        public boolean isRepeated() {
            return this.getDescriptor().isRepeated();
        }
        
        @Override
        public T getDefaultValue() {
            if (this.isRepeated()) {
                return (T)Collections.emptyList();
            }
            if (this.getDescriptor().getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
                return (T)this.messageDefaultInstance;
            }
            return (T)this.singularFromReflectionType(this.getDescriptor().getDefaultValue());
        }
    }
    
    public static class FieldAccessorTable
    {
        private final Descriptors.Descriptor descriptor;
        private final FieldAccessor[] fields;
        private String[] camelCaseNames;
        private final OneofAccessor[] oneofs;
        private volatile boolean initialized;
        
        public FieldAccessorTable(final Descriptors.Descriptor descriptor, final String[] camelCaseNames, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder<?>> builderClass) {
            this(descriptor, camelCaseNames);
            this.ensureFieldAccessorsInitialized(messageClass, builderClass);
        }
        
        public FieldAccessorTable(final Descriptors.Descriptor descriptor, final String[] camelCaseNames) {
            this.descriptor = descriptor;
            this.camelCaseNames = camelCaseNames;
            this.fields = new FieldAccessor[descriptor.getFieldCount()];
            this.oneofs = new OneofAccessor[descriptor.getOneofCount()];
            this.initialized = false;
        }
        
        @CanIgnoreReturnValue
        public FieldAccessorTable ensureFieldAccessorsInitialized(final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder<?>> builderClass) {
            if (this.initialized) {
                return this;
            }
            synchronized (this) {
                if (this.initialized) {
                    return this;
                }
                final int fieldsSize = this.fields.length;
                for (int i = 0; i < fieldsSize; ++i) {
                    final Descriptors.FieldDescriptor field = this.descriptor.getField(i);
                    String containingOneofCamelCaseName = null;
                    if (field.getContainingOneof() != null) {
                        final int index = fieldsSize + field.getContainingOneof().getIndex();
                        if (index < this.camelCaseNames.length) {
                            containingOneofCamelCaseName = this.camelCaseNames[index];
                        }
                    }
                    if (field.isRepeated()) {
                        if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
                            if (field.isMapField()) {
                                this.fields[i] = new MapFieldAccessor(field, messageClass);
                            }
                            else {
                                this.fields[i] = new RepeatedMessageFieldAccessor(this.camelCaseNames[i], messageClass, builderClass);
                            }
                        }
                        else if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.ENUM) {
                            this.fields[i] = new RepeatedEnumFieldAccessor(field, this.camelCaseNames[i], messageClass, builderClass);
                        }
                        else {
                            this.fields[i] = new RepeatedFieldAccessor(this.camelCaseNames[i], messageClass, builderClass);
                        }
                    }
                    else if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
                        this.fields[i] = new SingularMessageFieldAccessor(field, this.camelCaseNames[i], messageClass, builderClass, containingOneofCamelCaseName);
                    }
                    else if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.ENUM) {
                        this.fields[i] = new SingularEnumFieldAccessor(field, this.camelCaseNames[i], messageClass, builderClass, containingOneofCamelCaseName);
                    }
                    else if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.STRING) {
                        this.fields[i] = new SingularStringFieldAccessor(field, this.camelCaseNames[i], messageClass, builderClass, containingOneofCamelCaseName);
                    }
                    else {
                        this.fields[i] = new SingularFieldAccessor(field, this.camelCaseNames[i], messageClass, builderClass, containingOneofCamelCaseName);
                    }
                }
                for (int i = 0; i < this.descriptor.getOneofCount(); ++i) {
                    if (i < this.descriptor.getRealOneofCount()) {
                        this.oneofs[i] = new RealOneofAccessor(this.descriptor, this.camelCaseNames[i + fieldsSize], messageClass, builderClass);
                    }
                    else {
                        this.oneofs[i] = new SyntheticOneofAccessor(this.descriptor, i);
                    }
                }
                this.initialized = true;
                this.camelCaseNames = null;
                return this;
            }
        }
        
        private FieldAccessor getField(final Descriptors.FieldDescriptor field) {
            if (field.getContainingType() != this.descriptor) {
                throw new IllegalArgumentException("FieldDescriptor does not match message type.");
            }
            if (field.isExtension()) {
                throw new IllegalArgumentException("This type does not have extensions.");
            }
            return this.fields[field.getIndex()];
        }
        
        private OneofAccessor getOneof(final Descriptors.OneofDescriptor oneof) {
            if (oneof.getContainingType() != this.descriptor) {
                throw new IllegalArgumentException("OneofDescriptor does not match message type.");
            }
            return this.oneofs[oneof.getIndex()];
        }
        
        private static class RealOneofAccessor implements OneofAccessor
        {
            private final Descriptors.Descriptor descriptor;
            private final Method caseMethod;
            private final Method caseMethodBuilder;
            private final Method clearMethod;
            
            RealOneofAccessor(final Descriptors.Descriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder<?>> builderClass) {
                this.descriptor = descriptor;
                this.caseMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Case", (Class<?>[])new Class[0]);
                this.caseMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Case", (Class<?>[])new Class[0]);
                this.clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName, (Class<?>[])new Class[0]);
            }
            
            @Override
            public boolean has(final GeneratedMessage message) {
                return ((Internal.EnumLite)invokeOrDie(this.caseMethod, message, new Object[0])).getNumber() != 0;
            }
            
            @Override
            public boolean has(final Builder<?> builder) {
                return ((Internal.EnumLite)invokeOrDie(this.caseMethodBuilder, builder, new Object[0])).getNumber() != 0;
            }
            
            @Override
            public Descriptors.FieldDescriptor get(final GeneratedMessage message) {
                final int fieldNumber = ((Internal.EnumLite)invokeOrDie(this.caseMethod, message, new Object[0])).getNumber();
                if (fieldNumber > 0) {
                    return this.descriptor.findFieldByNumber(fieldNumber);
                }
                return null;
            }
            
            @Override
            public Descriptors.FieldDescriptor get(final Builder<?> builder) {
                final int fieldNumber = ((Internal.EnumLite)invokeOrDie(this.caseMethodBuilder, builder, new Object[0])).getNumber();
                if (fieldNumber > 0) {
                    return this.descriptor.findFieldByNumber(fieldNumber);
                }
                return null;
            }
            
            @Override
            public void clear(final Builder<?> builder) {
                final Object unused = invokeOrDie(this.clearMethod, builder, new Object[0]);
            }
        }
        
        private static class SyntheticOneofAccessor implements OneofAccessor
        {
            private final Descriptors.FieldDescriptor fieldDescriptor;
            
            SyntheticOneofAccessor(final Descriptors.Descriptor descriptor, final int oneofIndex) {
                final Descriptors.OneofDescriptor oneofDescriptor = descriptor.getOneof(oneofIndex);
                this.fieldDescriptor = oneofDescriptor.getField(0);
            }
            
            @Override
            public boolean has(final GeneratedMessage message) {
                return message.hasField(this.fieldDescriptor);
            }
            
            @Override
            public boolean has(final Builder<?> builder) {
                return builder.hasField(this.fieldDescriptor);
            }
            
            @Override
            public Descriptors.FieldDescriptor get(final GeneratedMessage message) {
                return message.hasField(this.fieldDescriptor) ? this.fieldDescriptor : null;
            }
            
            @Override
            public Descriptors.FieldDescriptor get(final Builder<?> builder) {
                return builder.hasField(this.fieldDescriptor) ? this.fieldDescriptor : null;
            }
            
            @Override
            public void clear(final Builder<?> builder) {
                builder.clearField(this.fieldDescriptor);
            }
        }
        
        private static class SingularFieldAccessor implements FieldAccessor
        {
            protected final Class<?> type;
            protected final Descriptors.FieldDescriptor field;
            protected final boolean isOneofField;
            protected final boolean hasHasMethod;
            protected final MethodInvoker invoker;
            
            SingularFieldAccessor(final Descriptors.FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder<?>> builderClass, final String containingOneofCamelCaseName) {
                this.isOneofField = (descriptor.getRealContainingOneof() != null);
                this.hasHasMethod = descriptor.hasPresence();
                final ReflectionInvoker reflectionInvoker = new ReflectionInvoker(camelCaseName, messageClass, builderClass, containingOneofCamelCaseName, this.isOneofField, this.hasHasMethod);
                this.field = descriptor;
                this.type = reflectionInvoker.getMethod.getReturnType();
                this.invoker = getMethodInvoker(reflectionInvoker);
            }
            
            static MethodInvoker getMethodInvoker(final ReflectionInvoker accessor) {
                return accessor;
            }
            
            @Override
            public Object get(final GeneratedMessage message) {
                return this.invoker.get(message);
            }
            
            @Override
            public Object get(final Builder<?> builder) {
                return this.invoker.get(builder);
            }
            
            @Override
            public Object getRaw(final GeneratedMessage message) {
                return this.get(message);
            }
            
            @Override
            public void set(final Builder<?> builder, final Object value) {
                this.invoker.set(builder, value);
            }
            
            @Override
            public Object getRepeated(final GeneratedMessage message, final int index) {
                throw new UnsupportedOperationException("getRepeatedField() called on a singular field.");
            }
            
            @Override
            public Object getRepeated(final Builder<?> builder, final int index) {
                throw new UnsupportedOperationException("getRepeatedField() called on a singular field.");
            }
            
            @Override
            public void setRepeated(final Builder<?> builder, final int index, final Object value) {
                throw new UnsupportedOperationException("setRepeatedField() called on a singular field.");
            }
            
            @Override
            public void addRepeated(final Builder<?> builder, final Object value) {
                throw new UnsupportedOperationException("addRepeatedField() called on a singular field.");
            }
            
            @Override
            public boolean has(final GeneratedMessage message) {
                if (this.hasHasMethod) {
                    return this.invoker.has(message);
                }
                if (this.isOneofField) {
                    return this.invoker.getOneofFieldNumber(message) == this.field.getNumber();
                }
                return !this.get(message).equals(this.field.getDefaultValue());
            }
            
            @Override
            public boolean has(final Builder<?> builder) {
                if (this.hasHasMethod) {
                    return this.invoker.has(builder);
                }
                if (this.isOneofField) {
                    return this.invoker.getOneofFieldNumber(builder) == this.field.getNumber();
                }
                return !this.get(builder).equals(this.field.getDefaultValue());
            }
            
            @Override
            public int getRepeatedCount(final GeneratedMessage message) {
                throw new UnsupportedOperationException("getRepeatedFieldSize() called on a singular field.");
            }
            
            @Override
            public int getRepeatedCount(final Builder<?> builder) {
                throw new UnsupportedOperationException("getRepeatedFieldSize() called on a singular field.");
            }
            
            @Override
            public void clear(final Builder<?> builder) {
                this.invoker.clear(builder);
            }
            
            @Override
            public Message.Builder newBuilder() {
                throw new UnsupportedOperationException("newBuilderForField() called on a non-Message type.");
            }
            
            @Override
            public Message.Builder getBuilder(final Builder<?> builder) {
                throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type.");
            }
            
            @Override
            public Message.Builder getRepeatedBuilder(final Builder<?> builder, final int index) {
                throw new UnsupportedOperationException("getRepeatedFieldBuilder() called on a non-Message type.");
            }
            
            private static final class ReflectionInvoker implements MethodInvoker
            {
                private final Method getMethod;
                private final Method getMethodBuilder;
                private final Method setMethod;
                private final Method hasMethod;
                private final Method hasMethodBuilder;
                private final Method clearMethod;
                private final Method caseMethod;
                private final Method caseMethodBuilder;
                
                ReflectionInvoker(final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder<?>> builderClass, final String containingOneofCamelCaseName, final boolean isOneofField, final boolean hasHasMethod) {
                    this.getMethod = getMethodOrDie(messageClass, "get" + camelCaseName, (Class<?>[])new Class[0]);
                    this.getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName, (Class<?>[])new Class[0]);
                    final Class<?> type = this.getMethod.getReturnType();
                    this.setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, (Class<?>[])new Class[] { type });
                    this.hasMethod = (hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName, (Class<?>[])new Class[0]) : null);
                    this.hasMethodBuilder = (hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName, (Class<?>[])new Class[0]) : null);
                    this.clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName, (Class<?>[])new Class[0]);
                    this.caseMethod = (isOneofField ? getMethodOrDie(messageClass, "get" + containingOneofCamelCaseName + "Case", (Class<?>[])new Class[0]) : null);
                    this.caseMethodBuilder = (isOneofField ? getMethodOrDie(builderClass, "get" + containingOneofCamelCaseName + "Case", (Class<?>[])new Class[0]) : null);
                }
                
                @Override
                public Object get(final GeneratedMessage message) {
                    return invokeOrDie(this.getMethod, message, new Object[0]);
                }
                
                @Override
                public Object get(final Builder<?> builder) {
                    return invokeOrDie(this.getMethodBuilder, builder, new Object[0]);
                }
                
                @Override
                public int getOneofFieldNumber(final GeneratedMessage message) {
                    return ((Internal.EnumLite)invokeOrDie(this.caseMethod, message, new Object[0])).getNumber();
                }
                
                @Override
                public int getOneofFieldNumber(final Builder<?> builder) {
                    return ((Internal.EnumLite)invokeOrDie(this.caseMethodBuilder, builder, new Object[0])).getNumber();
                }
                
                @Override
                public void set(final Builder<?> builder, final Object value) {
                    final Object unused = invokeOrDie(this.setMethod, builder, new Object[] { value });
                }
                
                @Override
                public boolean has(final GeneratedMessage message) {
                    return (boolean)invokeOrDie(this.hasMethod, message, new Object[0]);
                }
                
                @Override
                public boolean has(final Builder<?> builder) {
                    return (boolean)invokeOrDie(this.hasMethodBuilder, builder, new Object[0]);
                }
                
                @Override
                public void clear(final Builder<?> builder) {
                    final Object unused = invokeOrDie(this.clearMethod, builder, new Object[0]);
                }
            }
            
            private interface MethodInvoker
            {
                Object get(final GeneratedMessage message);
                
                Object get(final Builder<?> builder);
                
                int getOneofFieldNumber(final GeneratedMessage message);
                
                int getOneofFieldNumber(final Builder<?> builder);
                
                void set(final Builder<?> builder, final Object value);
                
                boolean has(final GeneratedMessage message);
                
                boolean has(final Builder<?> builder);
                
                void clear(final Builder<?> builder);
            }
        }
        
        private static class RepeatedFieldAccessor implements FieldAccessor
        {
            protected final Class<?> type;
            protected final MethodInvoker invoker;
            
            RepeatedFieldAccessor(final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder<?>> builderClass) {
                final ReflectionInvoker reflectionInvoker = new ReflectionInvoker(camelCaseName, messageClass, builderClass);
                this.type = reflectionInvoker.getRepeatedMethod.getReturnType();
                this.invoker = getMethodInvoker(reflectionInvoker);
            }
            
            static MethodInvoker getMethodInvoker(final ReflectionInvoker accessor) {
                return accessor;
            }
            
            @Override
            public Object get(final GeneratedMessage message) {
                return this.invoker.get(message);
            }
            
            @Override
            public Object get(final Builder<?> builder) {
                return this.invoker.get(builder);
            }
            
            @Override
            public Object getRaw(final GeneratedMessage message) {
                return this.get(message);
            }
            
            @Override
            public void set(final Builder<?> builder, final Object value) {
                this.clear(builder);
                for (final Object element : (List)value) {
                    this.addRepeated(builder, element);
                }
            }
            
            @Override
            public Object getRepeated(final GeneratedMessage message, final int index) {
                return this.invoker.getRepeated(message, index);
            }
            
            @Override
            public Object getRepeated(final Builder<?> builder, final int index) {
                return this.invoker.getRepeated(builder, index);
            }
            
            @Override
            public void setRepeated(final Builder<?> builder, final int index, final Object value) {
                this.invoker.setRepeated(builder, index, value);
            }
            
            @Override
            public void addRepeated(final Builder<?> builder, final Object value) {
                this.invoker.addRepeated(builder, value);
            }
            
            @Override
            public boolean has(final GeneratedMessage message) {
                throw new UnsupportedOperationException("hasField() called on a repeated field.");
            }
            
            @Override
            public boolean has(final Builder<?> builder) {
                throw new UnsupportedOperationException("hasField() called on a repeated field.");
            }
            
            @Override
            public int getRepeatedCount(final GeneratedMessage message) {
                return this.invoker.getRepeatedCount(message);
            }
            
            @Override
            public int getRepeatedCount(final Builder<?> builder) {
                return this.invoker.getRepeatedCount(builder);
            }
            
            @Override
            public void clear(final Builder<?> builder) {
                this.invoker.clear(builder);
            }
            
            @Override
            public Message.Builder newBuilder() {
                throw new UnsupportedOperationException("newBuilderForField() called on a repeated field.");
            }
            
            @Override
            public Message.Builder getBuilder(final Builder<?> builder) {
                throw new UnsupportedOperationException("getFieldBuilder() called on a repeated field.");
            }
            
            @Override
            public Message.Builder getRepeatedBuilder(final Builder<?> builder, final int index) {
                throw new UnsupportedOperationException("getRepeatedFieldBuilder() called on a non-Message type.");
            }
            
            private static final class ReflectionInvoker implements MethodInvoker
            {
                private final Method getMethod;
                private final Method getMethodBuilder;
                private final Method getRepeatedMethod;
                private final Method getRepeatedMethodBuilder;
                private final Method setRepeatedMethod;
                private final Method addRepeatedMethod;
                private final Method getCountMethod;
                private final Method getCountMethodBuilder;
                private final Method clearMethod;
                
                ReflectionInvoker(final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder<?>> builderClass) {
                    this.getMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "List", (Class<?>[])new Class[0]);
                    this.getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "List", (Class<?>[])new Class[0]);
                    this.getRepeatedMethod = getMethodOrDie(messageClass, "get" + camelCaseName, (Class<?>[])new Class[] { Integer.TYPE });
                    this.getRepeatedMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName, (Class<?>[])new Class[] { Integer.TYPE });
                    final Class<?> type = this.getRepeatedMethod.getReturnType();
                    this.setRepeatedMethod = getMethodOrDie(builderClass, "set" + camelCaseName, (Class<?>[])new Class[] { Integer.TYPE, type });
                    this.addRepeatedMethod = getMethodOrDie(builderClass, "add" + camelCaseName, (Class<?>[])new Class[] { type });
                    this.getCountMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Count", (Class<?>[])new Class[0]);
                    this.getCountMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Count", (Class<?>[])new Class[0]);
                    this.clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName, (Class<?>[])new Class[0]);
                }
                
                @Override
                public Object get(final GeneratedMessage message) {
                    return invokeOrDie(this.getMethod, message, new Object[0]);
                }
                
                @Override
                public Object get(final Builder<?> builder) {
                    return invokeOrDie(this.getMethodBuilder, builder, new Object[0]);
                }
                
                @Override
                public Object getRepeated(final GeneratedMessage message, final int index) {
                    return invokeOrDie(this.getRepeatedMethod, message, new Object[] { index });
                }
                
                @Override
                public Object getRepeated(final Builder<?> builder, final int index) {
                    return invokeOrDie(this.getRepeatedMethodBuilder, builder, new Object[] { index });
                }
                
                @Override
                public void setRepeated(final Builder<?> builder, final int index, final Object value) {
                    final Object unused = invokeOrDie(this.setRepeatedMethod, builder, new Object[] { index, value });
                }
                
                @Override
                public void addRepeated(final Builder<?> builder, final Object value) {
                    final Object unused = invokeOrDie(this.addRepeatedMethod, builder, new Object[] { value });
                }
                
                @Override
                public int getRepeatedCount(final GeneratedMessage message) {
                    return (int)invokeOrDie(this.getCountMethod, message, new Object[0]);
                }
                
                @Override
                public int getRepeatedCount(final Builder<?> builder) {
                    return (int)invokeOrDie(this.getCountMethodBuilder, builder, new Object[0]);
                }
                
                @Override
                public void clear(final Builder<?> builder) {
                    final Object unused = invokeOrDie(this.clearMethod, builder, new Object[0]);
                }
            }
            
            interface MethodInvoker
            {
                Object get(final GeneratedMessage message);
                
                Object get(final Builder<?> builder);
                
                Object getRepeated(final GeneratedMessage message, final int index);
                
                Object getRepeated(final Builder<?> builder, final int index);
                
                void setRepeated(final Builder<?> builder, final int index, final Object value);
                
                void addRepeated(final Builder<?> builder, final Object value);
                
                int getRepeatedCount(final GeneratedMessage message);
                
                int getRepeatedCount(final Builder<?> builder);
                
                void clear(final Builder<?> builder);
            }
        }
        
        private static class MapFieldAccessor implements FieldAccessor
        {
            private final Descriptors.FieldDescriptor field;
            private final Message mapEntryMessageDefaultInstance;
            
            MapFieldAccessor(final Descriptors.FieldDescriptor descriptor, final Class<? extends GeneratedMessage> messageClass) {
                this.field = descriptor;
                final Method getDefaultInstanceMethod = getMethodOrDie(messageClass, "getDefaultInstance", (Class<?>[])new Class[0]);
                final MapFieldReflectionAccessor defaultMapField = this.getMapField((GeneratedMessage)invokeOrDie(getDefaultInstanceMethod, null, new Object[0]));
                this.mapEntryMessageDefaultInstance = defaultMapField.getMapEntryMessageDefaultInstance();
            }
            
            private MapFieldReflectionAccessor getMapField(final GeneratedMessage message) {
                return message.internalGetMapFieldReflection(this.field.getNumber());
            }
            
            private MapFieldReflectionAccessor getMapField(final Builder<?> builder) {
                return builder.internalGetMapFieldReflection(this.field.getNumber());
            }
            
            private MapFieldReflectionAccessor getMutableMapField(final Builder<?> builder) {
                return builder.internalGetMutableMapFieldReflection(this.field.getNumber());
            }
            
            private Message coerceType(final Message value) {
                if (value == null) {
                    return null;
                }
                if (this.mapEntryMessageDefaultInstance.getClass().isInstance(value)) {
                    return value;
                }
                return this.mapEntryMessageDefaultInstance.toBuilder().mergeFrom(value).build();
            }
            
            @Override
            public Object get(final GeneratedMessage message) {
                final List<Object> result = new ArrayList<Object>();
                for (int i = 0; i < this.getRepeatedCount(message); ++i) {
                    result.add(this.getRepeated(message, i));
                }
                return Collections.unmodifiableList((List<?>)result);
            }
            
            @Override
            public Object get(final Builder<?> builder) {
                final List<Object> result = new ArrayList<Object>();
                for (int i = 0; i < this.getRepeatedCount(builder); ++i) {
                    result.add(this.getRepeated(builder, i));
                }
                return Collections.unmodifiableList((List<?>)result);
            }
            
            @Override
            public Object getRaw(final GeneratedMessage message) {
                return this.get(message);
            }
            
            @Override
            public void set(final Builder<?> builder, final Object value) {
                this.clear(builder);
                for (final Object entry : (List)value) {
                    this.addRepeated(builder, entry);
                }
            }
            
            @Override
            public Object getRepeated(final GeneratedMessage message, final int index) {
                return this.getMapField(message).getList().get(index);
            }
            
            @Override
            public Object getRepeated(final Builder<?> builder, final int index) {
                return this.getMapField(builder).getList().get(index);
            }
            
            @Override
            public void setRepeated(final Builder<?> builder, final int index, final Object value) {
                this.getMutableMapField(builder).getMutableList().set(index, this.coerceType((Message)value));
            }
            
            @Override
            public void addRepeated(final Builder<?> builder, final Object value) {
                this.getMutableMapField(builder).getMutableList().add(this.coerceType((Message)value));
            }
            
            @Override
            public boolean has(final GeneratedMessage message) {
                throw new UnsupportedOperationException("hasField() is not supported for repeated fields.");
            }
            
            @Override
            public boolean has(final Builder<?> builder) {
                throw new UnsupportedOperationException("hasField() is not supported for repeated fields.");
            }
            
            @Override
            public int getRepeatedCount(final GeneratedMessage message) {
                return this.getMapField(message).getList().size();
            }
            
            @Override
            public int getRepeatedCount(final Builder<?> builder) {
                return this.getMapField(builder).getList().size();
            }
            
            @Override
            public void clear(final Builder<?> builder) {
                this.getMutableMapField(builder).getMutableList().clear();
            }
            
            @Override
            public Message.Builder newBuilder() {
                return this.mapEntryMessageDefaultInstance.newBuilderForType();
            }
            
            @Override
            public Message.Builder getBuilder(final Builder<?> builder) {
                throw new UnsupportedOperationException("Nested builder not supported for map fields.");
            }
            
            @Override
            public Message.Builder getRepeatedBuilder(final Builder<?> builder, final int index) {
                throw new UnsupportedOperationException("Map fields cannot be repeated");
            }
        }
        
        private static final class SingularEnumFieldAccessor extends SingularFieldAccessor
        {
            private final Descriptors.EnumDescriptor enumDescriptor;
            private final Method valueOfMethod;
            private final Method getValueDescriptorMethod;
            private final boolean supportUnknownEnumValue;
            private Method getValueMethod;
            private Method getValueMethodBuilder;
            private Method setValueMethod;
            
            SingularEnumFieldAccessor(final Descriptors.FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder<?>> builderClass, final String containingOneofCamelCaseName) {
                super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
                this.enumDescriptor = descriptor.getEnumType();
                this.valueOfMethod = getMethodOrDie(this.type, "valueOf", (Class<?>[])new Class[] { Descriptors.EnumValueDescriptor.class });
                this.getValueDescriptorMethod = getMethodOrDie(this.type, "getValueDescriptor", (Class<?>[])new Class[0]);
                this.supportUnknownEnumValue = !descriptor.legacyEnumFieldTreatedAsClosed();
                if (this.supportUnknownEnumValue) {
                    this.getValueMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Value", (Class<?>[])new Class[0]);
                    this.getValueMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Value", (Class<?>[])new Class[0]);
                    this.setValueMethod = getMethodOrDie(builderClass, "set" + camelCaseName + "Value", (Class<?>[])new Class[] { Integer.TYPE });
                }
            }
            
            @Override
            public Object get(final GeneratedMessage message) {
                if (this.supportUnknownEnumValue) {
                    final int value = (int)invokeOrDie(this.getValueMethod, message, new Object[0]);
                    return this.enumDescriptor.findValueByNumberCreatingIfUnknown(value);
                }
                return invokeOrDie(this.getValueDescriptorMethod, super.get(message), new Object[0]);
            }
            
            @Override
            public Object get(final Builder<?> builder) {
                if (this.supportUnknownEnumValue) {
                    final int value = (int)invokeOrDie(this.getValueMethodBuilder, builder, new Object[0]);
                    return this.enumDescriptor.findValueByNumberCreatingIfUnknown(value);
                }
                return invokeOrDie(this.getValueDescriptorMethod, super.get(builder), new Object[0]);
            }
            
            @Override
            public void set(final Builder<?> builder, final Object value) {
                if (this.supportUnknownEnumValue) {
                    final Object unused = invokeOrDie(this.setValueMethod, builder, new Object[] { ((Descriptors.EnumValueDescriptor)value).getNumber() });
                    return;
                }
                super.set(builder, invokeOrDie(this.valueOfMethod, null, new Object[] { value }));
            }
        }
        
        private static final class RepeatedEnumFieldAccessor extends RepeatedFieldAccessor
        {
            private final Descriptors.EnumDescriptor enumDescriptor;
            private final Method valueOfMethod;
            private final Method getValueDescriptorMethod;
            private final boolean supportUnknownEnumValue;
            private Method getRepeatedValueMethod;
            private Method getRepeatedValueMethodBuilder;
            private Method setRepeatedValueMethod;
            private Method addRepeatedValueMethod;
            
            RepeatedEnumFieldAccessor(final Descriptors.FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder<?>> builderClass) {
                super(camelCaseName, messageClass, builderClass);
                this.enumDescriptor = descriptor.getEnumType();
                this.valueOfMethod = getMethodOrDie(this.type, "valueOf", (Class<?>[])new Class[] { Descriptors.EnumValueDescriptor.class });
                this.getValueDescriptorMethod = getMethodOrDie(this.type, "getValueDescriptor", (Class<?>[])new Class[0]);
                this.supportUnknownEnumValue = !descriptor.legacyEnumFieldTreatedAsClosed();
                if (this.supportUnknownEnumValue) {
                    this.getRepeatedValueMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Value", (Class<?>[])new Class[] { Integer.TYPE });
                    this.getRepeatedValueMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Value", (Class<?>[])new Class[] { Integer.TYPE });
                    this.setRepeatedValueMethod = getMethodOrDie(builderClass, "set" + camelCaseName + "Value", (Class<?>[])new Class[] { Integer.TYPE, Integer.TYPE });
                    this.addRepeatedValueMethod = getMethodOrDie(builderClass, "add" + camelCaseName + "Value", (Class<?>[])new Class[] { Integer.TYPE });
                }
            }
            
            @Override
            public Object get(final GeneratedMessage message) {
                final List<Object> newList = new ArrayList<Object>();
                for (int size = this.getRepeatedCount(message), i = 0; i < size; ++i) {
                    newList.add(this.getRepeated(message, i));
                }
                return Collections.unmodifiableList((List<?>)newList);
            }
            
            @Override
            public Object get(final Builder<?> builder) {
                final List<Object> newList = new ArrayList<Object>();
                for (int size = this.getRepeatedCount(builder), i = 0; i < size; ++i) {
                    newList.add(this.getRepeated(builder, i));
                }
                return Collections.unmodifiableList((List<?>)newList);
            }
            
            @Override
            public Object getRepeated(final GeneratedMessage message, final int index) {
                if (this.supportUnknownEnumValue) {
                    final int value = (int)invokeOrDie(this.getRepeatedValueMethod, message, new Object[] { index });
                    return this.enumDescriptor.findValueByNumberCreatingIfUnknown(value);
                }
                return invokeOrDie(this.getValueDescriptorMethod, super.getRepeated(message, index), new Object[0]);
            }
            
            @Override
            public Object getRepeated(final Builder<?> builder, final int index) {
                if (this.supportUnknownEnumValue) {
                    final int value = (int)invokeOrDie(this.getRepeatedValueMethodBuilder, builder, new Object[] { index });
                    return this.enumDescriptor.findValueByNumberCreatingIfUnknown(value);
                }
                return invokeOrDie(this.getValueDescriptorMethod, super.getRepeated(builder, index), new Object[0]);
            }
            
            @Override
            public void setRepeated(final Builder<?> builder, final int index, final Object value) {
                if (this.supportUnknownEnumValue) {
                    final Object unused = invokeOrDie(this.setRepeatedValueMethod, builder, new Object[] { index, ((Descriptors.EnumValueDescriptor)value).getNumber() });
                    return;
                }
                super.setRepeated(builder, index, invokeOrDie(this.valueOfMethod, null, new Object[] { value }));
            }
            
            @Override
            public void addRepeated(final Builder<?> builder, final Object value) {
                if (this.supportUnknownEnumValue) {
                    final Object unused = invokeOrDie(this.addRepeatedValueMethod, builder, new Object[] { ((Descriptors.EnumValueDescriptor)value).getNumber() });
                    return;
                }
                super.addRepeated(builder, invokeOrDie(this.valueOfMethod, null, new Object[] { value }));
            }
        }
        
        private static final class SingularStringFieldAccessor extends SingularFieldAccessor
        {
            private final Method getBytesMethod;
            private final Method setBytesMethodBuilder;
            
            SingularStringFieldAccessor(final Descriptors.FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder<?>> builderClass, final String containingOneofCamelCaseName) {
                super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
                this.getBytesMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Bytes", (Class<?>[])new Class[0]);
                this.setBytesMethodBuilder = getMethodOrDie(builderClass, "set" + camelCaseName + "Bytes", (Class<?>[])new Class[] { ByteString.class });
            }
            
            @Override
            public Object getRaw(final GeneratedMessage message) {
                return invokeOrDie(this.getBytesMethod, message, new Object[0]);
            }
            
            @Override
            public void set(final Builder<?> builder, final Object value) {
                if (value instanceof ByteString) {
                    invokeOrDie(this.setBytesMethodBuilder, builder, new Object[] { value });
                }
                else {
                    super.set(builder, value);
                }
            }
        }
        
        private static final class SingularMessageFieldAccessor extends SingularFieldAccessor
        {
            private final Method newBuilderMethod;
            private final Method getBuilderMethodBuilder;
            
            SingularMessageFieldAccessor(final Descriptors.FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder<?>> builderClass, final String containingOneofCamelCaseName) {
                super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
                this.newBuilderMethod = getMethodOrDie(this.type, "newBuilder", (Class<?>[])new Class[0]);
                this.getBuilderMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Builder", (Class<?>[])new Class[0]);
            }
            
            private Object coerceType(final Object value) {
                if (this.type.isInstance(value)) {
                    return value;
                }
                return ((Message.Builder)invokeOrDie(this.newBuilderMethod, null, new Object[0])).mergeFrom((Message)value).buildPartial();
            }
            
            @Override
            public void set(final Builder<?> builder, final Object value) {
                super.set(builder, this.coerceType(value));
            }
            
            @Override
            public Message.Builder newBuilder() {
                return (Message.Builder)invokeOrDie(this.newBuilderMethod, null, new Object[0]);
            }
            
            @Override
            public Message.Builder getBuilder(final Builder<?> builder) {
                return (Message.Builder)invokeOrDie(this.getBuilderMethodBuilder, builder, new Object[0]);
            }
        }
        
        private static final class RepeatedMessageFieldAccessor extends RepeatedFieldAccessor
        {
            private final Method newBuilderMethod;
            private final Method getBuilderMethodBuilder;
            
            RepeatedMessageFieldAccessor(final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder<?>> builderClass) {
                super(camelCaseName, messageClass, builderClass);
                this.newBuilderMethod = getMethodOrDie(this.type, "newBuilder", (Class<?>[])new Class[0]);
                this.getBuilderMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Builder", (Class<?>[])new Class[] { Integer.TYPE });
            }
            
            private Object coerceType(final Object value) {
                if (this.type.isInstance(value)) {
                    return value;
                }
                return ((Message.Builder)invokeOrDie(this.newBuilderMethod, null, new Object[0])).mergeFrom((Message)value).build();
            }
            
            @Override
            public void setRepeated(final Builder<?> builder, final int index, final Object value) {
                super.setRepeated(builder, index, this.coerceType(value));
            }
            
            @Override
            public void addRepeated(final Builder<?> builder, final Object value) {
                super.addRepeated(builder, this.coerceType(value));
            }
            
            @Override
            public Message.Builder newBuilder() {
                return (Message.Builder)invokeOrDie(this.newBuilderMethod, null, new Object[0]);
            }
            
            @Override
            public Message.Builder getRepeatedBuilder(final Builder<?> builder, final int index) {
                return (Message.Builder)invokeOrDie(this.getBuilderMethodBuilder, builder, new Object[] { index });
            }
        }
        
        private interface FieldAccessor
        {
            Object get(final GeneratedMessage message);
            
            Object get(final Builder<?> builder);
            
            Object getRaw(final GeneratedMessage message);
            
            void set(final Builder<?> builder, final Object value);
            
            Object getRepeated(final GeneratedMessage message, final int index);
            
            Object getRepeated(final Builder<?> builder, final int index);
            
            void setRepeated(final Builder<?> builder, final int index, final Object value);
            
            void addRepeated(final Builder<?> builder, final Object value);
            
            boolean has(final GeneratedMessage message);
            
            boolean has(final Builder<?> builder);
            
            int getRepeatedCount(final GeneratedMessage message);
            
            int getRepeatedCount(final Builder<?> builder);
            
            void clear(final Builder<?> builder);
            
            Message.Builder newBuilder();
            
            Message.Builder getBuilder(final Builder<?> builder);
            
            Message.Builder getRepeatedBuilder(final Builder<?> builder, final int index);
        }
        
        private interface OneofAccessor
        {
            boolean has(final GeneratedMessage message);
            
            boolean has(final Builder<?> builder);
            
            Descriptors.FieldDescriptor get(final GeneratedMessage message);
            
            Descriptors.FieldDescriptor get(final Builder<?> builder);
            
            void clear(final Builder<?> builder);
        }
    }
    
    interface ExtensionDescriptorRetriever
    {
        Descriptors.FieldDescriptor getDescriptor();
    }
}
