GeneratedMessage.java revision d0332953cda33fb4f8e24ebff9c49159b69c43d6
131c24bf5b39cc8391d4cfdbf8cf5163975fdb81eJim Grosbach// Protocol Buffers - Google's data interchange format
2334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// Copyright 2008 Google Inc.  All rights reserved.
3334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// http://code.google.com/p/protobuf/
4334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin//
5334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// Redistribution and use in source and binary forms, with or without
6334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// modification, are permitted provided that the following conditions are
7334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// met:
8334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin//
9334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin//     * Redistributions of source code must retain the above copyright
10334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// notice, this list of conditions and the following disclaimer.
11334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin//     * Redistributions in binary form must reproduce the above
12334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// copyright notice, this list of conditions and the following disclaimer
13334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// in the documentation and/or other materials provided with the
14334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// distribution.
15334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin//     * Neither the name of Google Inc. nor the names of its
16334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// contributors may be used to endorse or promote products derived from
17d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng// this software without specific prior written permission.
18334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin//
19334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20f95215f551949d5e5adfbf4753aa833b9009b77aAnton Korobeynikov// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov
31249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikovpackage com.google.protobuf;
32af76e592c7f9deff0e55c13dbb4a34f07f1c7f64Chris Lattner
33334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwinimport com.google.protobuf.Descriptors.Descriptor;
34f95215f551949d5e5adfbf4753aa833b9009b77aAnton Korobeynikovimport com.google.protobuf.Descriptors.EnumValueDescriptor;
35c25e7581b9b8088910da31702d4ca21c4734c6d7Torok Edwinimport com.google.protobuf.Descriptors.FieldDescriptor;
36334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
37334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwinimport java.io.IOException;
38334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwinimport java.lang.reflect.Method;
39334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwinimport java.lang.reflect.InvocationTargetException;
40334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwinimport java.util.ArrayList;
41334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwinimport java.util.Collections;
42f95215f551949d5e5adfbf4753aa833b9009b77aAnton Korobeynikovimport java.util.Iterator;
43f95215f551949d5e5adfbf4753aa833b9009b77aAnton Korobeynikovimport java.util.List;
44f95215f551949d5e5adfbf4753aa833b9009b77aAnton Korobeynikovimport java.util.Map;
45334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwinimport java.util.TreeMap;
46334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
47334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin/**
48334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin * All generated protocol message classes extend this class.  This class
49334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin * implements most of the Message and Builder interfaces using Java reflection.
50334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin * Users can ignore this class and pretend that generated messages implement
5178703ddafe3d037f75d8ca188e4829d238289ac3Evan Cheng * the Message interface directly.
5278703ddafe3d037f75d8ca188e4829d238289ac3Evan Cheng *
53334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin * @author kenton@google.com Kenton Varda
54334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin */
55334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwinpublic abstract class GeneratedMessage extends AbstractMessage {
56334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  protected GeneratedMessage() {}
57334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
58334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  private UnknownFieldSet unknownFields = UnknownFieldSet.getDefaultInstance();
59334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
60334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  /**
61334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * Get the FieldAccessorTable for this type.  We can't have the message
62334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * class pass this in to the constructor because of bootstrapping trouble
63334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * with DescriptorProtos.
64334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   */
65334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  protected abstract FieldAccessorTable internalGetFieldAccessorTable();
66334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
67334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  public Descriptor getDescriptorForType() {
68334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    return internalGetFieldAccessorTable().descriptor;
69334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  }
70334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
71334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  /** Internal helper which returns a mutable map. */
72334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  private Map<FieldDescriptor, Object> getAllFieldsMutable() {
73334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    final TreeMap<FieldDescriptor, Object> result =
74334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      new TreeMap<FieldDescriptor, Object>();
75334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
76334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    for (final FieldDescriptor field : descriptor.getFields()) {
77334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      if (field.isRepeated()) {
78334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final List value = (List) getField(field);
79334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        if (!value.isEmpty()) {
80334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          result.put(field, value);
81334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        }
82334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      } else {
83334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        if (hasField(field)) {
84334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          result.put(field, getField(field));
85334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        }
86334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
87334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
88334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    return result;
89334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  }
90334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
91334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  @Override
92334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  public boolean isInitialized() {
93334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    for (final FieldDescriptor field : getDescriptorForType().getFields()) {
94334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      // Check that all required fields are present.
95334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      if (field.isRequired()) {
96334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        if (!hasField(field)) {
97e7cbe4118b7ddf05032ff8772a98c51e1637bb5cEvan Cheng          return false;
98334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        }
99334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
100334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      // Check that embedded messages are initialized.
101334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
10278703ddafe3d037f75d8ca188e4829d238289ac3Evan Cheng        if (field.isRepeated()) {
103e7cbe4118b7ddf05032ff8772a98c51e1637bb5cEvan Cheng          @SuppressWarnings("unchecked") final
104334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          List<Message> messageList = (List<Message>) getField(field);
105334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          for (final Message element : messageList) {
106334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            if (!element.isInitialized()) {
107334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin              return false;
108334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            }
10978703ddafe3d037f75d8ca188e4829d238289ac3Evan Cheng          }
110334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        } else {
111334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          if (hasField(field) && !((Message) getField(field)).isInitialized()) {
112334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            return false;
113334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          }
11478703ddafe3d037f75d8ca188e4829d238289ac3Evan Cheng        }
115334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
116334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
117334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
118334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    return true;
119334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  }
120334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
121334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  public Map<FieldDescriptor, Object> getAllFields() {
122334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    return Collections.unmodifiableMap(getAllFieldsMutable());
123334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  }
124334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
12578703ddafe3d037f75d8ca188e4829d238289ac3Evan Cheng  public boolean hasField(final FieldDescriptor field) {
126334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    return internalGetFieldAccessorTable().getField(field).has(this);
127334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  }
128334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
129334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  public Object getField(final FieldDescriptor field) {
13078703ddafe3d037f75d8ca188e4829d238289ac3Evan Cheng    return internalGetFieldAccessorTable().getField(field).get(this);
131334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  }
132334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
133334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  public int getRepeatedFieldCount(final FieldDescriptor field) {
134334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    return internalGetFieldAccessorTable().getField(field)
135334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      .getRepeatedCount(this);
136334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  }
137334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
138334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  public Object getRepeatedField(final FieldDescriptor field, final int index) {
139334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    return internalGetFieldAccessorTable().getField(field)
140334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      .getRepeated(this, index);
141334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  }
142334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
143334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  public final UnknownFieldSet getUnknownFields() {
144334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    return unknownFields;
145334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  }
146334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
147334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  @SuppressWarnings("unchecked")
148334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  public abstract static class Builder <BuilderType extends Builder>
149334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      extends AbstractMessage.Builder<BuilderType> {
150334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    protected Builder() {}
151334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
152334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    // This is implemented here only to work around an apparent bug in the
153334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    // Java compiler and/or build system.  See bug #1898463.  The mere presence
154334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    // of this dummy clone() implementation makes it go away.
155334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    @Override
156334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public BuilderType clone() {
157334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      throw new UnsupportedOperationException(
158334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          "This is supposed to be overridden by subclasses.");
159334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
160334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
161334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /**
162334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * Get the message being built.  We don't just pass this to the
163334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * constructor because it becomes null when build() is called.
164334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     */
165334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    protected abstract GeneratedMessage internalGetResult();
166334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
167334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /**
168334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * Get the FieldAccessorTable for this type.  We can't have the message
169334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * class pass this in to the constructor because of bootstrapping trouble
170334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * with DescriptorProtos.
171334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     */
172334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    private FieldAccessorTable internalGetFieldAccessorTable() {
173334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return internalGetResult().internalGetFieldAccessorTable();
174334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
175334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
176334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public Descriptor getDescriptorForType() {
177334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return internalGetFieldAccessorTable().descriptor;
178334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
179334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
180334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public Map<FieldDescriptor, Object> getAllFields() {
181334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return internalGetResult().getAllFields();
182334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
183334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
184334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public Message.Builder newBuilderForField(
185334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final FieldDescriptor field) {
186334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return internalGetFieldAccessorTable().getField(field).newBuilder();
187334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
188334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
189334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public boolean hasField(final FieldDescriptor field) {
190334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return internalGetResult().hasField(field);
191334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
192334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
193334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public Object getField(final FieldDescriptor field) {
194334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      if (field.isRepeated()) {
195334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        // The underlying list object is still modifiable at this point.
196334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        // Make sure not to expose the modifiable list to the caller.
197334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        return Collections.unmodifiableList(
198334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          (List) internalGetResult().getField(field));
199334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      } else {
200334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        return internalGetResult().getField(field);
201334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
202334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
203334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
204334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public BuilderType setField(final FieldDescriptor field,
205334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                                final Object value) {
206334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      internalGetFieldAccessorTable().getField(field).set(this, value);
207334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return (BuilderType) this;
208334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
209334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
210334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public BuilderType clearField(final FieldDescriptor field) {
211334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      internalGetFieldAccessorTable().getField(field).clear(this);
212334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return (BuilderType) this;
213334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
214334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
215334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public int getRepeatedFieldCount(final FieldDescriptor field) {
2165ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng      return internalGetResult().getRepeatedFieldCount(field);
217334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
218334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
219334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public Object getRepeatedField(final FieldDescriptor field,
2205ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng                                   final int index) {
221334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return internalGetResult().getRepeatedField(field, index);
222334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
223334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
224334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public BuilderType setRepeatedField(final FieldDescriptor field,
225334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                                        final int index, final Object value) {
226334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      internalGetFieldAccessorTable().getField(field)
227334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        .setRepeated(this, index, value);
228334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return (BuilderType) this;
229334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
230334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
231334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public BuilderType addRepeatedField(final FieldDescriptor field,
232334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                                        final Object value) {
233334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
234334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return (BuilderType) this;
235334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
236334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
2375ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng    public final UnknownFieldSet getUnknownFields() {
238334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return internalGetResult().unknownFields;
2395ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng    }
240334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
241334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public final BuilderType setUnknownFields(
242334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final UnknownFieldSet unknownFields) {
243334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      internalGetResult().unknownFields = unknownFields;
244334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return (BuilderType) this;
245334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
246334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
247334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    @Override
248334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public final BuilderType mergeUnknownFields(
2495ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng        final UnknownFieldSet unknownFields) {
250334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      final GeneratedMessage result = internalGetResult();
251334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      result.unknownFields =
252334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        UnknownFieldSet.newBuilder(result.unknownFields)
253334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                       .mergeFrom(unknownFields)
254334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                       .build();
255334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return (BuilderType) this;
256334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
257334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
258334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public boolean isInitialized() {
259334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return internalGetResult().isInitialized();
2608d4de5abfa1bcd974554ea14904ebf7af289e84dBob Wilson    }
2618d4de5abfa1bcd974554ea14904ebf7af289e84dBob Wilson
2625ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng    /**
263334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * Called by subclasses to parse an unknown field.
264334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * @return {@code true} unless the tag is an end-group tag.
265334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     */
266334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    protected boolean parseUnknownField(
267334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final CodedInputStream input,
268334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final UnknownFieldSet.Builder unknownFields,
269334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final ExtensionRegistryLite extensionRegistry,
270334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final int tag) throws IOException {
271334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return unknownFields.mergeFieldFrom(tag, input);
272334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
273334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  }
274334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
275334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  // =================================================================
276334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  // Extensions-related stuff
277334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
2785ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng  /**
2795ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng   * Generated message classes for message types that contain extension ranges
280334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * subclass this.
281334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *
282334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * <p>This class implements type-safe accessors for extensions.  They
283334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * implement all the same operations that you can do with normal fields --
284334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * e.g. "has", "get", and "getCount" -- but for extensions.  The extensions
285334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * are identified using instances of the class {@link GeneratedExtension};
286334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * the protocol compiler generates a static instance of this class for every
287334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * extension in its input.  Through the magic of generics, all is made
288334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * type-safe.
2895ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng   *
290334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * <p>For example, imagine you have the {@code .proto} file:
291334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *
292334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * <pre>
293334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * option java_class = "MyProto";
294334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *
295334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * message Foo {
296334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *   extensions 1000 to max;
297334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * }
298334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *
299334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * extend Foo {
300334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *   optional int32 bar;
301334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * }
302334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * </pre>
3036495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng   *
3046495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng   * <p>Then you might write code like:
3056495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng   *
3066495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng   * <pre>
3076495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng   * MyProto.Foo foo = getFoo();
3086495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng   * int i = foo.getExtension(MyProto.bar);
309334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * </pre>
310334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *
311334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * <p>See also {@link ExtendableBuilder}.
312334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   */
313334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  public abstract static class ExtendableMessage<
314334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        MessageType extends ExtendableMessage>
315334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      extends GeneratedMessage {
316334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    protected ExtendableMessage() {}
317334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    private final FieldSet<FieldDescriptor> extensions = FieldSet.newFieldSet();
318334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
319334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    private void verifyExtensionContainingType(
320334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final GeneratedExtension<MessageType, ?> extension) {
321334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      if (extension.getDescriptor().getContainingType() !=
322334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          getDescriptorForType()) {
323334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        // This can only happen if someone uses unchecked operations.
324334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        throw new IllegalArgumentException(
325334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          "Extension is for type \"" +
326334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          extension.getDescriptor().getContainingType().getFullName() +
327334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          "\" which does not match message type \"" +
328334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          getDescriptorForType().getFullName() + "\".");
329334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
330334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
331334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
332334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /** Check if a singular extension is present. */
333334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public final boolean hasExtension(
334334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final GeneratedExtension<MessageType, ?> extension) {
335334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      verifyExtensionContainingType(extension);
336334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return extensions.hasField(extension.getDescriptor());
337334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
338334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
339334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /** Get the number of elements in a repeated extension. */
340334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public final <Type> int getExtensionCount(
341334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final GeneratedExtension<MessageType, List<Type>> extension) {
3425ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng      verifyExtensionContainingType(extension);
3435ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng      final FieldDescriptor descriptor = extension.getDescriptor();
344334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return extensions.getRepeatedFieldCount(descriptor);
345334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
346334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
347334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /** Get the value of an extension. */
348334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    @SuppressWarnings("unchecked")
349334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public final <Type> Type getExtension(
350334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final GeneratedExtension<MessageType, Type> extension) {
351334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      verifyExtensionContainingType(extension);
352334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      FieldDescriptor descriptor = extension.getDescriptor();
353334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      final Object value = extensions.getField(descriptor);
354334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      if (value == null) {
355334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        if (descriptor.isRepeated()) {
356334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          return (Type) Collections.emptyList();
357334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        } else if (descriptor.getJavaType() ==
358334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                   FieldDescriptor.JavaType.MESSAGE) {
359334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          return (Type) extension.getMessageDefaultInstance();
360334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        } else {
361334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          return (Type) extension.fromReflectionType(
362334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin              descriptor.getDefaultValue());
363334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        }
364334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      } else {
365334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        return (Type) extension.fromReflectionType(value);
366334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
367334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
368334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
369334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /** Get one element of a repeated extension. */
370334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    @SuppressWarnings("unchecked")
371334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public final <Type> Type getExtension(
372334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final GeneratedExtension<MessageType, List<Type>> extension,
373334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final int index) {
374334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      verifyExtensionContainingType(extension);
375334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      FieldDescriptor descriptor = extension.getDescriptor();
376334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return (Type) extension.singularFromReflectionType(
377334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          extensions.getRepeatedField(descriptor, index));
378334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
379334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
380334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /** Called by subclasses to check if all extensions are initialized. */
381334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    protected boolean extensionsAreInitialized() {
382334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return extensions.isInitialized();
383334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
384334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
385334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    @Override
386334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public boolean isInitialized() {
387334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return super.isInitialized() && extensionsAreInitialized();
3888fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng    }
389334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
390334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /**
391334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * Used by subclasses to serialize extensions.  Extension ranges may be
392334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * interleaved with field numbers, but we must write them in canonical
393334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * (sorted by field number) order.  ExtensionWriter helps us write
394334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * individual ranges of extensions at once.
395334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     */
396334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    protected class ExtensionWriter {
397334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      // Imagine how much simpler this code would be if Java iterators had
398334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      // a way to get the next element without advancing the iterator.
399334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
400334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      private final Iterator<Map.Entry<FieldDescriptor, Object>> iter =
401334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        extensions.iterator();
402334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      private Map.Entry<FieldDescriptor, Object> next;
403334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      private final boolean messageSetWireFormat;
404334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
405334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      private ExtensionWriter(final boolean messageSetWireFormat) {
406334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        if (iter.hasNext()) {
407334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          next = iter.next();
408334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        }
409334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        this.messageSetWireFormat = messageSetWireFormat;
410334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
411334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
412334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      public void writeUntil(final int end, final CodedOutputStream output)
413334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                             throws IOException {
414334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        while (next != null && next.getKey().getNumber() < end) {
415334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          FieldDescriptor descriptor = next.getKey();
416334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          if (messageSetWireFormat && descriptor.getLiteJavaType() ==
417334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                  WireFormat.JavaType.MESSAGE &&
418334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin              !descriptor.isRepeated()) {
41933adcfb4d217f5f23d9bde8ba02b8e48f9605fc5Chris Lattner            output.writeMessageSetExtension(descriptor.getNumber(),
420334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                                            (Message) next.getValue());
421334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          } else {
422334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            FieldSet.writeField(descriptor, next.getValue(), output);
423334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          }
424334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          if (iter.hasNext()) {
425a0ee862f2e3a0d202244e02459ddcf0dca0e8607Evan Cheng            next = iter.next();
426334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          } else {
427334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            next = null;
428334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          }
429334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        }
43033adcfb4d217f5f23d9bde8ba02b8e48f9605fc5Chris Lattner      }
431334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
432334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
433a0ee862f2e3a0d202244e02459ddcf0dca0e8607Evan Cheng    protected ExtensionWriter newExtensionWriter() {
434334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return new ExtensionWriter(false);
435c23197a26f34f559ea9797de51e187087c039c42Torok Edwin    }
436334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    protected ExtensionWriter newMessageSetExtensionWriter() {
43726207e5bf1123a793bd9b38bcda2f569a6b45ef2Jakob Stoklund Olesen      return new ExtensionWriter(true);
438334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
439334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
440334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /** Called by subclasses to compute the size of extensions. */
441334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    protected int extensionsSerializedSize() {
442334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return extensions.getSerializedSize();
443334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
444789476240d6b6f8ad9366cadf790a82bd41bb0b3Evan Cheng    protected int extensionsSerializedSizeAsMessageSet() {
445789476240d6b6f8ad9366cadf790a82bd41bb0b3Evan Cheng      return extensions.getMessageSetSerializedSize();
446789476240d6b6f8ad9366cadf790a82bd41bb0b3Evan Cheng    }
447334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
448a0ee862f2e3a0d202244e02459ddcf0dca0e8607Evan Cheng    // ---------------------------------------------------------------
449334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    // Reflection
450334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
451334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    @Override
452334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public Map<FieldDescriptor, Object> getAllFields() {
453789476240d6b6f8ad9366cadf790a82bd41bb0b3Evan Cheng      final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
454cdc17ebc2b2e9e18ac516b9d246a5c5a3af227d3Jim Grosbach      result.putAll(extensions.getAllFields());
4555aa1684e5da9a85286bf7d29da419d261a70c2f2Jim Grosbach      return Collections.unmodifiableMap(result);
4565a1cd36019ca3cbae811f2800631b5b56a9ffdc2Evan Cheng    }
457334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
458334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    @Override
459334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public boolean hasField(final FieldDescriptor field) {
460a0ee862f2e3a0d202244e02459ddcf0dca0e8607Evan Cheng      if (field.isExtension()) {
461d26b14c34cbcee1448b86b524578fc51cc979023Evan Cheng        verifyContainingType(field);
462d26b14c34cbcee1448b86b524578fc51cc979023Evan Cheng        return extensions.hasField(field);
463d26b14c34cbcee1448b86b524578fc51cc979023Evan Cheng      } else {
464334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        return super.hasField(field);
465d26b14c34cbcee1448b86b524578fc51cc979023Evan Cheng      }
466d26b14c34cbcee1448b86b524578fc51cc979023Evan Cheng    }
467a0ee862f2e3a0d202244e02459ddcf0dca0e8607Evan Cheng
468a0ee862f2e3a0d202244e02459ddcf0dca0e8607Evan Cheng    @Override
469334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public Object getField(final FieldDescriptor field) {
470334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      if (field.isExtension()) {
471334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        verifyContainingType(field);
472334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final Object value = extensions.getField(field);
473334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        if (value == null) {
474334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
475334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            // Lacking an ExtensionRegistry, we have no way to determine the
476334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            // extension's real type, so we return a DynamicMessage.
477334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            return DynamicMessage.getDefaultInstance(field.getMessageType());
478334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          } else {
479334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            return field.getDefaultValue();
480334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          }
481334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        } else {
482334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          return value;
48325f7cfc3cccba6f569f29f79ea533bae960b93c0Evan Cheng        }
48425f7cfc3cccba6f569f29f79ea533bae960b93c0Evan Cheng      } else {
48525f7cfc3cccba6f569f29f79ea533bae960b93c0Evan Cheng        return super.getField(field);
48625f7cfc3cccba6f569f29f79ea533bae960b93c0Evan Cheng      }
48725f7cfc3cccba6f569f29f79ea533bae960b93c0Evan Cheng    }
48825f7cfc3cccba6f569f29f79ea533bae960b93c0Evan Cheng
48925f7cfc3cccba6f569f29f79ea533bae960b93c0Evan Cheng    @Override
49025f7cfc3cccba6f569f29f79ea533bae960b93c0Evan Cheng    public int getRepeatedFieldCount(final FieldDescriptor field) {
491334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      if (field.isExtension()) {
492334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        verifyContainingType(field);
493334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        return extensions.getRepeatedFieldCount(field);
494334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      } else {
495334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        return super.getRepeatedFieldCount(field);
496334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
497334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
498334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
499334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    @Override
500334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public Object getRepeatedField(final FieldDescriptor field,
501334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                                   final int index) {
502334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      if (field.isExtension()) {
503334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        verifyContainingType(field);
504334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        return extensions.getRepeatedField(field, index);
505334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      } else {
506334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        return super.getRepeatedField(field, index);
507334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
508334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
509334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
51068e3c6ae49ff67cba98403e43b5bd0c2499caa41Evan Cheng    private void verifyContainingType(final FieldDescriptor field) {
511dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng      if (field.getContainingType() != getDescriptorForType()) {
512e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach        throw new IllegalArgumentException(
51368e3c6ae49ff67cba98403e43b5bd0c2499caa41Evan Cheng          "FieldDescriptor does not match message type.");
514e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach      }
515f95215f551949d5e5adfbf4753aa833b9009b77aAnton Korobeynikov    }
516334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  }
517334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
518334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  /**
519334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * Generated message builders for message types that contain extension ranges
52068e3c6ae49ff67cba98403e43b5bd0c2499caa41Evan Cheng   * subclass this.
52168e3c6ae49ff67cba98403e43b5bd0c2499caa41Evan Cheng   *
52268e3c6ae49ff67cba98403e43b5bd0c2499caa41Evan Cheng   * <p>This class implements type-safe accessors for extensions.  They
52368e3c6ae49ff67cba98403e43b5bd0c2499caa41Evan Cheng   * implement all the same operations that you can do with normal fields --
52468e3c6ae49ff67cba98403e43b5bd0c2499caa41Evan Cheng   * e.g. "get", "set", and "add" -- but for extensions.  The extensions are
52568e3c6ae49ff67cba98403e43b5bd0c2499caa41Evan Cheng   * identified using instances of the class {@link GeneratedExtension}; the
526334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * protocol compiler generates a static instance of this class for every
527334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * extension in its input.  Through the magic of generics, all is made
528334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * type-safe.
529334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *
530334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * <p>For example, imagine you have the {@code .proto} file:
531334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *
532334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * <pre>
533334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * option java_class = "MyProto";
53468e3c6ae49ff67cba98403e43b5bd0c2499caa41Evan Cheng   *
535334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * message Foo {
536334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *   extensions 1000 to max;
537334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * }
538334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *
539764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach   * extend Foo {
540334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *   optional int32 bar;
541334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * }
542dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng   * </pre>
543dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng   *
544dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng   * <p>Then you might write code like:
545dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng   *
546334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * <pre>
547334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * MyProto.Foo foo =
548334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *   MyProto.Foo.newBuilder()
549334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *     .setExtension(MyProto.bar, 123)
550334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *     .build();
551334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * </pre>
552334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *
553334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * <p>See also {@link ExtendableMessage}.
554dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng   */
555dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng  @SuppressWarnings("unchecked")
556dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng  public abstract static class ExtendableBuilder<
5575ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin        MessageType extends ExtendableMessage,
5585ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin        BuilderType extends ExtendableBuilder>
5595ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin      extends Builder<BuilderType> {
5605ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin    protected ExtendableBuilder() {}
5615ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin
5625ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin    // This is implemented here only to work around an apparent bug in the
563dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng    // Java compiler and/or build system.  See bug #1898463.  The mere presence
564e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach    // of this dummy clone() implementation makes it go away.
565e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach    @Override
566334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public BuilderType clone() {
567334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      throw new UnsupportedOperationException(
568334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          "This is supposed to be overridden by subclasses.");
569334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
570334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
571334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    @Override
572dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng    protected abstract ExtendableMessage<MessageType> internalGetResult();
573334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
574334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /** Check if a singular extension is present. */
575334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public final boolean hasExtension(
576334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final GeneratedExtension<MessageType, ?> extension) {
577334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return internalGetResult().hasExtension(extension);
578334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
579334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
580334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /** Get the number of elements in a repeated extension. */
581dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng    public final <Type> int getExtensionCount(
582dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng        final GeneratedExtension<MessageType, List<Type>> extension) {
583dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng      return internalGetResult().getExtensionCount(extension);
584dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng    }
585334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
586334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /** Get the value of an extension. */
587334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public final <Type> Type getExtension(
588334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final GeneratedExtension<MessageType, Type> extension) {
589334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return internalGetResult().getExtension(extension);
590334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
591334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
592334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /** Get one element of a repeated extension. */
593dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng    public final <Type> Type getExtension(
594dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng        final GeneratedExtension<MessageType, List<Type>> extension,
595dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng        final int index) {
5965ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin      return internalGetResult().getExtension(extension, index);
5975ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin    }
5985ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin
5995ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin    /** Set the value of an extension. */
6005ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin    public final <Type> BuilderType setExtension(
6015ff58b5c3ab6df332600678798ea5c69c5e943d3David Goodwin        final GeneratedExtension<MessageType, Type> extension,
602dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng        final Type value) {
603e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach      final ExtendableMessage<MessageType> message = internalGetResult();
604e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach      message.verifyExtensionContainingType(extension);
605334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      final FieldDescriptor descriptor = extension.getDescriptor();
606334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      message.extensions.setField(descriptor,
607334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                                  extension.toReflectionType(value));
608334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return (BuilderType) this;
609334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
610334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
611dced03fc846fa7cd9558ecb8e33ca98ec29bdcf0Evan Cheng    /** Set the value of one element of a repeated extension. */
612334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public final <Type> BuilderType setExtension(
613334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final GeneratedExtension<MessageType, List<Type>> extension,
614334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final int index, final Type value) {
615334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      final ExtendableMessage<MessageType> message = internalGetResult();
616334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      message.verifyExtensionContainingType(extension);
617334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      final FieldDescriptor descriptor = extension.getDescriptor();
618334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      message.extensions.setRepeatedField(
619334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        descriptor, index,
620334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        extension.singularToReflectionType(value));
621334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return (BuilderType) this;
622334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
623334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
624334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /** Append a value to a repeated extension. */
625334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public final <Type> BuilderType addExtension(
626334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final GeneratedExtension<MessageType, List<Type>> extension,
627b4db6a46e0de3283fa70ea0a7d3623f2e4e2d2a3Evan Cheng        final Type value) {
628b4db6a46e0de3283fa70ea0a7d3623f2e4e2d2a3Evan Cheng      final ExtendableMessage<MessageType> message = internalGetResult();
629b4db6a46e0de3283fa70ea0a7d3623f2e4e2d2a3Evan Cheng      message.verifyExtensionContainingType(extension);
630b4db6a46e0de3283fa70ea0a7d3623f2e4e2d2a3Evan Cheng      final FieldDescriptor descriptor = extension.getDescriptor();
631b4db6a46e0de3283fa70ea0a7d3623f2e4e2d2a3Evan Cheng      message.extensions.addRepeatedField(
632b4db6a46e0de3283fa70ea0a7d3623f2e4e2d2a3Evan Cheng          descriptor, extension.singularToReflectionType(value));
6337bfdca0206f51132b26094c6f83a5ac97ee0f943David Goodwin      return (BuilderType) this;
634334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
635334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
6367bfdca0206f51132b26094c6f83a5ac97ee0f943David Goodwin    /** Clear an extension. */
63708b93c6a70ae59af375f205cfcffeaa3517577abEvan Cheng    public final <Type> BuilderType clearExtension(
638dd6f63209cba0003e67470938830de2cb6917336Evan Cheng        final GeneratedExtension<MessageType, ?> extension) {
6397bfdca0206f51132b26094c6f83a5ac97ee0f943David Goodwin      final ExtendableMessage<MessageType> message = internalGetResult();
640e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach      message.verifyExtensionContainingType(extension);
641334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      message.extensions.clearField(extension.getDescriptor());
642b4db6a46e0de3283fa70ea0a7d3623f2e4e2d2a3Evan Cheng      return (BuilderType) this;
643e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach    }
644b4db6a46e0de3283fa70ea0a7d3623f2e4e2d2a3Evan Cheng
645f95215f551949d5e5adfbf4753aa833b9009b77aAnton Korobeynikov    /**
646f95215f551949d5e5adfbf4753aa833b9009b77aAnton Korobeynikov     * Called by subclasses to parse an unknown field or an extension.
647f95215f551949d5e5adfbf4753aa833b9009b77aAnton Korobeynikov     * @return {@code true} unless the tag is an end-group tag.
648f95215f551949d5e5adfbf4753aa833b9009b77aAnton Korobeynikov     */
649f95215f551949d5e5adfbf4753aa833b9009b77aAnton Korobeynikov    @Override
650e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach    protected boolean parseUnknownField(
651e56f9085b1e96f0cc302c678f1c00877676e455eAnton Korobeynikov        final CodedInputStream input,
652b4db6a46e0de3283fa70ea0a7d3623f2e4e2d2a3Evan Cheng        final UnknownFieldSet.Builder unknownFields,
653b4db6a46e0de3283fa70ea0a7d3623f2e4e2d2a3Evan Cheng        final ExtensionRegistryLite extensionRegistry,
654b74bb1a7a471a77e793d90de158aa4bbc67fe94dEvan Cheng        final int tag) throws IOException {
6557bfdca0206f51132b26094c6f83a5ac97ee0f943David Goodwin      final ExtendableMessage<MessageType> message = internalGetResult();
656334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      return AbstractMessage.Builder.mergeFieldFrom(
6577bfdca0206f51132b26094c6f83a5ac97ee0f943David Goodwin        input, unknownFields, extensionRegistry, this, tag);
658334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
659334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
660334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    // ---------------------------------------------------------------
661334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    // Reflection
662334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
663334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    // We don't have to override the get*() methods here because they already
664334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    // just forward to the underlying message.
665334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
666334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    @Override
667334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public BuilderType setField(final FieldDescriptor field,
668249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov                                final Object value) {
669249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov      if (field.isExtension()) {
67031bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach        final ExtendableMessage<MessageType> message = internalGetResult();
671249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov        message.verifyContainingType(field);
672249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov        message.extensions.setField(field, value);
673ff89dcb06fbd103373436e2d0ae85f252fae2254Evan Cheng        return (BuilderType) this;
674249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov      } else {
675249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov        return super.setField(field, value);
67631bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach      }
677334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
678334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
6795732ca084aaa0cd26149e50dd4b487efff37fe41Evan Cheng    @Override
680334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    public BuilderType clearField(final FieldDescriptor field) {
681249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov      if (field.isExtension()) {
6826ca0b9e7220911a6d1fccf34e532e69c7e37cd2fAnton Korobeynikov        final ExtendableMessage<MessageType> message = internalGetResult();
6836ca0b9e7220911a6d1fccf34e532e69c7e37cd2fAnton Korobeynikov        message.verifyContainingType(field);
6846ca0b9e7220911a6d1fccf34e532e69c7e37cd2fAnton Korobeynikov        message.extensions.clearField(field);
685e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach        return (BuilderType) this;
686334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      } else {
687249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov        return super.clearField(field);
688baf31088f1472f48ea5ae81f0b93636cc44ca444Anton Korobeynikov      }
689e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach    }
690334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
691249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov    @Override
692baf31088f1472f48ea5ae81f0b93636cc44ca444Anton Korobeynikov    public BuilderType setRepeatedField(final FieldDescriptor field,
693e56f9085b1e96f0cc302c678f1c00877676e455eAnton Korobeynikov                                        final int index, final Object value) {
694e56f9085b1e96f0cc302c678f1c00877676e455eAnton Korobeynikov      if (field.isExtension()) {
695baf31088f1472f48ea5ae81f0b93636cc44ca444Anton Korobeynikov        final ExtendableMessage<MessageType> message = internalGetResult();
69631bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach        message.verifyContainingType(field);
69731bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach        message.extensions.setRepeatedField(field, index, value);
69831bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach        return (BuilderType) this;
69931bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach      } else {
70031bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach        return super.setRepeatedField(field, index, value);
70131bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach      }
70231bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach    }
70331bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach
70431bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach    @Override
70531bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach    public BuilderType addRepeatedField(final FieldDescriptor field,
706334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                                        final Object value) {
707334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      if (field.isExtension()) {
708334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        final ExtendableMessage<MessageType> message = internalGetResult();
709334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        message.verifyContainingType(field);
710334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        message.extensions.addRepeatedField(field, value);
711334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        return (BuilderType) this;
712334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      } else {
713334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        return super.addRepeatedField(field, value);
714334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
715249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov    }
716249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov
71731bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach    protected final void mergeExtensionFields(final ExtendableMessage other) {
718249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov      internalGetResult().extensions.mergeFrom(other.extensions);
719249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov    }
720ff89dcb06fbd103373436e2d0ae85f252fae2254Evan Cheng  }
721249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov
722249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov  // -----------------------------------------------------------------
72331bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach
724334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  /** For use by generated code only. */
725334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  public static <ContainingType extends Message, Type>
7265732ca084aaa0cd26149e50dd4b487efff37fe41Evan Cheng      GeneratedExtension<ContainingType, Type>
727249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov      newGeneratedExtension() {
7286ca0b9e7220911a6d1fccf34e532e69c7e37cd2fAnton Korobeynikov    return new GeneratedExtension<ContainingType, Type>();
7296ca0b9e7220911a6d1fccf34e532e69c7e37cd2fAnton Korobeynikov  }
7306ca0b9e7220911a6d1fccf34e532e69c7e37cd2fAnton Korobeynikov
731e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  /**
732249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov   * Type used to represent generated extensions.  The protocol compiler
733baf31088f1472f48ea5ae81f0b93636cc44ca444Anton Korobeynikov   * generates a static singleton instance of this class for each extension.
734e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach   *
735249fb339ad9d4b921a04de738b9c67d27e328bb7Anton Korobeynikov   * <p>For example, imagine you have the {@code .proto} file:
736baf31088f1472f48ea5ae81f0b93636cc44ca444Anton Korobeynikov   *
737e56f9085b1e96f0cc302c678f1c00877676e455eAnton Korobeynikov   * <pre>
738b4db6a46e0de3283fa70ea0a7d3623f2e4e2d2a3Evan Cheng   * option java_class = "MyProto";
739b4db6a46e0de3283fa70ea0a7d3623f2e4e2d2a3Evan Cheng   *
740baf31088f1472f48ea5ae81f0b93636cc44ca444Anton Korobeynikov   * message Foo {
74131bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach   *   extensions 1000 to max;
74231bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach   * }
74331bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach   *
74431bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach   * extend Foo {
74531bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach   *   optional int32 bar;
74631bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach   * }
74731bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach   * </pre>
74831bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach   *
74931bc849123011b8eae6bb3c79876d9a3c26a6a1dJim Grosbach   * <p>Then, {@code MyProto.Foo.bar} has type
750334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * {@code GeneratedExtension<MyProto.Foo, Integer>}.
751334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   *
752334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * <p>In general, users should ignore the details of this type, and simply use
753334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * these static singletons as parameters to the extension accessors defined
754334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   * in {@link ExtendableMessage} and {@link ExtendableBuilder}.
755334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin   */
756334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  public static final class GeneratedExtension<
757334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      ContainingType extends Message, Type> {
758334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    // TODO(kenton):  Find ways to avoid using Java reflection within this
759334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    //   class.  Also try to avoid suppressing unchecked warnings.
760334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
76119068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    // We can't always initialize a GeneratedExtension when we first construct
762334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    // it due to initialization order difficulties (namely, the descriptor may
76319068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    // not have been constructed yet, since it is often constructed by the
76419068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    // initializer of a separate module).  So, we construct an uninitialized
76519068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    // GeneratedExtension once, then call internalInit() on it later.  Generated
76619068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    // code will always call internalInit() on all extensions as part of the
76719068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    // static initialization code, and internalInit() throws an exception if
76819068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    // called more than once, so this method is useless to users.
769ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng    private GeneratedExtension() {}
77019068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng
77119068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    /** For use by generated code only. */
77219068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    public void internalInit(final FieldDescriptor descriptor,
77319068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng                             final Class type) {
774ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng      if (this.descriptor != null) {
775ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng        throw new IllegalStateException("Already initialized.");
776ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng      }
77719068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng
77819068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng      if (!descriptor.isExtension()) {
77919068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng        throw new IllegalArgumentException(
780ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng          "GeneratedExtension given a regular (non-extension) field.");
781ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng      }
782ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng
78319068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng      this.descriptor = descriptor;
78419068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng      this.type = type;
78519068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng
786ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng      switch (descriptor.getJavaType()) {
78719068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng        case MESSAGE:
78819068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng          enumValueOf = null;
78919068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng          enumGetValueDescriptor = null;
79019068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng          messageDefaultInstance =
79119068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng            (Message) invokeOrDie(getMethodOrDie(type, "getDefaultInstance"),
79219068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng                                  null);
79319068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng          if (messageDefaultInstance == null) {
794ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng            throw new IllegalStateException(
79519068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng                type.getName() + ".getDefaultInstance() returned null.");
79619068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng          }
79719068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng          break;
79819068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng        case ENUM:
79919068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng          enumValueOf = getMethodOrDie(type, "valueOf",
80019068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng                                       EnumValueDescriptor.class);
801ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng          enumGetValueDescriptor = getMethodOrDie(type, "getValueDescriptor");
80219068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng          messageDefaultInstance = null;
803334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          break;
80419068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng        default:
80519068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng          enumValueOf = null;
80619068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng          enumGetValueDescriptor = null;
80719068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng          messageDefaultInstance = null;
80819068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng          break;
809ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng      }
81019068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    }
81119068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng
81219068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    private FieldDescriptor descriptor;
813ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng    private Class type;
814ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng    private Method enumValueOf;
815ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng    private Method enumGetValueDescriptor;
81619068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    private Message messageDefaultInstance;
81719068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng
81819068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    public FieldDescriptor getDescriptor() { return descriptor; }
819ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng
82019068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    /**
82119068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng     * If the extension is an embedded message or group, returns the default
82219068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng     * instance of the message.
82319068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng     */
82419068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    @SuppressWarnings("unchecked")
82519068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    public Message getMessageDefaultInstance() {
826ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng      return messageDefaultInstance;
827ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng    }
82819068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng
82919068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    /**
830e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach     * Convert from the type used by the reflection accessors to the type used
831334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * by native accessors.  E.g., for enums, the reflection accessors use
832334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * EnumValueDescriptors but the native accessors use the generated enum
833334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * type.
834334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     */
835ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng    @SuppressWarnings("unchecked")
836334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    private Object fromReflectionType(final Object value) {
837334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      if (descriptor.isRepeated()) {
838e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach        if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE ||
839ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng            descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
840ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng          // Must convert the whole list.
841334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          final List result = new ArrayList();
842334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          for (final Object element : (List) value) {
843334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            result.add(singularFromReflectionType(element));
844334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          }
845ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng          return result;
846334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        } else {
847334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          return value;
848e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach        }
849334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      } else {
850334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        return singularFromReflectionType(value);
851334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
852ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng    }
853ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng
854334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /**
855334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * Like {@link #fromReflectionType(Object)}, but if the type is a repeated
856334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * type, this converts a single element.
857e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach     */
858334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    private Object singularFromReflectionType(final Object value) {
859334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      switch (descriptor.getJavaType()) {
860334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        case MESSAGE:
861334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          if (type.isInstance(value)) {
862ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng            return value;
863334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          } else {
864334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            // It seems the copy of the embedded message stored inside the
865e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach            // extended message is not of the exact type the user was
866ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng            // expecting.  This can happen if a user defines a
867ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng            // GeneratedExtension manually and gives it a different type.
868ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng            // This should not happen in normal use.  But, to be nice, we'll
869334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            // copy the message to whatever type the caller was expecting.
870334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin            return messageDefaultInstance.newBuilderForType()
871334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin                           .mergeFrom((Message) value).build();
872ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng          }
873334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        case ENUM:
874334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value);
875e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach        default:
876334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          return value;
877334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
878334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
879ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng
880ed3ad212ec34fa2866fb70f9e52ddda31032ea3bEvan Cheng    /**
881334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * Convert from the type used by the native accessors to the type used
882334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * by reflection accessors.  E.g., for enums, the reflection accessors use
883334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * EnumValueDescriptors but the native accessors use the generated enum
884334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     * type.
885334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin     */
886334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    @SuppressWarnings("unchecked")
887334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    private Object toReflectionType(final Object value) {
888764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach      if (descriptor.isRepeated()) {
889334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
890334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          // Must convert the whole list.
891334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          final List result = new ArrayList();
892334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          for (final Object element : (List) value) {
8931f5c9887544ac2cb39d48e35cc6fa7a7b73ed3b0Evan Cheng            result.add(singularToReflectionType(element));
894334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          }
895334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          return result;
896334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        } else {
897334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin          return value;
898334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        }
899229464564243b24fb12cece515d727673e726994Evan Cheng      } else {
900334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        return singularToReflectionType(value);
901334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
902334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
9035732ca084aaa0cd26149e50dd4b487efff37fe41Evan Cheng
904334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    /**
905229464564243b24fb12cece515d727673e726994Evan Cheng     * Like {@link #toReflectionType(Object)}, but if the type is a repeated
906229464564243b24fb12cece515d727673e726994Evan Cheng     * type, this converts a single element.
90719068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng     */
90819068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng    private Object singularToReflectionType(final Object value) {
90919068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng      switch (descriptor.getJavaType()) {
91019068ba71a480d9b5032fd9f87eb412e8beb09f4Evan Cheng        case ENUM:
911e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach          return invokeOrDie(enumGetValueDescriptor, value);
912334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin        default:
913e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach          return value;
914334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin      }
915334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin    }
916334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  }
917334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin
918334c26473bba3ad8b88341bb0d25d0ac2008bb8dDavid Goodwin  // =================================================================
9195ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng
920fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng  /** Calls Class.getMethod and throws a RuntimeException if it fails. */
921fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng  @SuppressWarnings("unchecked")
922fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng  private static Method getMethodOrDie(
923fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng      final Class clazz, final String name, final Class... params) {
924d57cdd5683ea926e489067364fb7ffe5fd5d35eeEvan Cheng    try {
925d57cdd5683ea926e489067364fb7ffe5fd5d35eeEvan Cheng      return clazz.getMethod(name, params);
926fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng    } catch (NoSuchMethodException e) {
927d57cdd5683ea926e489067364fb7ffe5fd5d35eeEvan Cheng      throw new RuntimeException(
928d57cdd5683ea926e489067364fb7ffe5fd5d35eeEvan Cheng        "Generated message class \"" + clazz.getName() +
929d57cdd5683ea926e489067364fb7ffe5fd5d35eeEvan Cheng        "\" missing method \"" + name + "\".", e);
930d57cdd5683ea926e489067364fb7ffe5fd5d35eeEvan Cheng    }
931d57cdd5683ea926e489067364fb7ffe5fd5d35eeEvan Cheng  }
932d57cdd5683ea926e489067364fb7ffe5fd5d35eeEvan Cheng
933fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng  /** Calls invoke and throws a RuntimeException if it fails. */
934fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng  private static Object invokeOrDie(
935fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng      final Method method, final Object object, final Object... params) {
936fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng    try {
937fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng      return method.invoke(object, params);
938fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng    } catch (IllegalAccessException e) {
939fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng      throw new RuntimeException(
940fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng        "Couldn't use Java reflection to implement protocol message " +
941fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng        "reflection.", e);
942fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng    } catch (InvocationTargetException e) {
943fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng      final Throwable cause = e.getCause();
944fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng      if (cause instanceof RuntimeException) {
945fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng        throw (RuntimeException) cause;
946fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng      } else if (cause instanceof Error) {
947fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng        throw (Error) cause;
948fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng      } else {
949fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng        throw new RuntimeException(
950fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng          "Unexpected exception thrown by generated accessor method.", cause);
951fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng      }
952fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng    }
953fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng  }
954fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng
955fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng  /**
956fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng   * Users should ignore this class.  This class provides the implementation
957fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng   * with access to the fields of a message object using Java reflection.
958fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng   */
959fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng  public static final class FieldAccessorTable {
960fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng
961fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng    /**
962fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng     * Construct a FieldAccessorTable for a particular message class.  Only
963fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng     * one FieldAccessorTable should ever be constructed per class.
964fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng     *
965fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng     * @param descriptor     The type's descriptor.
966fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng     * @param camelCaseNames The camelcase names of all fields in the message.
967fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng     *                       These are used to derive the accessor method names.
968fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng     * @param messageClass   The message type.
969fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng     * @param builderClass   The builder type.
970fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng     */
971fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng    public FieldAccessorTable(
972fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng        final Descriptor descriptor,
973fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng        final String[] camelCaseNames,
974fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng        final Class<? extends GeneratedMessage> messageClass,
975fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng        final Class<? extends Builder> builderClass) {
976fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng      this.descriptor = descriptor;
977fdc834046efd427d474e3b899ec69354c05071e0Evan Cheng      fields = new FieldAccessor[descriptor.getFields().size()];
978d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng
979d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng      for (int i = 0; i < fields.length; i++) {
980d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng        final FieldDescriptor field = descriptor.getFields().get(i);
981d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng        if (field.isRepeated()) {
982d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng          if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
983d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng            fields[i] = new RepeatedMessageFieldAccessor(
984d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng              field, camelCaseNames[i], messageClass, builderClass);
985d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng          } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
986d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng            fields[i] = new RepeatedEnumFieldAccessor(
987d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng              field, camelCaseNames[i], messageClass, builderClass);
988d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng          } else {
989d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng            fields[i] = new RepeatedFieldAccessor(
990d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng              field, camelCaseNames[i], messageClass, builderClass);
991d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng          }
992d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng        } else {
993d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng          if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
994d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng            fields[i] = new SingularMessageFieldAccessor(
995d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng              field, camelCaseNames[i], messageClass, builderClass);
996d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng          } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
997d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng            fields[i] = new SingularEnumFieldAccessor(
998d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng              field, camelCaseNames[i], messageClass, builderClass);
999d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng          } else {
1000d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng            fields[i] = new SingularFieldAccessor(
1001d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng              field, camelCaseNames[i], messageClass, builderClass);
1002d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng          }
1003d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng        }
1004d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng      }
1005d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng    }
1006d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng
1007d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng    private final Descriptor descriptor;
1008d457e6e9a5cd975baf4d1f0578382ab8373e6153Evan Cheng    private final FieldAccessor[] fields;
10098fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng
10108fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng    /** Get the FieldAccessor for a particular field. */
10118fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng    private FieldAccessor getField(final FieldDescriptor field) {
10125adb66a646e2ec32265263739f5b01c3f50c176aEvan Cheng      if (field.getContainingType() != descriptor) {
10135adb66a646e2ec32265263739f5b01c3f50c176aEvan Cheng        throw new IllegalArgumentException(
10148fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng          "FieldDescriptor does not match message type.");
10158fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng      } else if (field.isExtension()) {
10168fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng        // If this type had extensions, it would subclass ExtendableMessage,
10178fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng        // which overrides the reflection interface to handle extensions.
10188fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng        throw new IllegalArgumentException(
10198fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng          "This type does not have extensions.");
10208fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng      }
10218fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng      return fields[field.getIndex()];
10228fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng    }
10238fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng
10248fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng    /**
10256495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng     * Abstract interface that provides access to a single field.  This is
10265ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng     * implemented differently depending on the field type and cardinality.
10275ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng     */
10285ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng    private interface FieldAccessor {
10295ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng      Object get(GeneratedMessage message);
10305ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng      void set(Builder builder, Object value);
10315ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng      Object getRepeated(GeneratedMessage message, int index);
10325ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng      void setRepeated(Builder builder,
10335ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng                       int index, Object value);
10345ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng      void addRepeated(Builder builder, Object value);
10355ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng      boolean has(GeneratedMessage message);
10365ca53a7ad821613d324e4189ddbb0d468a326146Evan Cheng      int getRepeatedCount(GeneratedMessage message);
10376495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      void clear(Builder builder);
10386495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      Message.Builder newBuilder();
10396495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng    }
10406495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng
10416495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng    // ---------------------------------------------------------------
10426495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng
10436495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng    private static class SingularFieldAccessor implements FieldAccessor {
10446495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      SingularFieldAccessor(
10456495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          final FieldDescriptor descriptor, final String camelCaseName,
10466495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          final Class<? extends GeneratedMessage> messageClass,
10476495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          final Class<? extends Builder> builderClass) {
10486495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
10496495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        type = getMethod.getReturnType();
10506495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
10516495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        hasMethod =
10526495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          getMethodOrDie(messageClass, "has" + camelCaseName);
10536495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
10546495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
10556495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng
10566495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      // Note:  We use Java reflection to call public methods rather than
10576495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      //   access private fields directly as this avoids runtime security
10586495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      //   checks.
10596495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      protected final Class type;
10606495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      protected final Method getMethod;
10616495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      protected final Method setMethod;
10626495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      protected final Method hasMethod;
10636495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      protected final Method clearMethod;
10646495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng
1065cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng      public Object get(final GeneratedMessage message) {
1066cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng        return invokeOrDie(getMethod, message);
1067cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng      }
10686495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public void set(final Builder builder, final Object value) {
10696495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        invokeOrDie(setMethod, builder, value);
10706495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
10716495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public Object getRepeated(final GeneratedMessage message,
1072764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach                                final int index) {
10736495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        throw new UnsupportedOperationException(
10746495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          "getRepeatedField() called on a singular field.");
10756495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
1076764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach      public void setRepeated(final Builder builder,
10776495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng                              final int index, final Object value) {
10786495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        throw new UnsupportedOperationException(
10796495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          "setRepeatedField() called on a singular field.");
10806495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
10816495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public void addRepeated(final Builder builder, final Object value) {
10826495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        throw new UnsupportedOperationException(
10836495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          "addRepeatedField() called on a singular field.");
1084cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng      }
1085cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng      public boolean has(final GeneratedMessage message) {
10866495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        return (Boolean) invokeOrDie(hasMethod, message);
10876495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
10886495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public int getRepeatedCount(final GeneratedMessage message) {
10896495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        throw new UnsupportedOperationException(
10906495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          "getRepeatedFieldSize() called on a singular field.");
10916495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
10926495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public void clear(final Builder builder) {
10936495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        invokeOrDie(clearMethod, builder);
10946495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
10956495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public Message.Builder newBuilder() {
10966495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        throw new UnsupportedOperationException(
1097cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng          "newBuilderForField() called on a non-Message type.");
1098cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng      }
10996495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng    }
11006495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng
11016495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng    private static class RepeatedFieldAccessor implements FieldAccessor {
11026495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      RepeatedFieldAccessor(
11036495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          final FieldDescriptor descriptor, final String camelCaseName,
11046495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          final Class<? extends GeneratedMessage> messageClass,
11056495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          final Class<? extends Builder> builderClass) {
11066495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        getMethod = getMethodOrDie(messageClass,
11076495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng                                   "get" + camelCaseName + "List");
11086495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng
11096495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        getRepeatedMethod =
11106495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
11116495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        type = getRepeatedMethod.getReturnType();
11126495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        setRepeatedMethod =
11136495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          getMethodOrDie(builderClass, "set" + camelCaseName,
11146495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng                         Integer.TYPE, type);
11156495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        addRepeatedMethod =
11166495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          getMethodOrDie(builderClass, "add" + camelCaseName, type);
11176495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        getCountMethod =
11186495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          getMethodOrDie(messageClass, "get" + camelCaseName + "Count");
11196495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng
11206495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
11216495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
11226495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng
11236495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      protected final Class type;
11246495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      protected final Method getMethod;
11256495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      protected final Method getRepeatedMethod;
11266495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      protected final Method setRepeatedMethod;
11276495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      protected final Method addRepeatedMethod;
11286495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      protected final Method getCountMethod;
11296495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      protected final Method clearMethod;
11306495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng
11316495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public Object get(final GeneratedMessage message) {
11326495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        return invokeOrDie(getMethod, message);
11336495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
11346495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public void set(final Builder builder, final Object value) {
1135baf31088f1472f48ea5ae81f0b93636cc44ca444Anton Korobeynikov        // Add all the elements individually.  This serves two purposes:
1136cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng        // 1) Verifies that each element has the correct type.
1137cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng        // 2) Insures that the caller cannot modify the list later on and
11386495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        //    have the modifications be reflected in the message.
11396495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        clear(builder);
11406495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        for (final Object element : (List) value) {
11416495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          addRepeated(builder, element);
11426495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        }
11436495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
11446495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public Object getRepeated(final GeneratedMessage message,
11456495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng                                final int index) {
11466495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        return invokeOrDie(getRepeatedMethod, message, index);
11476495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
11486495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public void setRepeated(final Builder builder,
11496495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng                              final int index, final Object value) {
11506495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        invokeOrDie(setRepeatedMethod, builder, index, value);
11516495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
11526495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public void addRepeated(final Builder builder, final Object value) {
11536495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        invokeOrDie(addRepeatedMethod, builder, value);
11546495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
11556495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public boolean has(final GeneratedMessage message) {
11566495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        throw new UnsupportedOperationException(
11576495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          "hasField() called on a singular field.");
11586495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
11596495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public int getRepeatedCount(final GeneratedMessage message) {
11606495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        return (Integer) invokeOrDie(getCountMethod, message);
11616495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
11626495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public void clear(final Builder builder) {
11636495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        invokeOrDie(clearMethod, builder);
11646495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
11656495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      public Message.Builder newBuilder() {
11666495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        throw new UnsupportedOperationException(
11676495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          "newBuilderForField() called on a non-Message type.");
11686495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      }
11696495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng    }
11706495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng
1171cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng    // ---------------------------------------------------------------
1172cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng
11736495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng    private static final class SingularEnumFieldAccessor
1174764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach        extends SingularFieldAccessor {
11756495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng      SingularEnumFieldAccessor(
11766495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          final FieldDescriptor descriptor, final String camelCaseName,
11776495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          final Class<? extends GeneratedMessage> messageClass,
11786495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng          final Class<? extends Builder> builderClass) {
11796495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        super(descriptor, camelCaseName, messageClass, builderClass);
11806495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng
11816495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        valueOfMethod = getMethodOrDie(type, "valueOf",
11826495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng                                       EnumValueDescriptor.class);
11836495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng        getValueDescriptorMethod =
1184cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng          getMethodOrDie(type, "getValueDescriptor");
1185cdbb3f5d3311e0f46d22bc8daa211b2fab3541cbEvan Cheng      }
11866495f63945e8dbde81f03a1dc2ab421993b9a495Evan Cheng
1187      private Method valueOfMethod;
1188      private Method getValueDescriptorMethod;
1189
1190      @Override
1191      public Object get(final GeneratedMessage message) {
1192        return invokeOrDie(getValueDescriptorMethod, super.get(message));
1193      }
1194      @Override
1195      public void set(final Builder builder, final Object value) {
1196        super.set(builder, invokeOrDie(valueOfMethod, null, value));
1197      }
1198    }
1199
1200    private static final class RepeatedEnumFieldAccessor
1201        extends RepeatedFieldAccessor {
1202      RepeatedEnumFieldAccessor(
1203          final FieldDescriptor descriptor, final String camelCaseName,
1204          final Class<? extends GeneratedMessage> messageClass,
1205          final Class<? extends Builder> builderClass) {
1206        super(descriptor, camelCaseName, messageClass, builderClass);
1207
1208        valueOfMethod = getMethodOrDie(type, "valueOf",
1209                                       EnumValueDescriptor.class);
1210        getValueDescriptorMethod =
1211          getMethodOrDie(type, "getValueDescriptor");
1212      }
1213
1214      private final Method valueOfMethod;
1215      private final Method getValueDescriptorMethod;
1216
1217      @Override
1218      @SuppressWarnings("unchecked")
1219      public Object get(final GeneratedMessage message) {
1220        final List newList = new ArrayList();
1221        for (final Object element : (List) super.get(message)) {
1222          newList.add(invokeOrDie(getValueDescriptorMethod, element));
1223        }
1224        return Collections.unmodifiableList(newList);
1225      }
1226      @Override
1227      public Object getRepeated(final GeneratedMessage message,
1228                                final int index) {
1229        return invokeOrDie(getValueDescriptorMethod,
1230          super.getRepeated(message, index));
1231      }
1232      @Override
1233      public void setRepeated(final Builder builder,
1234                              final int index, final Object value) {
1235        super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null,
1236                          value));
1237      }
1238      @Override
1239      public void addRepeated(final Builder builder, final Object value) {
1240        super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value));
1241      }
1242    }
1243
1244    // ---------------------------------------------------------------
1245
1246    private static final class SingularMessageFieldAccessor
1247        extends SingularFieldAccessor {
1248      SingularMessageFieldAccessor(
1249          final FieldDescriptor descriptor, final String camelCaseName,
1250          final Class<? extends GeneratedMessage> messageClass,
1251          final Class<? extends Builder> builderClass) {
1252        super(descriptor, camelCaseName, messageClass, builderClass);
1253
1254        newBuilderMethod = getMethodOrDie(type, "newBuilder");
1255      }
1256
1257      private final Method newBuilderMethod;
1258
1259      private Object coerceType(final Object value) {
1260        if (type.isInstance(value)) {
1261          return value;
1262        } else {
1263          // The value is not the exact right message type.  However, if it
1264          // is an alternative implementation of the same type -- e.g. a
1265          // DynamicMessage -- we should accept it.  In this case we can make
1266          // a copy of the message.
1267          return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
1268                  .mergeFrom((Message) value).build();
1269        }
1270      }
1271
1272      @Override
1273      public void set(final Builder builder, final Object value) {
1274        super.set(builder, coerceType(value));
1275      }
1276      @Override
1277      public Message.Builder newBuilder() {
1278        return (Message.Builder) invokeOrDie(newBuilderMethod, null);
1279      }
1280    }
1281
1282    private static final class RepeatedMessageFieldAccessor
1283        extends RepeatedFieldAccessor {
1284      RepeatedMessageFieldAccessor(
1285          final FieldDescriptor descriptor, final String camelCaseName,
1286          final Class<? extends GeneratedMessage> messageClass,
1287          final Class<? extends Builder> builderClass) {
1288        super(descriptor, camelCaseName, messageClass, builderClass);
1289
1290        newBuilderMethod = getMethodOrDie(type, "newBuilder");
1291      }
1292
1293      private final Method newBuilderMethod;
1294
1295      private Object coerceType(final Object value) {
1296        if (type.isInstance(value)) {
1297          return value;
1298        } else {
1299          // The value is not the exact right message type.  However, if it
1300          // is an alternative implementation of the same type -- e.g. a
1301          // DynamicMessage -- we should accept it.  In this case we can make
1302          // a copy of the message.
1303          return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
1304                  .mergeFrom((Message) value).build();
1305        }
1306      }
1307
1308      @Override
1309      public void setRepeated(final Builder builder,
1310                              final int index, final Object value) {
1311        super.setRepeated(builder, index, coerceType(value));
1312      }
1313      @Override
1314      public void addRepeated(final Builder builder, final Object value) {
1315        super.addRepeated(builder, coerceType(value));
1316      }
1317      @Override
1318      public Message.Builder newBuilder() {
1319        return (Message.Builder) invokeOrDie(newBuilderMethod, null);
1320      }
1321    }
1322  }
1323}
1324