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