1/* 2 * Copyright (C) 2012 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.google.common.collect; 17 18import static com.google.common.base.Preconditions.checkArgument; 19 20import com.google.common.annotations.GwtCompatible; 21 22import java.io.Serializable; 23import java.util.EnumMap; 24import java.util.Iterator; 25 26import javax.annotation.Nullable; 27 28/** 29 * Implementation of {@link ImmutableMap} backed by a non-empty {@link 30 * java.util.EnumMap}. 31 * 32 * @author Louis Wasserman 33 */ 34@GwtCompatible(serializable = true, emulated = true) 35@SuppressWarnings("serial") // we're overriding default serialization 36final class ImmutableEnumMap<K extends Enum<K>, V> extends ImmutableMap<K, V> { 37 static <K extends Enum<K>, V> ImmutableMap<K, V> asImmutable(EnumMap<K, V> map) { 38 switch (map.size()) { 39 case 0: 40 return ImmutableMap.of(); 41 case 1: { 42 Entry<K, V> entry = Iterables.getOnlyElement(map.entrySet()); 43 return ImmutableMap.of(entry.getKey(), entry.getValue()); 44 } 45 default: 46 return new ImmutableEnumMap<K, V>(map); 47 } 48 } 49 50 private transient final EnumMap<K, V> delegate; 51 52 private ImmutableEnumMap(EnumMap<K, V> delegate) { 53 this.delegate = delegate; 54 checkArgument(!delegate.isEmpty()); 55 } 56 57 @Override 58 ImmutableSet<K> createKeySet() { 59 return new ImmutableSet<K>() { 60 61 @Override 62 public boolean contains(Object object) { 63 return delegate.containsKey(object); 64 } 65 66 @Override 67 public int size() { 68 return ImmutableEnumMap.this.size(); 69 } 70 71 @Override 72 public UnmodifiableIterator<K> iterator() { 73 return Iterators.unmodifiableIterator(delegate.keySet().iterator()); 74 } 75 76 @Override 77 boolean isPartialView() { 78 return true; 79 } 80 }; 81 } 82 83 @Override 84 public int size() { 85 return delegate.size(); 86 } 87 88 @Override 89 public boolean containsKey(@Nullable Object key) { 90 return delegate.containsKey(key); 91 } 92 93 @Override 94 public V get(Object key) { 95 return delegate.get(key); 96 } 97 98 @Override 99 ImmutableSet<Entry<K, V>> createEntrySet() { 100 return new ImmutableMapEntrySet<K, V>() { 101 102 @Override 103 ImmutableMap<K, V> map() { 104 return ImmutableEnumMap.this; 105 } 106 107 @Override 108 public UnmodifiableIterator<Entry<K, V>> iterator() { 109 return new UnmodifiableIterator<Entry<K, V>>() { 110 private final Iterator<Entry<K, V>> backingIterator = delegate.entrySet().iterator(); 111 112 @Override 113 public boolean hasNext() { 114 return backingIterator.hasNext(); 115 } 116 117 @Override 118 public Entry<K, V> next() { 119 Entry<K, V> entry = backingIterator.next(); 120 return Maps.immutableEntry(entry.getKey(), entry.getValue()); 121 } 122 }; 123 } 124 }; 125 } 126 127 @Override 128 boolean isPartialView() { 129 return false; 130 } 131 132 // All callers of the constructor are restricted to <K extends Enum<K>>. 133 @Override Object writeReplace() { 134 return new EnumSerializedForm<K, V>(delegate); 135 } 136 137 /* 138 * This class is used to serialize ImmutableEnumSet instances. 139 */ 140 private static class EnumSerializedForm<K extends Enum<K>, V> 141 implements Serializable { 142 final EnumMap<K, V> delegate; 143 EnumSerializedForm(EnumMap<K, V> delegate) { 144 this.delegate = delegate; 145 } 146 Object readResolve() { 147 return new ImmutableEnumMap<K, V>(delegate); 148 } 149 private static final long serialVersionUID = 0; 150 } 151} 152