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 static com.google.protobuf.Internal.checkNotNull; 34 35 import java.util.ArrayList; 36 import java.util.Collection; 37 import java.util.Collections; 38 import java.util.Iterator; 39 import java.util.LinkedHashMap; 40 import java.util.List; 41 import java.util.Map; 42 import java.util.Set; 43 44 /** 45 * Internal representation of map fields in generated messages. 46 * 47 * <p>This class supports accessing the map field as a {@link Map} to be used in generated API and 48 * also supports accessing the field as a {@link List} to be used in reflection API. It keeps track 49 * of where the data is currently stored and do necessary conversions between map and list. 50 * 51 * <p>This class is a protobuf implementation detail. Users shouldn't use this class directly. 52 * 53 * <p>THREAD-SAFETY NOTE: Read-only access is thread-safe. Users can call getMap() and getList() 54 * concurrently in multiple threads. If write-access is needed, all access must be synchronized. 55 */ 56 public class MapField<K, V> implements MutabilityOracle { 57 58 /** 59 * Indicates where the data of this map field is currently stored. 60 * 61 * <ul> 62 * <li>MAP: Data is stored in mapData. 63 * <li>LIST: Data is stored in listData. 64 * <li>BOTH: mapData and listData have the same data. 65 * </ul> 66 * 67 * <p>When the map field is accessed (through generated API or reflection API), it will shift 68 * between these 3 modes: 69 * 70 * <pre> 71 * <b>getMap() getList() getMutableMap() getMutableList()</b> 72 * <b>MAP</b> MAP BOTH MAP LIST 73 * <b>LIST</b> BOTH LIST MAP LIST 74 * <b>BOTH</b> BOTH BOTH MAP LIST 75 * </pre> 76 * 77 * <p>As the map field changes its mode, the list/map reference returned in a previous method call 78 * may be invalidated. 79 */ 80 private enum StorageMode { 81 MAP, 82 LIST, 83 BOTH 84 } 85 86 private volatile boolean isMutable; 87 private volatile StorageMode mode; 88 private MutatabilityAwareMap<K, V> mapData; 89 private List<Message> listData; 90 91 // Convert between a map entry Message and a key-value pair. 92 private static interface Converter<K, V> { convertKeyAndValueToMessage(K key, V value)93 Message convertKeyAndValueToMessage(K key, V value); 94 convertMessageToKeyAndValue(Message message, Map<K, V> map)95 void convertMessageToKeyAndValue(Message message, Map<K, V> map); 96 getMessageDefaultInstance()97 Message getMessageDefaultInstance(); 98 } 99 100 private static class ImmutableMessageConverter<K, V> implements Converter<K, V> { 101 private final MapEntry<K, V> defaultEntry; 102 ImmutableMessageConverter(MapEntry<K, V> defaultEntry)103 public ImmutableMessageConverter(MapEntry<K, V> defaultEntry) { 104 this.defaultEntry = defaultEntry; 105 } 106 107 @Override convertKeyAndValueToMessage(K key, V value)108 public Message convertKeyAndValueToMessage(K key, V value) { 109 return defaultEntry.newBuilderForType().setKey(key).setValue(value).buildPartial(); 110 } 111 112 @Override 113 @SuppressWarnings("unchecked") convertMessageToKeyAndValue(Message message, Map<K, V> map)114 public void convertMessageToKeyAndValue(Message message, Map<K, V> map) { 115 MapEntry<K, V> entry = (MapEntry<K, V>) message; 116 map.put(entry.getKey(), entry.getValue()); 117 } 118 119 @Override getMessageDefaultInstance()120 public Message getMessageDefaultInstance() { 121 return defaultEntry; 122 } 123 } 124 125 126 private final Converter<K, V> converter; 127 MapField(Converter<K, V> converter, StorageMode mode, Map<K, V> mapData)128 private MapField(Converter<K, V> converter, StorageMode mode, Map<K, V> mapData) { 129 this.converter = converter; 130 this.isMutable = true; 131 this.mode = mode; 132 this.mapData = new MutatabilityAwareMap<K, V>(this, mapData); 133 this.listData = null; 134 } 135 MapField(MapEntry<K, V> defaultEntry, StorageMode mode, Map<K, V> mapData)136 private MapField(MapEntry<K, V> defaultEntry, StorageMode mode, Map<K, V> mapData) { 137 this(new ImmutableMessageConverter<K, V>(defaultEntry), mode, mapData); 138 } 139 140 141 /** Returns an immutable empty MapField. */ emptyMapField(MapEntry<K, V> defaultEntry)142 public static <K, V> MapField<K, V> emptyMapField(MapEntry<K, V> defaultEntry) { 143 return new MapField<K, V>(defaultEntry, StorageMode.MAP, Collections.<K, V>emptyMap()); 144 } 145 146 147 /** Creates a new mutable empty MapField. */ newMapField(MapEntry<K, V> defaultEntry)148 public static <K, V> MapField<K, V> newMapField(MapEntry<K, V> defaultEntry) { 149 return new MapField<K, V>(defaultEntry, StorageMode.MAP, new LinkedHashMap<K, V>()); 150 } 151 152 convertKeyAndValueToMessage(K key, V value)153 private Message convertKeyAndValueToMessage(K key, V value) { 154 return converter.convertKeyAndValueToMessage(key, value); 155 } 156 157 @SuppressWarnings("unchecked") convertMessageToKeyAndValue(Message message, Map<K, V> map)158 private void convertMessageToKeyAndValue(Message message, Map<K, V> map) { 159 converter.convertMessageToKeyAndValue(message, map); 160 } 161 convertMapToList(MutatabilityAwareMap<K, V> mapData)162 private List<Message> convertMapToList(MutatabilityAwareMap<K, V> mapData) { 163 List<Message> listData = new ArrayList<Message>(); 164 for (Map.Entry<K, V> entry : mapData.entrySet()) { 165 listData.add(convertKeyAndValueToMessage(entry.getKey(), entry.getValue())); 166 } 167 return listData; 168 } 169 convertListToMap(List<Message> listData)170 private MutatabilityAwareMap<K, V> convertListToMap(List<Message> listData) { 171 Map<K, V> mapData = new LinkedHashMap<K, V>(); 172 for (Message item : listData) { 173 convertMessageToKeyAndValue(item, mapData); 174 } 175 return new MutatabilityAwareMap<K, V>(this, mapData); 176 } 177 178 /** Returns the content of this MapField as a read-only Map. */ getMap()179 public Map<K, V> getMap() { 180 if (mode == StorageMode.LIST) { 181 synchronized (this) { 182 if (mode == StorageMode.LIST) { 183 mapData = convertListToMap(listData); 184 mode = StorageMode.BOTH; 185 } 186 } 187 } 188 return Collections.unmodifiableMap(mapData); 189 } 190 191 /** Gets a mutable Map view of this MapField. */ getMutableMap()192 public Map<K, V> getMutableMap() { 193 if (mode != StorageMode.MAP) { 194 if (mode == StorageMode.LIST) { 195 mapData = convertListToMap(listData); 196 } 197 listData = null; 198 mode = StorageMode.MAP; 199 } 200 return mapData; 201 } 202 mergeFrom(MapField<K, V> other)203 public void mergeFrom(MapField<K, V> other) { 204 getMutableMap().putAll(MapFieldLite.copy(other.getMap())); 205 } 206 clear()207 public void clear() { 208 mapData = new MutatabilityAwareMap<K, V>(this, new LinkedHashMap<K, V>()); 209 mode = StorageMode.MAP; 210 } 211 212 @SuppressWarnings("unchecked") 213 @Override equals(Object object)214 public boolean equals(Object object) { 215 if (!(object instanceof MapField)) { 216 return false; 217 } 218 MapField<K, V> other = (MapField<K, V>) object; 219 return MapFieldLite.<K, V>equals(getMap(), other.getMap()); 220 } 221 222 @Override hashCode()223 public int hashCode() { 224 return MapFieldLite.<K, V>calculateHashCodeForMap(getMap()); 225 } 226 227 /** Returns a deep copy of this MapField. */ copy()228 public MapField<K, V> copy() { 229 return new MapField<K, V>(converter, StorageMode.MAP, MapFieldLite.copy(getMap())); 230 } 231 232 /** Gets the content of this MapField as a read-only List. */ getList()233 List<Message> getList() { 234 if (mode == StorageMode.MAP) { 235 synchronized (this) { 236 if (mode == StorageMode.MAP) { 237 listData = convertMapToList(mapData); 238 mode = StorageMode.BOTH; 239 } 240 } 241 } 242 return Collections.unmodifiableList(listData); 243 } 244 245 /** Gets a mutable List view of this MapField. */ getMutableList()246 List<Message> getMutableList() { 247 if (mode != StorageMode.LIST) { 248 if (mode == StorageMode.MAP) { 249 listData = convertMapToList(mapData); 250 } 251 mapData = null; 252 mode = StorageMode.LIST; 253 } 254 return listData; 255 } 256 257 /** Gets the default instance of the message stored in the list view of this map field. */ getMapEntryMessageDefaultInstance()258 Message getMapEntryMessageDefaultInstance() { 259 return converter.getMessageDefaultInstance(); 260 } 261 262 /** 263 * Makes this list immutable. All subsequent modifications will throw an {@link 264 * UnsupportedOperationException}. 265 */ makeImmutable()266 public void makeImmutable() { 267 isMutable = false; 268 } 269 270 /** Returns whether this field can be modified. */ isMutable()271 public boolean isMutable() { 272 return isMutable; 273 } 274 275 /* (non-Javadoc) 276 * @see com.google.protobuf.MutabilityOracle#ensureMutable() 277 */ 278 @Override ensureMutable()279 public void ensureMutable() { 280 if (!isMutable()) { 281 throw new UnsupportedOperationException(); 282 } 283 } 284 285 /** An internal map that checks for mutability before delegating. */ 286 private static class MutatabilityAwareMap<K, V> implements Map<K, V> { 287 private final MutabilityOracle mutabilityOracle; 288 private final Map<K, V> delegate; 289 MutatabilityAwareMap(MutabilityOracle mutabilityOracle, Map<K, V> delegate)290 MutatabilityAwareMap(MutabilityOracle mutabilityOracle, Map<K, V> delegate) { 291 this.mutabilityOracle = mutabilityOracle; 292 this.delegate = delegate; 293 } 294 295 @Override size()296 public int size() { 297 return delegate.size(); 298 } 299 300 @Override isEmpty()301 public boolean isEmpty() { 302 return delegate.isEmpty(); 303 } 304 305 @Override containsKey(Object key)306 public boolean containsKey(Object key) { 307 return delegate.containsKey(key); 308 } 309 310 @Override containsValue(Object value)311 public boolean containsValue(Object value) { 312 return delegate.containsValue(value); 313 } 314 315 @Override get(Object key)316 public V get(Object key) { 317 return delegate.get(key); 318 } 319 320 @Override put(K key, V value)321 public V put(K key, V value) { 322 mutabilityOracle.ensureMutable(); 323 checkNotNull(key); 324 checkNotNull(value); 325 return delegate.put(key, value); 326 } 327 328 @Override remove(Object key)329 public V remove(Object key) { 330 mutabilityOracle.ensureMutable(); 331 return delegate.remove(key); 332 } 333 334 @Override putAll(Map<? extends K, ? extends V> m)335 public void putAll(Map<? extends K, ? extends V> m) { 336 mutabilityOracle.ensureMutable(); 337 for (K key : m.keySet()) { 338 checkNotNull(key); 339 checkNotNull(m.get(key)); 340 } 341 delegate.putAll(m); 342 } 343 344 @Override clear()345 public void clear() { 346 mutabilityOracle.ensureMutable(); 347 delegate.clear(); 348 } 349 350 @Override keySet()351 public Set<K> keySet() { 352 return new MutatabilityAwareSet<K>(mutabilityOracle, delegate.keySet()); 353 } 354 355 @Override values()356 public Collection<V> values() { 357 return new MutatabilityAwareCollection<V>(mutabilityOracle, delegate.values()); 358 } 359 360 @Override entrySet()361 public Set<java.util.Map.Entry<K, V>> entrySet() { 362 return new MutatabilityAwareSet<Entry<K, V>>(mutabilityOracle, delegate.entrySet()); 363 } 364 365 @Override equals(Object o)366 public boolean equals(Object o) { 367 return delegate.equals(o); 368 } 369 370 @Override hashCode()371 public int hashCode() { 372 return delegate.hashCode(); 373 } 374 375 @Override toString()376 public String toString() { 377 return delegate.toString(); 378 } 379 380 /** An internal collection that checks for mutability before delegating. */ 381 private static class MutatabilityAwareCollection<E> implements Collection<E> { 382 private final MutabilityOracle mutabilityOracle; 383 private final Collection<E> delegate; 384 MutatabilityAwareCollection(MutabilityOracle mutabilityOracle, Collection<E> delegate)385 MutatabilityAwareCollection(MutabilityOracle mutabilityOracle, Collection<E> delegate) { 386 this.mutabilityOracle = mutabilityOracle; 387 this.delegate = delegate; 388 } 389 390 @Override size()391 public int size() { 392 return delegate.size(); 393 } 394 395 @Override isEmpty()396 public boolean isEmpty() { 397 return delegate.isEmpty(); 398 } 399 400 @Override contains(Object o)401 public boolean contains(Object o) { 402 return delegate.contains(o); 403 } 404 405 @Override iterator()406 public Iterator<E> iterator() { 407 return new MutatabilityAwareIterator<E>(mutabilityOracle, delegate.iterator()); 408 } 409 410 @Override toArray()411 public Object[] toArray() { 412 return delegate.toArray(); 413 } 414 415 @Override toArray(T[] a)416 public <T> T[] toArray(T[] a) { 417 return delegate.toArray(a); 418 } 419 420 @Override add(E e)421 public boolean add(E e) { 422 // Unsupported operation in the delegate. 423 throw new UnsupportedOperationException(); 424 } 425 426 @Override remove(Object o)427 public boolean remove(Object o) { 428 mutabilityOracle.ensureMutable(); 429 return delegate.remove(o); 430 } 431 432 @Override containsAll(Collection<?> c)433 public boolean containsAll(Collection<?> c) { 434 return delegate.containsAll(c); 435 } 436 437 @Override addAll(Collection<? extends E> c)438 public boolean addAll(Collection<? extends E> c) { 439 // Unsupported operation in the delegate. 440 throw new UnsupportedOperationException(); 441 } 442 443 @Override removeAll(Collection<?> c)444 public boolean removeAll(Collection<?> c) { 445 mutabilityOracle.ensureMutable(); 446 return delegate.removeAll(c); 447 } 448 449 @Override retainAll(Collection<?> c)450 public boolean retainAll(Collection<?> c) { 451 mutabilityOracle.ensureMutable(); 452 return delegate.retainAll(c); 453 } 454 455 @Override clear()456 public void clear() { 457 mutabilityOracle.ensureMutable(); 458 delegate.clear(); 459 } 460 461 @Override equals(Object o)462 public boolean equals(Object o) { 463 return delegate.equals(o); 464 } 465 466 @Override hashCode()467 public int hashCode() { 468 return delegate.hashCode(); 469 } 470 471 @Override toString()472 public String toString() { 473 return delegate.toString(); 474 } 475 } 476 477 /** An internal set that checks for mutability before delegating. */ 478 private static class MutatabilityAwareSet<E> implements Set<E> { 479 private final MutabilityOracle mutabilityOracle; 480 private final Set<E> delegate; 481 MutatabilityAwareSet(MutabilityOracle mutabilityOracle, Set<E> delegate)482 MutatabilityAwareSet(MutabilityOracle mutabilityOracle, Set<E> delegate) { 483 this.mutabilityOracle = mutabilityOracle; 484 this.delegate = delegate; 485 } 486 487 @Override size()488 public int size() { 489 return delegate.size(); 490 } 491 492 @Override isEmpty()493 public boolean isEmpty() { 494 return delegate.isEmpty(); 495 } 496 497 @Override contains(Object o)498 public boolean contains(Object o) { 499 return delegate.contains(o); 500 } 501 502 @Override iterator()503 public Iterator<E> iterator() { 504 return new MutatabilityAwareIterator<E>(mutabilityOracle, delegate.iterator()); 505 } 506 507 @Override toArray()508 public Object[] toArray() { 509 return delegate.toArray(); 510 } 511 512 @Override toArray(T[] a)513 public <T> T[] toArray(T[] a) { 514 return delegate.toArray(a); 515 } 516 517 @Override add(E e)518 public boolean add(E e) { 519 mutabilityOracle.ensureMutable(); 520 return delegate.add(e); 521 } 522 523 @Override remove(Object o)524 public boolean remove(Object o) { 525 mutabilityOracle.ensureMutable(); 526 return delegate.remove(o); 527 } 528 529 @Override containsAll(Collection<?> c)530 public boolean containsAll(Collection<?> c) { 531 return delegate.containsAll(c); 532 } 533 534 @Override addAll(Collection<? extends E> c)535 public boolean addAll(Collection<? extends E> c) { 536 mutabilityOracle.ensureMutable(); 537 return delegate.addAll(c); 538 } 539 540 @Override retainAll(Collection<?> c)541 public boolean retainAll(Collection<?> c) { 542 mutabilityOracle.ensureMutable(); 543 return delegate.retainAll(c); 544 } 545 546 @Override removeAll(Collection<?> c)547 public boolean removeAll(Collection<?> c) { 548 mutabilityOracle.ensureMutable(); 549 return delegate.removeAll(c); 550 } 551 552 @Override clear()553 public void clear() { 554 mutabilityOracle.ensureMutable(); 555 delegate.clear(); 556 } 557 558 @Override equals(Object o)559 public boolean equals(Object o) { 560 return delegate.equals(o); 561 } 562 563 @Override hashCode()564 public int hashCode() { 565 return delegate.hashCode(); 566 } 567 568 @Override toString()569 public String toString() { 570 return delegate.toString(); 571 } 572 } 573 574 /** An internal iterator that checks for mutability before delegating. */ 575 private static class MutatabilityAwareIterator<E> implements Iterator<E> { 576 private final MutabilityOracle mutabilityOracle; 577 private final Iterator<E> delegate; 578 MutatabilityAwareIterator(MutabilityOracle mutabilityOracle, Iterator<E> delegate)579 MutatabilityAwareIterator(MutabilityOracle mutabilityOracle, Iterator<E> delegate) { 580 this.mutabilityOracle = mutabilityOracle; 581 this.delegate = delegate; 582 } 583 584 @Override hasNext()585 public boolean hasNext() { 586 return delegate.hasNext(); 587 } 588 589 @Override next()590 public E next() { 591 return delegate.next(); 592 } 593 594 @Override remove()595 public void remove() { 596 mutabilityOracle.ensureMutable(); 597 delegate.remove(); 598 } 599 600 @Override equals(Object obj)601 public boolean equals(Object obj) { 602 return delegate.equals(obj); 603 } 604 605 @Override hashCode()606 public int hashCode() { 607 return delegate.hashCode(); 608 } 609 610 @Override toString()611 public String toString() { 612 return delegate.toString(); 613 } 614 } 615 } 616 } 617