2 * Copyright 2000-2013 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.util.containers;
18 import com.intellij.util.ObjectUtils;
19 import gnu.trove.THashMap;
20 import org.jetbrains.annotations.NotNull;
21 import org.jetbrains.annotations.Nullable;
25 import static com.intellij.util.ObjectUtils.NULL;
30 public abstract class FactoryMap<K,V> implements Map<K, V> {
31 protected Map<K,V> myMap;
33 protected Map<K, V> createMap() {
34 return new THashMap<K, V>();
38 protected abstract V create(K key);
40 private Map<K, V> getMap() {
48 public V get(Object key) {
49 final Map<K, V> map = getMap();
50 V value = map.get(getKey(key));
52 value = create((K)key);
53 map.put((K)getKey(key), value == null ? (V)NULL : value);
55 return value == NULL ? null : value;
58 private static <K> K getKey(final K key) {
59 return key == null ? (K)NULL : key;
63 public final boolean containsKey(Object key) {
64 return myMap != null && myMap.containsKey(getKey(key));
68 public V put(K key, V value) {
69 V v = getMap().put(getKey(key), value == null ? (V)NULL : value);
70 return v == NULL ? null : v;
74 public V remove(Object key) {
75 if (myMap == null) return null;
76 V v = myMap.remove(key);
77 return v == NULL ? null : v;
82 public Set<K> keySet() {
83 if (myMap == null) return Collections.emptySet();
84 final Set<K> ts = myMap.keySet();
85 if (ts.contains(NULL)) {
86 final HashSet<K> hashSet = new HashSet<K>(ts);
94 public Collection<V> notNullValues() {
95 if (myMap == null) return Collections.emptyList();
96 final Collection<V> values = ContainerUtil.newArrayList(myMap.values());
97 for (Iterator<V> iterator = values.iterator(); iterator.hasNext();) {
98 if (iterator.next() == NULL) {
105 public boolean removeValue(Object value) {
106 if (myMap == null) return false;
107 Object t = ObjectUtils.notNull(value, NULL);
108 return myMap.values().remove(t);
113 public void clear() {
121 if (myMap == null) return 0;
126 public boolean isEmpty() {
127 return myMap == null || myMap.isEmpty();
131 public boolean containsValue(final Object value) {
132 return myMap != null && myMap.containsValue(value);
136 public void putAll(@NotNull final Map<? extends K, ? extends V> m) {
137 for (Entry<? extends K, ? extends V> entry : m.entrySet()) {
138 put(entry.getKey(), entry.getValue());
144 public Collection<V> values() {
145 if (myMap == null) return Collections.emptyList();
146 return myMap.values();
151 public Set<Entry<K, V>> entrySet() {
152 if (myMap == null) return Collections.emptySet();
153 return myMap.entrySet();