"AssertionError: Already disposed" when opening project in the same frame
[idea/community.git] / platform / util / src / com / intellij / util / containers / FactoryMap.java
1 /*
2  * Copyright 2000-2013 JetBrains s.r.o.
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  */
16 package com.intellij.util.containers;
17
18 import com.intellij.util.ObjectUtils;
19 import gnu.trove.THashMap;
20 import org.jetbrains.annotations.NotNull;
21 import org.jetbrains.annotations.Nullable;
22
23 import java.util.*;
24
25 import static com.intellij.util.ObjectUtils.NULL;
26
27 /**
28  * @author peter
29  */
30 public abstract class FactoryMap<K,V> implements Map<K, V> {
31   protected Map<K,V> myMap;
32
33   protected Map<K, V> createMap() {
34     return new THashMap<K, V>();
35   }
36
37   @Nullable
38   protected abstract V create(K key);
39
40   private Map<K, V> getMap() {
41     if (myMap == null) {
42       myMap = createMap();
43     }
44     return myMap;
45   }
46   
47   @Override
48   public V get(Object key) {
49     final Map<K, V> map = getMap();
50     V value = map.get(getKey(key));
51     if (value == null) {
52       value = create((K)key);
53       map.put((K)getKey(key), value == null ? (V)NULL : value);
54     }
55     return value == NULL ? null : value;
56   }
57
58   private static <K> K getKey(final K key) {
59     return key == null ? (K)NULL : key;
60   }
61
62   @Override
63   public final boolean containsKey(Object key) {
64     return myMap != null && myMap.containsKey(getKey(key));
65   }
66
67   @Override
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;
71   }
72
73   @Override
74   public V remove(Object key) {
75     if (myMap == null) return null;
76     V v = myMap.remove(key);
77     return v == NULL ? null : v;
78   }
79
80   @NotNull
81   @Override
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);
87       hashSet.remove(NULL);
88       hashSet.add(null);
89       return hashSet;
90     }
91     return ts;
92   }
93
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) {
99         iterator.remove();
100       }
101     }
102     return values;
103   }
104
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);
109   }
110
111
112   @Override
113   public void clear() {
114     if (myMap != null) {
115       myMap.clear();
116     }
117   }
118
119   @Override
120   public int size() {
121     if (myMap == null) return 0;
122     return myMap.size();
123   }
124
125   @Override
126   public boolean isEmpty() {
127     return myMap == null || myMap.isEmpty();
128   }
129
130   @Override
131   public boolean containsValue(final Object value) {
132     return myMap != null && myMap.containsValue(value);
133   }
134
135   @Override
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());
139     }
140   }
141
142   @NotNull
143   @Override
144   public Collection<V> values() {
145     if (myMap == null) return Collections.emptyList();
146     return myMap.values();
147   }
148
149   @NotNull
150   @Override
151   public Set<Entry<K, V>> entrySet() {
152     if (myMap == null) return Collections.emptySet();
153     return myMap.entrySet();
154   }
155 }