1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 package com.google.protobuf; 32 33 import com.google.protobuf.Descriptors.Descriptor; 34 import com.google.protobuf.Descriptors.EnumValueDescriptor; 35 import com.google.protobuf.Descriptors.FieldDescriptor; 36 37 import java.io.IOException; 38 import java.util.Collections; 39 import java.util.Map; 40 import java.util.TreeMap; 41 42 /** 43 * Implements MapEntry messages. 44 * 45 * In reflection API, map fields will be treated as repeated message fields and 46 * each map entry is accessed as a message. This MapEntry class is used to 47 * represent these map entry messages in reflection API. 48 * 49 * Protobuf internal. Users shouldn't use this class. 50 */ 51 public final class MapEntry<K, V> extends AbstractMessage { 52 private static class Metadata<K, V> { 53 public final Descriptor descriptor; 54 public final MapEntry<K, V> defaultInstance; 55 public final AbstractParser<MapEntry<K, V>> parser; 56 Metadata( final Descriptor descriptor, final MapEntry<K, V> defaultInstance)57 public Metadata( 58 final Descriptor descriptor, final MapEntry<K, V> defaultInstance) { 59 this.descriptor = descriptor; 60 this.defaultInstance = defaultInstance; 61 final Metadata<K, V> thisMetadata = this; 62 this.parser = new AbstractParser<MapEntry<K, V>>() { 63 private final Parser<MapEntryLite<K, V>> dataParser = 64 defaultInstance.data.getParserForType(); 65 @Override 66 public MapEntry<K, V> parsePartialFrom( 67 CodedInputStream input, ExtensionRegistryLite extensionRegistry) 68 throws InvalidProtocolBufferException { 69 MapEntryLite<K, V> data = 70 dataParser.parsePartialFrom(input, extensionRegistry); 71 return new MapEntry<K, V>(thisMetadata, data); 72 } 73 74 }; 75 } 76 } 77 78 private final Metadata<K, V> metadata; 79 private final MapEntryLite<K, V> data; 80 81 /** Create a default MapEntry instance. */ MapEntry(Descriptor descriptor, WireFormat.FieldType keyType, K defaultKey, WireFormat.FieldType valueType, V defaultValue)82 private MapEntry(Descriptor descriptor, 83 WireFormat.FieldType keyType, K defaultKey, 84 WireFormat.FieldType valueType, V defaultValue) { 85 this.data = MapEntryLite.newDefaultInstance( 86 keyType, defaultKey, valueType, defaultValue); 87 this.metadata = new Metadata<K, V>(descriptor, this); 88 } 89 90 /** Create a new MapEntry message. */ MapEntry(Metadata<K, V> metadata, MapEntryLite<K, V> data)91 private MapEntry(Metadata<K, V> metadata, MapEntryLite<K, V> data) { 92 this.metadata = metadata; 93 this.data = data; 94 } 95 96 /** 97 * Create a default MapEntry instance. A default MapEntry instance should be 98 * created only once for each map entry message type. Generated code should 99 * store the created default instance and use it later to create new MapEntry 100 * messages of the same type. 101 */ newDefaultInstance( Descriptor descriptor, WireFormat.FieldType keyType, K defaultKey, WireFormat.FieldType valueType, V defaultValue)102 public static <K, V> MapEntry<K, V> newDefaultInstance( 103 Descriptor descriptor, 104 WireFormat.FieldType keyType, K defaultKey, 105 WireFormat.FieldType valueType, V defaultValue) { 106 return new MapEntry<K, V>( 107 descriptor, keyType, defaultKey, valueType, defaultValue); 108 } 109 getKey()110 public K getKey() { 111 return data.getKey(); 112 } 113 getValue()114 public V getValue() { 115 return data.getValue(); 116 } 117 118 @Override getSerializedSize()119 public int getSerializedSize() { 120 return data.getSerializedSize(); 121 } 122 123 @Override writeTo(CodedOutputStream output)124 public void writeTo(CodedOutputStream output) throws IOException { 125 data.writeTo(output); 126 } 127 128 @Override isInitialized()129 public boolean isInitialized() { 130 return data.isInitialized(); 131 } 132 133 @Override getParserForType()134 public Parser<MapEntry<K, V>> getParserForType() { 135 return metadata.parser; 136 } 137 138 @Override newBuilderForType()139 public Builder<K, V> newBuilderForType() { 140 return new Builder<K, V>(metadata); 141 } 142 143 @Override toBuilder()144 public Builder<K, V> toBuilder() { 145 return new Builder<K, V>(metadata, data); 146 } 147 148 @Override getDefaultInstanceForType()149 public MapEntry<K, V> getDefaultInstanceForType() { 150 return metadata.defaultInstance; 151 } 152 153 @Override getDescriptorForType()154 public Descriptor getDescriptorForType() { 155 return metadata.descriptor; 156 } 157 158 @Override getAllFields()159 public Map<FieldDescriptor, Object> getAllFields() { 160 final TreeMap<FieldDescriptor, Object> result = 161 new TreeMap<FieldDescriptor, Object>(); 162 for (final FieldDescriptor field : metadata.descriptor.getFields()) { 163 if (hasField(field)) { 164 result.put(field, getField(field)); 165 } 166 } 167 return Collections.unmodifiableMap(result); 168 } 169 checkFieldDescriptor(FieldDescriptor field)170 private void checkFieldDescriptor(FieldDescriptor field) { 171 if (field.getContainingType() != metadata.descriptor) { 172 throw new RuntimeException( 173 "Wrong FieldDescriptor \"" + field.getFullName() 174 + "\" used in message \"" + metadata.descriptor.getFullName()); 175 } 176 } 177 178 @Override hasField(FieldDescriptor field)179 public boolean hasField(FieldDescriptor field) { 180 checkFieldDescriptor(field);; 181 // A MapEntry always contains two fields. 182 return true; 183 } 184 185 @Override getField(FieldDescriptor field)186 public Object getField(FieldDescriptor field) { 187 checkFieldDescriptor(field); 188 Object result = field.getNumber() == 1 ? getKey() : getValue(); 189 // Convert enums to EnumValueDescriptor. 190 if (field.getType() == FieldDescriptor.Type.ENUM) { 191 result = field.getEnumType().findValueByNumberCreatingIfUnknown( 192 (java.lang.Integer) result); 193 } 194 return result; 195 } 196 197 @Override getRepeatedFieldCount(FieldDescriptor field)198 public int getRepeatedFieldCount(FieldDescriptor field) { 199 throw new RuntimeException( 200 "There is no repeated field in a map entry message."); 201 } 202 203 @Override getRepeatedField(FieldDescriptor field, int index)204 public Object getRepeatedField(FieldDescriptor field, int index) { 205 throw new RuntimeException( 206 "There is no repeated field in a map entry message."); 207 } 208 209 @Override getUnknownFields()210 public UnknownFieldSet getUnknownFields() { 211 return UnknownFieldSet.getDefaultInstance(); 212 } 213 214 /** 215 * Builder to create {@link MapEntry} messages. 216 */ 217 public static class Builder<K, V> 218 extends AbstractMessage.Builder<Builder<K, V>> { 219 private final Metadata<K, V> metadata; 220 private MapEntryLite<K, V> data; 221 private MapEntryLite.Builder<K, V> dataBuilder; 222 Builder(Metadata<K, V> metadata)223 private Builder(Metadata<K, V> metadata) { 224 this.metadata = metadata; 225 this.data = metadata.defaultInstance.data; 226 this.dataBuilder = null; 227 } 228 Builder(Metadata<K, V> metadata, MapEntryLite<K, V> data)229 private Builder(Metadata<K, V> metadata, MapEntryLite<K, V> data) { 230 this.metadata = metadata; 231 this.data = data; 232 this.dataBuilder = null; 233 } 234 getKey()235 public K getKey() { 236 return dataBuilder == null ? data.getKey() : dataBuilder.getKey(); 237 } 238 getValue()239 public V getValue() { 240 return dataBuilder == null ? data.getValue() : dataBuilder.getValue(); 241 } 242 ensureMutable()243 private void ensureMutable() { 244 if (dataBuilder == null) { 245 dataBuilder = data.toBuilder(); 246 } 247 } 248 setKey(K key)249 public Builder<K, V> setKey(K key) { 250 ensureMutable(); 251 dataBuilder.setKey(key); 252 return this; 253 } 254 clearKey()255 public Builder<K, V> clearKey() { 256 ensureMutable(); 257 dataBuilder.clearKey(); 258 return this; 259 } 260 setValue(V value)261 public Builder<K, V> setValue(V value) { 262 ensureMutable(); 263 dataBuilder.setValue(value); 264 return this; 265 } 266 clearValue()267 public Builder<K, V> clearValue() { 268 ensureMutable(); 269 dataBuilder.clearValue(); 270 return this; 271 } 272 273 @Override build()274 public MapEntry<K, V> build() { 275 MapEntry<K, V> result = buildPartial(); 276 if (!result.isInitialized()) { 277 throw newUninitializedMessageException(result); 278 } 279 return result; 280 } 281 282 @Override buildPartial()283 public MapEntry<K, V> buildPartial() { 284 if (dataBuilder != null) { 285 data = dataBuilder.buildPartial(); 286 dataBuilder = null; 287 } 288 return new MapEntry<K, V>(metadata, data); 289 } 290 291 @Override getDescriptorForType()292 public Descriptor getDescriptorForType() { 293 return metadata.descriptor; 294 } 295 checkFieldDescriptor(FieldDescriptor field)296 private void checkFieldDescriptor(FieldDescriptor field) { 297 if (field.getContainingType() != metadata.descriptor) { 298 throw new RuntimeException( 299 "Wrong FieldDescriptor \"" + field.getFullName() 300 + "\" used in message \"" + metadata.descriptor.getFullName()); 301 } 302 } 303 304 @Override newBuilderForField( FieldDescriptor field)305 public com.google.protobuf.Message.Builder newBuilderForField( 306 FieldDescriptor field) { 307 checkFieldDescriptor(field);; 308 // This method should be called for message fields and in a MapEntry 309 // message only the value field can possibly be a message field. 310 if (field.getNumber() != 2 311 || field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { 312 throw new RuntimeException( 313 "\"" + field.getFullName() + "\" is not a message value field."); 314 } 315 return ((Message) data.getValue()).newBuilderForType(); 316 } 317 318 @SuppressWarnings("unchecked") 319 @Override setField(FieldDescriptor field, Object value)320 public Builder<K, V> setField(FieldDescriptor field, Object value) { 321 checkFieldDescriptor(field); 322 if (field.getNumber() == 1) { 323 setKey((K) value); 324 } else { 325 if (field.getType() == FieldDescriptor.Type.ENUM) { 326 value = ((EnumValueDescriptor) value).getNumber(); 327 } 328 setValue((V) value); 329 } 330 return this; 331 } 332 333 @Override clearField(FieldDescriptor field)334 public Builder<K, V> clearField(FieldDescriptor field) { 335 checkFieldDescriptor(field); 336 if (field.getNumber() == 1) { 337 clearKey(); 338 } else { 339 clearValue(); 340 } 341 return this; 342 } 343 344 @Override setRepeatedField(FieldDescriptor field, int index, Object value)345 public Builder<K, V> setRepeatedField(FieldDescriptor field, int index, 346 Object value) { 347 throw new RuntimeException( 348 "There is no repeated field in a map entry message."); 349 } 350 351 @Override addRepeatedField(FieldDescriptor field, Object value)352 public Builder<K, V> addRepeatedField(FieldDescriptor field, Object value) { 353 throw new RuntimeException( 354 "There is no repeated field in a map entry message."); 355 } 356 357 @Override setUnknownFields(UnknownFieldSet unknownFields)358 public Builder<K, V> setUnknownFields(UnknownFieldSet unknownFields) { 359 // Unknown fields are discarded for MapEntry message. 360 return this; 361 } 362 363 @Override getDefaultInstanceForType()364 public MapEntry<K, V> getDefaultInstanceForType() { 365 return metadata.defaultInstance; 366 } 367 368 @Override isInitialized()369 public boolean isInitialized() { 370 if (dataBuilder != null) { 371 return dataBuilder.isInitialized(); 372 } else { 373 return data.isInitialized(); 374 } 375 } 376 377 @Override getAllFields()378 public Map<FieldDescriptor, Object> getAllFields() { 379 final TreeMap<FieldDescriptor, Object> result = 380 new TreeMap<FieldDescriptor, Object>(); 381 for (final FieldDescriptor field : metadata.descriptor.getFields()) { 382 if (hasField(field)) { 383 result.put(field, getField(field)); 384 } 385 } 386 return Collections.unmodifiableMap(result); 387 } 388 389 @Override hasField(FieldDescriptor field)390 public boolean hasField(FieldDescriptor field) { 391 checkFieldDescriptor(field); 392 return true; 393 } 394 395 @Override getField(FieldDescriptor field)396 public Object getField(FieldDescriptor field) { 397 checkFieldDescriptor(field); 398 Object result = field.getNumber() == 1 ? getKey() : getValue(); 399 // Convert enums to EnumValueDescriptor. 400 if (field.getType() == FieldDescriptor.Type.ENUM) { 401 result = field.getEnumType().findValueByNumberCreatingIfUnknown( 402 (java.lang.Integer) result); 403 } 404 return result; 405 } 406 407 @Override getRepeatedFieldCount(FieldDescriptor field)408 public int getRepeatedFieldCount(FieldDescriptor field) { 409 throw new RuntimeException( 410 "There is no repeated field in a map entry message."); 411 } 412 413 @Override getRepeatedField(FieldDescriptor field, int index)414 public Object getRepeatedField(FieldDescriptor field, int index) { 415 throw new RuntimeException( 416 "There is no repeated field in a map entry message."); 417 } 418 419 @Override getUnknownFields()420 public UnknownFieldSet getUnknownFields() { 421 return UnknownFieldSet.getDefaultInstance(); 422 } 423 424 @Override clone()425 public Builder<K, V> clone() { 426 if (dataBuilder == null) { 427 return new Builder<K, V>(metadata, data); 428 } else { 429 return new Builder<K, V>(metadata, dataBuilder.build()); 430 } 431 } 432 } 433 } 434